Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
175 changes: 175 additions & 0 deletions .github/workflows/pr_testing_configure.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
---
name: 'PR Testing the configure task'

on:
push:
branches:
- main
pull_request:
branches:
- main

env:
# These openvox_bootstrap::configure parameters are used in both
# the agent and server task runs, but puppet_conf will vary.
COMMON_CONFIGURE_PARAMS: |-
"csr_attributes": {
"custom_attributes": {
"1.2.840.113549.1.9.7": "password"
},
"extension_requests": {
"pp_role": "tomato"
}
},
"puppet_service_running": true,
"puppet_service_enabled": false

jobs:
test-configure-task:
strategy:
matrix:
os:
- [almalinux, '9']
- [ubuntu, '24.04']
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- id: install-bolt
uses: ./.github/actions/bolt
with:
os-codename: jammy
- id: vm-cluster
uses: jpartlow/nested_vms@v1
with:
os: ${{ matrix.os[0] }}
os-version: ${{ matrix.os[1] }}
os-arch: ${{ matrix.os[2] || 'x86_64' }}
host-root-access: true
ruby-version: '3.3'
install-openvox: false
vms: |-
[
{
"role": "primary",
"cpus": 4,
"mem_mb": 8192,
"cpu_mode": "host-model"
},
{
"role": "agent",
"cpus": 2,
"mem_mb": 4096,
"cpu_mode": "host-model"
}
]
- name: Capture dereferenced inventory for use with openvox_bootstrap
working-directory: kvm_automation_tooling
run: |-
bolt inventory --inventory terraform/instances/inventory.test.yaml show --format json --detail | \
jq '.inventory | with_entries(select(.key == "targets")) | del(.targets[].groups)' | \
yq -P > ../inventory.yaml
cat ../inventory.yaml
- name: Install openvox
run: |-
bolt task run openvox_bootstrap::install --inventory inventory.yaml --targets test-primary-1,test-agent-1
- name: Install openvox-server
run: |-
bolt task run openvox_bootstrap::install --inventory inventory.yaml --targets test-primary-1 package=openvox-server
- name: Disable agents to prevent background service runs
run: |-
bolt command run '/opt/puppetlabs/bin/puppet agent --disable "OpenVox PR testing"' --inventory inventory.yaml --targets test-agent-1,test-primary-1
- name: Write server configure params
run: |-
cat > server-params.json <<EOF
{
"puppet_conf": {
"main": {
"server": "test-primary-1.vm"
},
"server": {
"autosign": "/etc/puppetlabs/puppet/sign.sh"
}
},
${COMMON_CONFIGURE_PARAMS}
}
EOF
cat server-params.json
- name: Run openvox_boostrap::configure task on the primary
run: |-
bolt task run openvox_bootstrap::configure --inventory inventory.yaml --targets test-primary-1 --params @server-params.json
- name: Configure openvox-server
env:
PUPPET_CONF: |-
SIGN_SH: |-
run: |-
cat > sign.sh <<'EOF'
#!/bin/bash
set -e
csr_pem=$(cat)
csr_text=$(openssl req -text <<<"$csr_pem")
password=$(awk -F: -e '/challengePassword/ { print $2 }' <<<"$csr_text")
[[ "${password}" == 'password' ]]
EOF
bolt file upload sign.sh /etc/puppetlabs/puppet/sign.sh --inventory inventory.yaml --targets test-primary-1

cat > standup.sh <<'EOF'
#! /bin/bash
set -e
set -x

chmod 750 /etc/puppetlabs/puppet/sign.sh
chown puppet:puppet /etc/puppetlabs/puppet/sign.sh

set +e
systemctl start puppetserver
if [ $? -ne 0 ]; then
cat /var/log/puppetlabs/puppetserver/puppetserver.log
exit 1
fi
EOF
bolt script run standup.sh --inventory inventory.yaml --targets test-primary-1 --stream
- name: Write agent configure params
run: |-
cat > agent-params.json <<EOF
{
"puppet_conf": {
"main": {
"server": "test-primary-1.vm"
}
},
${COMMON_CONFIGURE_PARAMS}
}
EOF
cat agent-params.json
- name: Run openvox_bootstrap::configure task on the agent
run: |-
bolt task run openvox_bootstrap::configure --inventory inventory.yaml --targets test-agent-1 --params @agent-params.json
- name: Validate agent run on the primary
run: |-
bolt command run '/opt/puppetlabs/bin/puppet agent --agent_disabled_lockfile=/tmp/not_locked.lock --test' --inventory inventory.yaml --targets test-primary-1 --stream
- name: Validate agent run on the agent
run: |-
bolt command run '/opt/puppetlabs/bin/puppet agent --agent_disabled_lockfile=/tmp/not_locked.lock --test' --inventory inventory.yaml --targets test-agent-1 --stream
- name: Validate certificate extensions
run: |-
cat > site.pp <<'EOF'
node default {
notify { "Trusted Facts":
message => $trusted,
}
if $trusted.dig('extensions', 'pp_role') != 'tomato' {
fail("Certificate extension 'pp_role' should be 'tomato'. trusted['extensions'] = ${trusted['extensions']}")
}
}
EOF
bolt file upload site.pp /etc/puppetlabs/code/environments/production/manifests/site.pp --inventory inventory.yaml --targets test-primary-1
bolt command run '/opt/puppetlabs/bin/puppet agent --agent_disabled_lockfile=/tmp/not_locked.lock --onetime --verbose --no-daemonize' --inventory inventory.yaml --targets test-primary-1,test-agent-1 --stream
- name: Validate service state
run: |-
cat > apply.sh <<'EOF'
set -e
/opt/puppetlabs/bin/puppet apply --test -e 'service { "puppet": ensure => running, enable => false }'
EOF
# Use script rather than bolt apply so that we trip if the
# apply produces changes and returns an exitcode of 2.
bolt script run apply.sh --inventory inventory.yaml --targets test-agent-1,test-primary-1 --stream
56 changes: 56 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,60 @@ bolt task run openvox_bootstrap::install_build_artifact \
--run-as root
```

### openvox_bootstrap::configure

The openvox_bootstrap::configure task can be used to provide very
basic initial configuration for the openvox agent.

It does not install the agent. Run openvox_bootstrap::install first.
Since the agent service is installed stopped, configuration can
be laid down before the first run begins the certificate request
process.

It provides the following support:

* laying down an initial puppet.conf (primary use case being to set
the [server] parameter to point to the openvox-server).
* creating a [csr_attributes.yaml] file for the agent to use when
generating a CSR for use with autosigning scripts and to provide
extension data to the generated certificate.
* ensuring the `puppet` service is in a preferred state.

NOTE: the csr_attributes.yaml will overwrite any pre-existing files,
but settings for puppet.conf will be merged into an existing file if
present.

With an example params.json file like this:

```json
{
"puppet_conf": {
"main": {
"server": "puppetserver.foo"
}
},
"csr_attributes": {
"custom_attributes": {
"1.2.840.113549.1.9.7": "password"
},
"extension_requests": {
"pp_role": "thing1"
}
},
"puppet_service_running": true,
"puppet_service_enabled": true
}
```

You can run the task like this:

```sh
bolt task run openvox_bootstrap::configure \
--targets <target> \
--params @params.json \
--run-as root
```

## Reference

See [REFERENCE.md](./REFERENCE.md) for the generated reference doc.
Expand Down Expand Up @@ -117,3 +171,5 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
[puppet_agent::install tasks]: https://github.com/puppetlabs/puppetlabs-puppet_agent/tree/main?tab=readme-ov-file#puppet_agentinstall
[apply_prep]: https://www.puppet.com/docs/bolt/latest/plan_functions#apply-prep
[puppet_library]: https://www.puppet.com/docs/bolt/latest/using_plugins#puppet-library-plugins
[server]: https://github.com/puppetlabs/puppet/blob/main/references/configuration.md#server
[csr_attributes.yaml]: https://help.puppet.com/core/current/Content/PuppetCore/config_file_csr_attributes.htm
81 changes: 81 additions & 0 deletions REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,61 @@

## Table of Contents

### Data types

* [`Openvox_bootstrap::Cer_short_names`](#Openvox_bootstrap--Cer_short_names): Certificate extension request short names. These are the allowed short names documented for Puppet(TM) extension requests per [csr_attributes
* [`Openvox_bootstrap::Csr_attributes`](#Openvox_bootstrap--Csr_attributes): [csr_attributes.yaml](https://help.puppet.com/core/current/Content/PuppetCore/config_file_csr_attributes.htm)
* [`Openvox_bootstrap::Ini_file`](#Openvox_bootstrap--Ini_file): Simple type for data to be transformed to an INI file format.
* [`Openvox_bootstrap::Oid`](#Openvox_bootstrap--Oid): Object Identifier per https://en.wikipedia.org/wiki/Object_identifier

### Tasks

* [`check`](#check): Check whether a Puppet(tm) implementation is installed. Optionally checks the version.
* [`configure`](#configure): Provides initial configuration for a freshly installed openvox-agent.
* [`install`](#install): Installs an openvox package. By default, this will be the latest openvox-agent from the latest collection.
* [`install_build_artifact`](#install_build_artifact): Downloads and installs a package directly from the openvox build artifact server.

## Data types

### <a name="Openvox_bootstrap--Cer_short_names"></a>`Openvox_bootstrap::Cer_short_names`

Certificate extension request short names.
These are the allowed short names documented for Puppet(TM)
extension requests per [csr_attributes.yaml](https://help.puppet.com/core/current/Content/PuppetCore/config_file_csr_attributes.htm)

Alias of `Enum['pp_uuid', 'pp_instance_id', 'pp_image_name', 'pp_preshared_key', 'pp_cost_center', 'pp_product', 'pp_project', 'pp_application', 'pp_service', 'pp_employee', 'pp_created_by', 'pp_environment', 'pp_role', 'pp_software_version', 'pp_department', 'pp_cluster', 'pp_provisioner', 'pp_region', 'pp_datacenter', 'pp_zone', 'pp_network', 'pp_securitypolicy', 'pp_cloudplatform', 'pp_apptier', 'pp_hostname', 'pp_authorization', 'pp_auth_role']`

### <a name="Openvox_bootstrap--Csr_attributes"></a>`Openvox_bootstrap::Csr_attributes`

[csr_attributes.yaml](https://help.puppet.com/core/current/Content/PuppetCore/config_file_csr_attributes.htm)

Alias of

```puppet
Struct[{
Optional['custom_attributes'] => Hash[
Openvox_bootstrap::Oid,
String
],
Optional['extension_requests'] => Hash[
Variant[Openvox_bootstrap::Oid,Openvox_bootstrap::Cer_short_names],
String
],
}]
```

### <a name="Openvox_bootstrap--Ini_file"></a>`Openvox_bootstrap::Ini_file`

Simple type for data to be transformed to an INI file format.

Alias of `Hash[String, Hash[String, String]]`

### <a name="Openvox_bootstrap--Oid"></a>`Openvox_bootstrap::Oid`

Object Identifier per https://en.wikipedia.org/wiki/Object_identifier

Alias of `Pattern[/\d+(\.\d+)*/]`

## Tasks

### <a name="check"></a>`check`
Expand All @@ -32,6 +81,38 @@ Data type: `Enum['eq', 'lt', 'le', 'gt', 'ge']`

Version comparison operator.

### <a name="configure"></a>`configure`

Provides initial configuration for a freshly installed openvox-agent.

**Supports noop?** false

#### Parameters

##### `puppet_conf`

Data type: `Optional[Openvox_bootstrap::Ini_file]`

Hash of puppet configuration settings to add to the puppet.conf ini file. These will be merged into the existing puppet.conf, if any.

##### `csr_attributes`

Data type: `Optional[Openvox_bootstrap::Csr_attributes]`

Hash of CSR attributes (custom_attributes and extension_requests) to write to the csr_attributes.yaml file. NOTE: This will completely overwrite any pre-existing csr_attributes.yaml.

##### `puppet_service_running`

Data type: `Boolean`

Whether the Puppet service should be running after this task completes. Defaults to true.

##### `puppet_service_enabled`

Data type: `Boolean`

Whether the Puppet service should be enabled to start on boot after this task completes. Defaults to true.

### <a name="install"></a>`install`

Installs an openvox package. By default, this will be the latest openvox-agent from the latest collection.
Expand Down
25 changes: 25 additions & 0 deletions lib/openvox_bootstrap/task.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# frozen_string_literal: true

require 'json'

module OpenvoxBootstrap
# Base class for openvox_bootstrap Ruby tasks.
class Task
# Run the task and print the result as JSON.
def self.run
params = JSON.parse($stdin.read)
raise(ArgumentError, <<~ERR) unless params.is_a?(Hash)
Expected a Hash, got #{params.class}: #{params.inspect}
ERR

params.transform_keys!(&:to_sym)
# Clean out empty params so that task defaults are used.
params.delete_if { |_, v| v.nil? || v == '' }

result = new.task(**params)
puts JSON.pretty_generate(result)

result
end
end
end
1 change: 1 addition & 0 deletions spec/bash_spec_helper.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# frozen_string_literal: true

require 'json'
require 'tmpdir'
require 'rspec'
require 'lib/bash_rspec'
Expand Down
Loading