{"id":15022609,"url":"https://github.com/puppetlabs/ca_extend","last_synced_at":"2025-09-30T06:31:11.194Z","repository":{"id":38362525,"uuid":"335722045","full_name":"puppetlabs/ca_extend","owner":"puppetlabs","description":null,"archived":false,"fork":true,"pushed_at":"2024-11-25T09:50:57.000Z","size":171,"stargazers_count":2,"open_issues_count":1,"forks_count":16,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-12-18T20:22:20.167Z","etag":null,"topics":["module","supported"],"latest_commit_sha":null,"homepage":null,"language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"mahesws/ca_extend","license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/puppetlabs.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":null,"support":null,"governance":null}},"created_at":"2021-02-03T18:45:26.000Z","updated_at":"2024-11-25T09:51:01.000Z","dependencies_parsed_at":"2023-02-19T10:45:46.305Z","dependency_job_id":null,"html_url":"https://github.com/puppetlabs/ca_extend","commit_stats":{"total_commits":117,"total_committers":20,"mean_commits":5.85,"dds":0.7863247863247863,"last_synced_commit":"de3999bf71f1c890cc90b78b0b4719c8a3c9a6bf"},"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/puppetlabs%2Fca_extend","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/puppetlabs%2Fca_extend/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/puppetlabs%2Fca_extend/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/puppetlabs%2Fca_extend/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/puppetlabs","download_url":"https://codeload.github.com/puppetlabs/ca_extend/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":234570384,"owners_count":18854156,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["module","supported"],"created_at":"2024-09-24T19:58:11.869Z","updated_at":"2025-09-30T06:31:05.875Z","avatar_url":"https://github.com/puppetlabs.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ca_extend\n\n#### Table of Contents\n\n1. [Overview](#overview)\n1. [Description - What the module does and why it is useful](#description)\n1. [Setup - The basics of getting started with this module](#setup)\n1. [Usage - Configuration options and additional functionality](#usage)\n1. [Reference - An under-the-hood peek at what the module is doing](#reference)\n1. [Development - Guide for contributing to the module](#How-to-Report-an-issue-or-contribute-to-the-module)\n\n## Overview\n\nThis module can extend a certificate authority (CA) that's about to expire or has already expired.\n\nA Puppet CA certificate is only valid for a finite time (a new installation of PE 2019.x / Puppet 6.x will create a 15 year CA, while earlier versions will create a 5 year CA; and upgrading does not extend the CA.), after which it expires.\nWhen a CA certificate expires, Puppet services will no longer accept any certificates signed by that CA, and your Puppet infrastructure will immediately stop working.\n\nIf your CA certificate is expiring soon (or it's already expired), you need to:\n\n* Generate a new CA certificate using the existing CA keypair.\n* Distribute the new CA certificate to agents.\n\nThis module can automate those tasks.\n\n## Description\n\nThis module is composed of Plans and Tasks to extend the expiration date of the CA certificate in Puppet Enterprise (and Puppet Open Source) and distribute that CA certificate to agents.\n\nNote that, with Puppet Open Source, if the CA certificate is only used by the Puppet CA and no other integrations, there is no further action to take after using the two Plans.\nHowever, if it is used for other integrations (such as SSL encrypted PuppetDB traffic) then those integrations will need to have their copy of the CA certificate updated.\nIf the CA certificate is stored in any keystores, those will also need to be updated.\n\nThe functionality of this module is composed into two Plans:\n\n*  `ca_extend::extend_ca_cert`\n    * Extend the CA certificate and configure the primary Puppet server, Replica, Compilers, and Postgres nodes to use that extended certificate.\n*  `ca_extend::upload_ca_cert`\n    * Distribute the CA certificate to agents using transport supported by Puppet Bolt, such as `ssh` and `winrm`.\n\nRegardless of whether the CA certificate is expired, the `extend_ca_cert` plan may be used to extend its expiration date in-place and configure the primary Puppet server and any Compilers to use it.\n\nAfter the CA certificate has been extended, there are three methods for distributing it to agents:\n\n1. Using the `ca_extend::upload_ca_cert` plan or another method to copy the CA certificate to agents.\n1. Manually deleting `ca.pem` on agents and letting them download that file as part of the next Puppet agent run. The agent will download that file only if it is absent, so it must be deleted to use this method.\n1. Using a Puppet file resource to manage `ca.pem`. _Note: This method is only possible if the CA certificate has not yet expired because Puppet communications depend upon a valid CA certificate._\n\nThere are also complementary tasks to check the expiration date of the CA certificate, agent certificates, and the CA CRL.\n\n* `ca_extend::check_ca_expiry`\n    * Checks if the CA certificate expires by a certain date. Defaults to three months from today.\n* `ca_extend::check_agent_expiry`\n    * Checks if any agent certificate expires by a certain date. Defaults to three months from today.\n*  `ca_extend::check_crl_expiry`\n    * Checks if the CA crl on the primary server has expired\n*  `ca_extend::crl_truncate`\n    * Will truncate and regenerate the CA CRL, this should only be run if the CRL is expired\n  \n** If the CA certificate is expiring or expired, you must extend it as soon as possible. **\n\n## Setup\n\nThis module requires [Puppet Bolt](https://puppet.com/docs/bolt/latest/bolt_installing.html) \u003e= 1.38.0 on either on the primary Puppet server or a workstation with connectivity to the primary.\n\nThe installation procedure will differ depending on the version of Bolt.  If possible, using Bolt \u003e= 3.0.0 is recommended.  For example, this will install the latest Bolt version on EL 7.\n\n```bash\nsudo rpm -Uvh https://yum.puppet.com/puppet-tools-release-el-7.noarch.rpm\nsudo yum install puppet-bolt\n```\n\nThe following two sections show how to install the module dependencies depending on the installed version of Bolt.\n\n### Bolt \u003e= 1.38.0 \u003c 3.0.0\n\nThe recommended procedure for these versions is to use a [Bolt Puppetfile](https://puppet.com/docs/bolt/latest/installing_tasks_from_the_forge.html#task-8928).\nFrom within a [Boltdir](https://puppet.com/docs/bolt/latest/bolt_project_directories.html#embedded-project-directory), specify this module and `puppetlabs-stdlib` as dependencies and run `bolt puppetfile install`.  For example:\n\n```bash\nmkdir -p ~/Boltdir\ncd ~/Boltdir\n\ncat \u003e\u003ePuppetfile \u003c\u003cEOF\nmod 'puppetlabs-stdlib'\n\nmod 'puppetlabs-ca_extend'\nEOF\n\nbolt puppetfile install\n```\n\n### Bolt \u003e= 3.0.0\n\nThe recommended procedure for these versions is to use a Bolt Project.  When creating a [Bolt project](https://puppet.com/docs/bolt/latest/bolt_project_directories.html#embedded-project-directory), specify this module and `puppetlabs-stdlib` as dependencies and initialize the project.  For example:\n\n```bash\nsudo rpm -Uvh https://yum.puppet.com/puppet-tools-release-el-7.noarch.rpm\nsudo yum install puppet-bolt\n```\n\nIf your primary Puppet server or workstation has internet access, the project can be initialized with the needed dependencies with the following:\n\n```bash\nmkdir ca_extend\ncd ca_extend\n\nbolt project init expiry --modules puppetlabs-stdlib,puppetlabs-ca_extend\n```\n\nOtherwise, if your primary Puppet server or workstation operates behind a proxy, initialize the project without the `--modules` option:\n\n```bash\nmkdir ca_extend\ncd ca_extend\n\nbolt project init expiry\n```\n\nThen edit your `bolt-project.yaml` to use the proxy according to the [documentation](https://puppet.com/docs/bolt/latest/bolt_installing_modules.html#install-modules-using-a-proxy).  Next, add the module dependencies to `bolt-project.yaml`:\n\n```yaml\n---\nname: expiry\nmodules:\n  - name: puppetlabs-stdlib\n  - name: puppetlabs-ca_extend\n\n```\n\nFinally, install the modules.\n\n```bash\nbolt module install\n```\n\nSee the \"Usage\" section for how to run the tasks and plans remotely or locally on the primary Puppet server.\n\n### Dependencies\n\n*  A [Puppet Bolt](https://puppet.com/docs/bolt/latest/bolt_installing.html) \u003e= 1.38.0\n*  [puppetlabs-stdlib](https://puppet.com/docs/bolt/latest/bolt_installing.html)\n*  A `base64` binary on the primary Puppet server which supports the `-w` flag\n*  `bash` \u003e= 4.0 on the primary Puppet server\n\n## Usage\n\n### Extend the CA using the ca_extend::extend_ca_cert plan\n\nFirst, check the expiration of the Puppet agent certificate by running the following command as root on the primary Puppet server:\n\n```bash\n/opt/puppetlabs/puppet/bin/openssl x509 -in \"$(/opt/puppetlabs/bin/puppet config print hostcert)\" -enddate -noout\n```\n\nIf, and only if, the `notAfter` date printed has already passed, then the primary Puppet server certificate has expired and must be cleaned up before the CA can be regenerated.  This can be accomplished by passing `regen_primary_cert=true` to the `ca_extend::extend_ca_cert` plan.\n\n\u003e Note: This plan will also run the `ca_extend::check_crl_cert` task and if the crl is expired, will automatically resolve the issue by running the `ca_extend::crl_truncate` task.\n\n```bash\nbolt plan run ca_extend::extend_ca_cert regen_primary_cert=true --targets \u003cprimary_fqdn\u003e replica=\u003creplica_fqdn\u003e compilers=\u003ccomma_separated_compiler_fqdns\u003e --run-as root\n```\n\nNote that if you are running `extend_ca_cert` locally on the primary Puppet server, you can avoid potential Bolt transport issues by specifying `--targets local://hostname`, e.g.\n\n```bash\nbolt plan run ca_extend::extend_ca_cert --targets local://hostname --run-as root\n```\n\n### Distribute `ca.pem` to agents \n\nNext, distribute `ca.pem` to agents using one of the three methods:\n\n#### 1. Using the ca_extend::upload_ca_cert Plan\n\nUsing the `ca_extend::upload_ca_cert` plan relies on using `ssh` and/or `winrm` transport methods. Use the `cert` parameter to specify the location of the updated CA cert on the primary server. For example, you may use `cert=$(puppet config print localcacert)`. Distribute the CA certificate to agent nodes specified in the `targets` parameter. Bolt defaults to using `ssh` transport, which in turn will use `~/.ssh/config` for options such as `username` and `private-key`. However, the `ca_extend::upload_ca_cert` plan works best with a Bolt [inventory file](https://puppet.com/docs/bolt/latest/inventory_file.html) to specify `targets`; this allows for simultaneous uploads to \\*nix and Windows agents. See the Bolt documentation for more information on configuring an inventory file and the `targets` parameter.\n\n```bash\nbolt plan run ca_extend::upload_ca_cert cert=\u003cpath_to_cert\u003e --targets \u003cTargetSpec\u003e\n```\n\nAs an alternative to using the `targets` parameter, you may specify targets for the `ca_extend::upload_ca_cert` plan by connecting Bolt to [PuppetDB](https://puppet.com/docs/bolt/latest/bolt_connect_puppetdb.html), after which the [--query](https://puppet.com/docs/bolt/latest/bolt_command_reference.html#command-options) parameter can be used. \n\nExample query for all agent nodes excluding puppetserver nodes because the `ca_extend::extend_ca_cert` plan already updates the primary's and compilers' copies of the CA certificate:\n\n```bash\nbolt plan run ca_extend::upload_ca_cert cert=\u003cpath_to_cert\u003e --query \"nodes[certname]{! certname in ['primaryfqdn', 'compiler1fqdn', 'compiler2fqdn']}\"\n```\n\n#### 2. Manually deleting `ca.pem` on agents and letting them download that file as part of the next Puppet agent run\n\nThe agent will download `ca.pem` only if it is absent, so it must be deleted to use this method. \n\nFor example, on an \\*nix agent node delete `ca.pem` by running:\n\n```bash\nrm $(puppet config print localcacert)\n```\n\nNext, run puppet so the agent will retreive `ca.pem`:\n\n```bash\npuppet agent -t\n```\n\n**Note:** If you are depending on agent nodes downloading `ca.pem` during a scheduled Puppet run rather than manually initiating a Puppet run with `puppet agent -t`, you may need to restart the `puppet` service on \\*nix nodes. This is because the Puppet agent daemon on \\*nix nodes could have previous CA content loaded into memory. \n\n#### 3. Using a Puppet file resource to manage `ca.pem`\n\n\nYou may add this code to the catalog received by your agent nodes; the code manages `ca.pem` on Windows and \\*nix nodes with the contents of `ca.pem` on the compiling server (primary server or compiler). The code will not work with a serverless approach such as `puppet apply`. _Note: This method is only possible if the CA certificate has not yet expired because Puppet communications depend upon a valid CA certificate._\n\n```\n  $localcacert = $facts['os']['family'] ? {\n    'windows' =\u003e 'C:\\ProgramData\\PuppetLabs\\puppet\\etc\\ssl\\certs\\ca.pem',\n    default   =\u003e '/etc/puppetlabs/puppet/ssl/certs/ca.pem'\n  }\n  file {$localcacert:\n    ensure  =\u003e file,\n    content =\u003e file($settings::localcacert),\n  }\n```\n\n### ca_extend::check_ca_expiry Task\n\nYou can use this task to check the CA cert expiry on the `primary` mainly but you can also use it to check that a remote \\*nix node's CA cert has been updated after using any means to distribute the new CA certificate.\n\n```bash\nbolt task run ca_extend::check_ca_expiry --targets \u003cTargetSpec\u003e\n```\n\n### ca_extend::check_agent_expiry Task\n\nYou can use this task to categorize all PE certs in a PE environment as part of a valid or expiring section based on a customizable date in the future (default 3 months from now). This task runs against a `primary` server and checks all certs under `/etc/puppetlabs/puppet/ssl/ca/signed` as the single source of truth for the PE environment and splits the certs between a valid section or expiring section.\n\n```bash\nbolt task run ca_extend::check_agent_expiry --targets local://hostname\n```\n\nAs such, the following output illustrates that all available certs in `/etc/puppetlabs/puppet/ssl/ca/signed` are valid and nothing is expiring in the next 3 months.\n\n```bash\n[root@pe-server-7a5b76-0 ca_extend]# bolt task run ca_extend::check_agent_expiry --targets local://hostname\nStarted on local://pe-server-7a5b76-0.us-west1-c.internal...\nFinished on local://pe-server-7a5b76-0.us-west1-c.internal:\n  {\n    \"valid\": [\n      {\n        \"console-cert.pem\": \"Jan 14 19:55:34 2024 GMT\"\n      },\n      {\n        \"critical-boom.delivery.puppetlabs.net.pem\": \"Apr 21 17:57:20 2027 GMT\"\n      },\n      {\n        \"irate-maple.delivery.puppetlabs.net.pem\": \"Apr 21 19:25:35 2027 GMT\"\n      }\n    ],\n    \"expired\": [\n\n    ]\n  }\n\nSuccessful on 1 target: local://pe-server-7a5b76-0.us-west1-c.internal\nRan on 1 target in 1.32 sec\n```\n\nSee `REFERENCE.md` for more detailed examples.\n\n## Reference\n\nPuppet's security is based on a PKI using X.509 certificates.\n\nThis module's `ca_extend::extend_ca_cert` plan creates a new self-signed CA certificate using the same keypair as the prior self-signed CA. The new CA has the same:\n\n* Keypair.\n* Subject.\n* Issuer.\n* X509v3 Subject Key Identifier (the fingerprint of the public key).\n\nThe new CA has a different:\n\n* Authority Key Identifier (just the serial number, since it's self-signed).\n* Validity period (the point of the whole exercise).\n* Signature (since we changed the serial number and validity period).\n\nSince Puppet's services (and other services that use Puppet's PKI) validate certificates by trusting a self-signed CA and comparing its public key to the Signatures and Authority Key Identifiers of the certificates it has issued,\nit's possible to issue a new self-signed CA certificate based on a prior keypair without invalidating any certificates issued by the old CA.\nOnce you've done that, it's just a matter of delivering the new CA certificate to every participant in the PKI.\n\n## How to Report an issue or contribute to the module\n\nIf you are a PE user and need support using this module or are encountering issues, our Support team would be happy to help you resolve your issue and help reproduce any bugs. Just raise a ticket on the [support portal](https://support.puppet.com/hc/en-us/requests/new).\n\nIf you have a reproducible bug or are a community user you can raise it directly on the Github issues page of the module [here.](https://github.com/puppetlabs/ca_extend/issues) We also welcome PR contributions to improve the module. Please see further details about contributing [here](https://puppet.com/docs/puppet/7.5/contributing.html#contributing_changes_to_module_repositories)\n\n\n---\n\n# Supporting Content\n\n### Articles\n\nThe [Support Knowledge base](https://support.puppet.com/hc/en-us) is a searchable repository for technical information and how-to guides for all Puppet products.\n\nThis Module has the following specific Article(s) available:\n\n1. [Check and fix the expiry date for your CA certificate in Puppet Enterprise](https://support.puppet.com/hc/en-us/articles/360022508353)\n\n\n### Videos\n\nThe [Support Video Playlist](https://youtube.com/playlist?list=PLV86BgbREluWKzzvVulR74HZzMl6SCh3S) is a resource of content generated by the support team\n\n   \n   ---\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpuppetlabs%2Fca_extend","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpuppetlabs%2Fca_extend","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpuppetlabs%2Fca_extend/lists"}