92 changes: 34 additions & 58 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,88 +1,64 @@

# ca_regen

Welcome to your new module. A short overview of the generated parts can be found in the PDK documentation at https://puppet.com/pdk/latest/pdk_generating_modules.html .

The README template below provides a starting point with details about what information to include in your README.
# ca_extend

#### Table of Contents

1. [Description](#description)
2. [Setup - The basics of getting started with ca_regen](#setup)
* [What ca_regen affects](#what-ca_regen-affects)
* [Setup requirements](#setup-requirements)
* [Beginning with ca_regen](#beginning-with-ca_regen)
2. [Setup - The basics of getting started with ca_extend](#setup)
3. [Usage - Configuration options and additional functionality](#usage)
4. [Limitations - OS compatibility, etc.](#limitations)
5. [Development - Guide for contributing to the module](#development)

## Description

Briefly tell users why they might want to use your module. Explain what your module does and what kind of problems users can solve with it.

This should be a fairly short description helps the user decide if your module is what they want.
A set of Plans and Tasks to extend the expiration date of the certificate for the certificate authority in Puppet Enterprise and distrubute the certificate to agent nodes.

## Setup
This module requires a [Bolt installation](https://puppet.com/docs/bolt/latest/bolt_installing.html) >= 1.8.0 on either a client machine or the Puppet master

### What ca_regen affects **OPTIONAL**

If it's obvious what your module touches, you can skip this section. For example, folks can probably figure out that your mysql_instance module affects their MySQL instances.
The recommended installation procedure for this module is to use a [Bolt Puppetfile](https://puppet.com/docs/bolt/latest/installing_tasks_from_the_forge.html#task-8928). From 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:

If there's more that they should know about, though, this is the place to mention:
```
~/Boltdir$ cat Puppetfile
mod 'puppetlabs-stdlib'
* Files, packages, services, or operations that the module will alter, impact, or execute.
* Dependencies that your module automatically installs.
* Warnings or other important notices.
mod 'm0dular/ca_extend',
git: 'git@github.com:m0dular/ca_extend.git'
### Setup Requirements **OPTIONAL**
~/Boltdir$ bolt puppetfile install
Successfully synced modules from /home/adrian/Boltdir/Puppetfile to /home/adrian/Boltdir/modules
```

If your module requires anything extra before setting up (pluginsync enabled, another module, etc.), mention it here.
## Dependencies

If your most recent release breaks compatibility or requires particular steps for upgrading, you might want to include an additional "Upgrading" section here.
* A [Bolt installation](https://puppet.com/docs/bolt/latest/bolt_installing.html) >= 1.8.0
* [puppetlabs-stdlib](https://puppet.com/docs/bolt/latest/bolt_installing.html) >= 3.2.0 < 6.0.0
* A `base64` binary on the master which supports the `-w` flag
* `bash` >= 4.0 on the master

### Beginning with ca_regen
## Configuration

The very basic steps needed for a user to get the module up and running. This can include setup steps, if necessary, or it can be an example of the most basic use of the module.
### Inventory

## Usage
This module works best with a Bolt [inventory file](https://puppet.com/docs/bolt/latest/inventory_file.html) to support simultaneous uploads to \*nix and Windows agents. See the Bolt documentation for how to configure the inventory. See the `REFERENCE.md` for a sample inventory file.

Include usage examples for common use cases in the **Usage** section. Show your users how to use your module to solve problems, and be sure to include code examples. Include three to five examples of the most important or common tasks a user can accomplish with your module. Show users how to accomplish more complex tasks that involve different types, classes, and functions working in tandem.
Alternatively, one can use an `ssh` config file if only using this protocol to connect to agents. Bolt defaults to using `ssh`, which in turn will use `~/.ssh/config` for options such as the username and identity file.

## Reference
### Connecting to PuppetDB

This section is deprecated. Instead, add reference information to your code as Puppet Strings comments, and then use Strings to generate a REFERENCE.md in your module. For details on how to add code comments and generate documentation with Strings, see the Puppet Strings [documentation](https://puppet.com/docs/puppet/latest/puppet_strings.html) and [style guide](https://puppet.com/docs/puppet/latest/puppet_strings_style.html)
Another convenient way to specify targets for the `ca_extend::upload_ca_cert` plan is by connecting Bolt to [PuppetDB](https://puppet.com/docs/bolt/latest/bolt_command_reference.html#command-options), after which the [--query](https://puppet.com/docs/bolt/latest/bolt_command_reference.html#command-options) can be used to specify a node list. See `REFERENCE.md` for an example.

If you aren't ready to use Strings yet, manually create a REFERENCE.md in the root of your module directory and list out each of your module's classes, defined types, facts, functions, Puppet tasks, task plans, and resource types and providers, along with the parameters for each.
## Usage

For each element (class, defined type, function, and so on), list:
The functionality of this module is divided into two main plans:

* The data type, if applicable.
* A description of what the element does.
* Valid values, if the data type doesn't make it obvious.
* Default value, if any.
* `ca_extend::extend_ca_cert` to extend the certificate and configure the master and any compile masters to use the new certificate
* `ca_extend::upload_ca_cert` to distribute the certificate to any number of agents. Any protocol supported by Bolt can be used, such as `ssh`, `winrm`, or `PCP`.

For example:
### Usage

```
### `pet::cat`
#### Parameters
##### `meow`
Enables vocalization in your cat. Valid options: 'string'.
Default: 'medium-loud'.
bolt plan run ca_extend::extend_ca_cert master=<master_fqdn> compile_masters=<comma_separated_compile_master_fqdns>
```

## Limitations

In the Limitations section, list any incompatibilities, known issues, or other warnings.

## Development

In the Development section, tell other users the ground rules for contributing to your project and how they should submit their work.

## Release Notes/Contributors/Etc. **Optional**

If you aren't using changelog, put your release notes here (though you should consider using changelog). You can also add any additional sections you feel are necessary or important to include here. Please use the `## ` header.
```
bolt plan run ca_extend::upload_ca_cert cert=<path_to_cert> --nodes <TargetSpec>
```
See `REFERENCE.md` for example commands
224 changes: 224 additions & 0 deletions REFERENCE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
# Reference

## Configuration

### ssh

By default, Bolt will assume the `ssh` transport and use `~/.ssh.config` for configuration options. Below is a sample `config` file and command.

```
Host pe-*
User centos
Port 22
PasswordAuthentication no
IdentityFile /home/adrian/.ssh/id_rsa-acceptance
IdentitiesOnly yes
LogLevel ERROR
```

```
$ bolt plan run ca_extend::upload_ca_cert cert=/tmp/tmp.CuWtz3dmfx --run-as root --nodes pe-201815-agent
{
"success": {
"pe-201815-agent": {
"_output": "Uploaded '/tmp/tmp.CuWtz3dmfx' to 'pe-201815-agent:/etc/puppetlabs/puppet/ssl/certs/ca.pem'"
}
}
}
```

### Inventory

See the [Bolt inventory](https://puppet.com/docs/bolt/latest/inventory_file.html) documentation for a full reference on how to use the inventory. Below is a sample inventory created using [bolt-inventory-pdb](https://puppet.com/docs/bolt/latest/inventory_file_generating.html) and example commands.

```
$ cat pdb.yaml
---
query: "inventory[certname] {}"
groups:
- name: windows
query: "inventory[certname] { facts.osfamily = 'windows' }"
config:
transport: winrm
winrm:
user: Administrator
password: foo
ssl: false
- name: linux
query: "inventory[certname] { facts.kernel = 'Linux' }"
config:
transport: ssh
ssh:
user: centos
private-key: ~/.ssh/id_rsa-acceptance
host-key-check: false
```

```
$ /opt/puppetlabs/bolt/bin/bolt-inventory-pdb pdb.yaml -o ~/.puppetlabs/bolt/inventory.yaml
```

```
$ cat ~/.puppetlabs/bolt/inventory.yaml
---
query: inventory[certname] {}
groups:
- name: windows
query: inventory[certname] { facts.osfamily = 'windows' }
config:
transport: winrm
winrm:
user: Administrator
password: foo
ssl: false
nodes:
- ljbkgu9t2x3ohqd.delivery.puppetlabs.net
- name: linux
query: inventory[certname] { facts.kernel = 'Linux' }
config:
transport: ssh
ssh:
user: centos
private-key: "~/.ssh/id_rsa-acceptance"
host-key-check: false
nodes:
- pe-201815-master.puppetdebug.vlan
- pe-201815-agent.platform9.puppet.net
- pe-201815-compile.platform9.puppet.net
nodes:
- ljbkgu9t2x3ohqd.delivery.puppetlabs.net
- pe-201815-master.puppetdebug.vlan
- pe-201815-agent.platform9.puppet.net
- pe-201815-compile.platform9.puppet.net
```

```
$ bolt command run hostname --nodes linux
Started on pe-201815-compile.platform9.puppet.net...
Started on pe-201815-master.puppetdebug.vlan...
Started on pe-201815-agent.platform9.puppet.net...
Finished on pe-201815-master.puppetdebug.vlan:
STDOUT:
pe-201815-master.puppetdebug.vlan
Finished on pe-201815-compile.platform9.puppet.net:
STDOUT:
pe-201815-compile
Finished on pe-201815-agent.platform9.puppet.net:
STDOUT:
pe-201815-agent
Successful on 3 nodes: pe-201815-master.puppetdebug.vlan,pe-201815-agent.platform9.puppet.net,pe-201815-compile.platform9.puppet.net
Ran on 3 nodes in 0.62 seconds
```

```
$ bolt command run hostname --nodes windows
Started on ljbkgu9t2x3ohqd.delivery.puppetlabs.net...
Finished on ljbkgu9t2x3ohqd.delivery.puppetlabs.net:
STDOUT:
ljbkgu9t2x3ohqd
Successful on 1 node: ljbkgu9t2x3ohqd.delivery.puppetlabs.net
Ran on 1 node in 0.70 seconds
```

## Plans

### `ca_extend::extend_ca_cert`

#### Arguments

* master - Fully qualified domain name of the master containing the certificate authority
* compile_masters - Comma separated list of fully qualified domain names of compile masters

#### Steps

* Runs the `service` task to stop the `puppet` and `pe-puppetserver` services on the master
* Runs the `ca_extend::extend_ca_cert` task to dump the new cert to a file and return the path to the file and a base64 encoded string of its contents
* Runs the `ca_extend::configure_master` task to backup the `ssl` directory to `/var/puppetlabs/backups`, copy the new cert into place, and configure the master to use the new cert
* Decodes the cert's contents and dump it to a temp file
* Uploads the new cert to any compile masters and configures them to use the new cert

#### Output

All steps in this plan are critical to extending the certificate, so the plan will fail if any step fails. The output consists of Bolt logging messages and any failures of the steps involved.

### Example

```
$ bolt plan run ca_extend::extend_ca_cert master=pe-201815-master compile_masters=pe-201815-compile --run-as root
Starting: plan ca_extend::extend_ca_cert
Starting: command 'echo "test" | base64 -w 0 - &>/dev/null' on localhost
Finished: command 'echo "test" | base64 -w 0 - &>/dev/null' with 0 failures in 0.0 sec
INFO: Stopping puppet and pe-puppetserver services on pe-201815-master
Starting: task service on pe-201815-master
Finished: task service with 0 failures in 0.85 sec
Starting: task service on pe-201815-master
Finished: task service with 0 failures in 1.95 sec
INFO: Extending certificate on master pe-201815-master
Starting: task ca_extend::extend_ca_cert on pe-201815-master
Finished: task ca_extend::extend_ca_cert with 0 failures in 2.92 sec
INFO: Configuring master pe-201815-master to use new certificate
Starting: task ca_extend::configure_master on pe-201815-master
Finished: task ca_extend::configure_master with 0 failures in 95.72 sec
Starting: task service on pe-201815-master
Finished: task service with 0 failures in 1.64 sec
INFO: Configuring compile master(s) pe-201815-compile to use new certificate
Starting: file upload from /tmp/tmp.CuWtz3dmfx to /etc/puppetlabs/puppet/ssl/certs/ca.pem on pe-201815-compile
Finished: file upload from /tmp/tmp.CuWtz3dmfx to /etc/puppetlabs/puppet/ssl/certs/ca.pem with 0 failures in 0.59 sec
Starting: task run_agent on pe-201815-compile
Finished: task run_agent with 0 failures in 44.34 sec
INFO: CA cert decoded and stored at /tmp/tmp.CuWtz3dmfx
INFO: Run plan 'ca_extend::upload_ca_cert' to distribute to agents
Finished: plan ca_extend::extend_ca_cert in 148.06 sec
```

### `ca_extend::upload_ca_cert`

#### Arguments

* cert - Location of the new certificate on disk.

This plan accepts any valid TargetSpec(s) specified by the `--nodes` option.

#### Steps

* Collects facts from agents and separates them into groups of \*nix and Windows
* Runs `upload_file` on each list of agents to distribute the cert
* Constructs a JSON formatted object of the results of the uploads and returns it

#### Output

The output of this plan is a JSON object with two keys: `success` and `failure`. Each key contains any number of objects consisting of the agent certname and the output of the `upload_file` command.

```
$ bolt plan run ca_extend::upload_ca_cert cert=/tmp/tmp.CuWtz3dmfx --run-as root --query 'inventory { }'
Starting: plan ca_extend::upload_ca_cert
Starting: plan ca_extend::get_agent_facts
Starting: install puppet and gather facts on pe-201815-agent.platform9.puppet.net, ljbkgu9t2x3ohqd.delivery.puppetlabs.net, pe-201815-master.puppetdebug.vlan, pe-201815-compile.platform9.puppet.net
Finished: install puppet and gather facts with 0 failures in 9.33 sec
Finished: plan ca_extend::get_agent_facts in 9.33 sec
Starting: plan facts
Starting: task facts on pe-201815-agent.platform9.puppet.net, ljbkgu9t2x3ohqd.delivery.puppetlabs.net, pe-201815-master.puppetdebug.vlan, pe-201815-compile.platform9.puppet.net
Finished: task facts with 0 failures in 6.27 sec
Finished: plan facts in 6.31 sec
Starting: file upload from /tmp/tmp.CuWtz3dmfx to C:\ProgramData\PuppetLabs\puppet\etc\ssl\certs\ca.pem on ljbkgu9t2x3ohqd.delivery.puppetlabs.net
Finished: file upload from /tmp/tmp.CuWtz3dmfx to C:\ProgramData\PuppetLabs\puppet\etc\ssl\certs\ca.pem with 0 failures in 1.07 sec
Starting: file upload from /tmp/tmp.CuWtz3dmfx to /etc/puppetlabs/puppet/ssl/certs/ca.pem on pe-201815-agent.platform9.puppet.net, pe-201815-master.puppetdebug.vlan, pe-201815-compile.platform9.puppet.net
Finished: file upload from /tmp/tmp.CuWtz3dmfx to /etc/puppetlabs/puppet/ssl/certs/ca.pem with 0 failures in 0.66 sec
Finished: plan ca_extend::upload_ca_cert in 17.41 sec
{
"success": {
"pe-201815-agent.platform9.puppet.net": {
"_output": "Uploaded '/tmp/tmp.CuWtz3dmfx' to 'pe-201815-agent.platform9.puppet.net:/etc/puppetlabs/puppet/ssl/certs/ca.pem'"
},
"pe-201815-master.puppetdebug.vlan": {
"_output": "Uploaded '/tmp/tmp.CuWtz3dmfx' to 'pe-201815-master.puppetdebug.vlan:/etc/puppetlabs/puppet/ssl/certs/ca.pem'"
},
"pe-201815-compile.platform9.puppet.net": {
"_output": "Uploaded '/tmp/tmp.CuWtz3dmfx' to 'pe-201815-compile.platform9.puppet.net:/etc/puppetlabs/puppet/ssl/certs/ca.pem'"
},
"ljbkgu9t2x3ohqd.delivery.puppetlabs.net": {
"_output": "Uploaded '/tmp/tmp.CuWtz3dmfx' to 'ljbkgu9t2x3ohqd.delivery.puppetlabs.net:C:\\ProgramData\\PuppetLabs\\puppet\\etc\\ssl\\certs\\ca.pem'"
}
}
}
```
12 changes: 3 additions & 9 deletions files/common.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ fail() {
# Print a stderr: entry if there were anything printed to stderr
if [[ -s $_tmp ]]; then
# Hack to try and output valid json by replacing newlines with spaces.
echo "{ \"$1\": {\"status\": \"error\", \"message\": \"$2\", \"stderr\": \"$(tr '\n' ' ' <$_tmp)\" } }"
echo "{ \"status\": \"error\", \"message\": \"$1\", \"stderr\": \"$(tr '\n' ' ' <$_tmp)\" }"
else
echo "{ \"$1\": {\"status\": \"error\", \"message\": \"$2\" } }"
echo "{ \"status\": \"error\", \"message\": \"$1\" }"
fi

exit ${2:-1}
Expand All @@ -20,13 +20,6 @@ success() {
exit 0
}

# Any temp files stored in variables prefixed by "_tmp" will be removed on exit
cleanup() {
for f in ${!_tmp*}; do rm "${!f}"; done
}

#trap 'cleanup' INT TERM

# Test for colors. If unavailable, unset variables are ok
if tput colors &>/dev/null; then
green="$(tput setaf 2)"
Expand All @@ -35,6 +28,7 @@ if tput colors &>/dev/null; then
fi

_tmp="$(mktemp)"
exec 2>>"$_tmp"

# Use indirection to munge PT_ environment variables
# e.g. "$PT_version" becomes "$version"
Expand Down
2 changes: 2 additions & 0 deletions files/regen.sh → files/extend.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#!/bin/bash

# Credit: https://github.com/Sharpie

set -e

PUPPET_BIN='/opt/puppetlabs/puppet/bin'
Expand Down
Loading