cem_acpt 0.10.10 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +8 -0
  3. data/.worktreeinclude +1 -0
  4. data/CLAUDE.md +126 -0
  5. data/Gemfile.lock +3 -1
  6. data/README.md +20 -7
  7. data/cem_acpt.gemspec +1 -0
  8. data/docs/ARCHITECTURE.md +1042 -0
  9. data/docs/rfcs/0000-template.md +54 -0
  10. data/docs/rfcs/0001-fix-bolt-missing-skip-path.md +105 -0
  11. data/docs/rfcs/0002-fix-default-character-substitutions.md +119 -0
  12. data/docs/rfcs/0003-windows-image-builder-template.md +110 -0
  13. data/docs/rfcs/0004-image-name-truncation-off-by-one.md +108 -0
  14. data/docs/rfcs/0005-os-dispatch-replace-windows-heuristic.md +117 -0
  15. data/docs/rfcs/0006-configurable-windows-bucket.md +96 -0
  16. data/docs/rfcs/0007-logging-quiet-and-typos.md +121 -0
  17. data/docs/rfcs/0008-namespace-platform-classes.md +110 -0
  18. data/docs/rfcs/0009-bolt-log-formatter-cleanup.md +111 -0
  19. data/docs/rfcs/0010-dead-code-cleanup.md +83 -0
  20. data/docs/rfcs/0011-provisioner-factory-consistency.md +89 -0
  21. data/docs/rfcs/README.md +34 -0
  22. data/exe/cem_acpt +1 -0
  23. data/exe/cem_acpt_image +1 -0
  24. data/lib/cem_acpt/cli.rb +35 -7
  25. data/lib/cem_acpt/config/base.rb +105 -30
  26. data/lib/cem_acpt/config/cem_acpt.rb +5 -2
  27. data/lib/cem_acpt/config/cem_acpt_image.rb +8 -0
  28. data/lib/cem_acpt/image_builder/errors.rb +24 -0
  29. data/lib/cem_acpt/image_builder/provision_commands.rb +4 -6
  30. data/lib/cem_acpt/image_builder.rb +58 -10
  31. data/lib/cem_acpt/image_name_builder.rb +8 -1
  32. data/lib/cem_acpt/platform/gcp.rb +101 -56
  33. data/lib/cem_acpt/platform.rb +22 -19
  34. data/lib/cem_acpt/provision/terraform/linux.rb +1 -1
  35. data/lib/cem_acpt/provision/terraform/os_data.rb +24 -1
  36. data/lib/cem_acpt/provision/terraform/windows.rb +7 -1
  37. data/lib/cem_acpt/provision/terraform.rb +39 -20
  38. data/lib/cem_acpt/test_runner/log_formatter/bolt_summary_results_formatter.rb +2 -1
  39. data/lib/cem_acpt/test_runner/log_formatter.rb +0 -1
  40. data/lib/cem_acpt/test_runner.rb +30 -9
  41. data/lib/cem_acpt/utils/winrm_runner.rb +4 -3
  42. data/lib/cem_acpt/utils.rb +0 -12
  43. data/lib/cem_acpt/version.rb +1 -1
  44. data/lib/cem_acpt.rb +19 -7
  45. data/lib/terraform/gcp/linux/main.tf +145 -145
  46. data/lib/terraform/gcp/windows/main.tf +64 -64
  47. data/lib/terraform/image/gcp/linux/main.tf +84 -76
  48. data/specifications/CEM-6713.md +165 -0
  49. data/specifications/CEM-6714.md +271 -0
  50. data/specifications/CEM-6715.md +133 -0
  51. data/specifications/CEM-6716.md +160 -0
  52. data/specifications/CEM-6717.md +239 -0
  53. data/specifications/CEM-6718.md +120 -0
  54. data/specifications/CEM-6719.md +173 -0
  55. metadata +47 -10
  56. data/lib/cem_acpt/action_result.rb +0 -91
  57. data/lib/cem_acpt/puppet_helpers.rb +0 -38
  58. data/lib/cem_acpt/test_runner/log_formatter/bolt_error_formatter.rb +0 -65
  59. data/lib/cem_acpt/test_runner/log_formatter/bolt_output_formatter.rb +0 -54
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b957ec32b61b81b89e9fdf3961a0dcdf80030835434a6a9be34c9d57c94e761f
4
- data.tar.gz: f73b5bff3f0cbedeca09bc50b607a368a9e4f9bb31dfedde2377782ef73d23e5
3
+ metadata.gz: df61aa1c290a076e460b4c790babb19d0e0729e7d543feb96a9fb40e1589e50a
4
+ data.tar.gz: 800a652e59491e42f0e3fdd43db93e397956309e2b575d33e0f2c1497ebd8311
5
5
  SHA512:
6
- metadata.gz: 60a7e8efb5e618f05bee99a9ce88db85ccc98e5b35ed35272ee8dae0ff8824ef8c83470e854e4d1ccccac65453a37e58bc29da57dbc61e357176f7dd4dd45e38
7
- data.tar.gz: fd4c65392b90be5d35194ba990d8ada0f222721382a4fd6ee40b2f3c346f1f475dedbb9896495e70a2b2e07dcfa7890a3535c5fc34b5ea5c369b256cb65d06a2
6
+ metadata.gz: a4a93419e474a066291ead08cbb28222f635f218b3df394b92f8c23d2fc1d63d55b9c5e240229c86db22a7b98e0e8673a5f13c7d02bd0d3633976942cc22be08
7
+ data.tar.gz: 614ecdad289b17a01ffcaea724aa928372cf578a4270f641e592549a6f2d017235646fe5ab8b3274e23801755935b6d7e17cdd39072aee28cbc7692b86e5b663
data/.gitignore CHANGED
@@ -16,3 +16,11 @@ profile.txt
16
16
 
17
17
  # local dev
18
18
  run_script.rb
19
+
20
+ # Ignore .env files which may contain sensitive information
21
+ .env
22
+ .env.*.local
23
+
24
+ # Local Claude configuration
25
+ .claude/settings.local.json
26
+ .claude/worktrees/
data/.worktreeinclude ADDED
@@ -0,0 +1 @@
1
+ .env
data/CLAUDE.md ADDED
@@ -0,0 +1,126 @@
1
+ # CLAUDE.md
2
+
3
+ ## What This Project Is
4
+
5
+ `cem_acpt` is a Ruby gem providing an acceptance testing CLI for Puppet SCE (Security Compliance Enforcement, formerly Puppet CEM / Compliance Enforcement Modules). It provisions cloud nodes via Terraform, applies a Puppet manifest, runs infrastructure tests via Goss (and optionally Bolt task/plan tests), then tears everything down. Both Linux nodes (over SSH) and Windows nodes (over WinRM) are supported.
6
+
7
+ A second binary, `cem_acpt_image`, builds the base VM images used by the test runner.
8
+
9
+ The gem name is intentionally unchanged after the CEM → SCE rename. The consuming Puppet modules were renamed to `sce_linux` / `sce_windows`, but this gem stays `cem_acpt`.
10
+
11
+ ## Where to Read More
12
+
13
+ Before diving into the summary below, skim:
14
+ - `docs/ARCHITECTURE.md` — fuller architecture writeup
15
+ - `docs/rfcs/` — design decisions (Windows image builder, OS dispatch, platform namespacing, logging behavior, etc.). Check here before proposing structural changes.
16
+
17
+ ## Commands
18
+
19
+ ```bash
20
+ bundle install # Install dependencies
21
+
22
+ bundle exec rake spec # Run all spec tests
23
+ bundle exec rake spec SPEC=spec/path/to/file_spec.rb # Run a single spec file
24
+
25
+ rubocop # Lint
26
+ rubocop -a # Auto-fix lint issues
27
+
28
+ bundle exec rake build # Build the gem (saves to pkg/cem_acpt-<semver>.gem)
29
+ bundle exec gem install pkg/cem_acpt-X.X.X.gem # Install built gem
30
+
31
+ bundle exec exe/cem_acpt -h # CLI help
32
+ bundle exec exe/cem_acpt -Y # Print merged config as YAML
33
+ bundle exec exe/cem_acpt -X # Explain config merge sources
34
+ ```
35
+
36
+ CI runs `bundle exec rake spec` on PRs against `main` (see `.github/workflows/spec.yml`). Lint is not currently gated in CI, but RuboCop should be clean before merging.
37
+
38
+ RuboCop targets Ruby 3.2 with a 200-char line limit. The config in `.rubocop.yml` is intentionally permissive — many cops (complexity, layout, style) are disabled. Check `.rubocop.yml` before assuming a rule is enforced.
39
+
40
+ ## Architecture
41
+
42
+ ### Entry Points
43
+
44
+ - `exe/cem_acpt` and `exe/cem_acpt_image` both call into `CemAcpt.run` in `lib/cem_acpt.rb`, which dispatches on the command:
45
+ - `:cem_acpt` → `TestRunner::Runner`
46
+ - `:cem_acpt_image` → `ImageBuilder::TerraformBuilder`
47
+ - `:print_yaml_config` / `:print_explain_config` → handle the `-Y` / `-X` debugging flags
48
+ - `:version` → prints gem version
49
+ - CLI parsing lives in `lib/cem_acpt/cli.rb` (Ruby `OptionParser`).
50
+
51
+ ### Configuration System (`lib/cem_acpt/config/`)
52
+
53
+ Config is built by merging four sources, with each later source overriding earlier ones:
54
+
55
+ 1. Environment variables (`CEM_ACPT_` prefix; nested keys use `__`)
56
+ 2. User config at `~/.cem_acpt/config.yaml`
57
+ 3. `--config FILE` option
58
+ 4. Other CLI flags
59
+
60
+ `Config::Base` handles the merge via `deep_merge`. `Config::CemAcpt` and `Config::CemAcptImage` define the schema for each command. Use `-Y` to print the merged result and `-X` to see which source contributed each value.
61
+
62
+ ### Test Runner Lifecycle (`lib/cem_acpt/test_runner.rb`)
63
+
64
+ 1. **Pre-provision** — Build the Puppet module tarball (`Utils::Puppet`).
65
+ 2. **Provision** — Spin up nodes via the configured platform (currently only GCP) using Terraform (`Provision::Terraform`), generate ephemeral SSH keys (or set up WinRM for Windows), and install the module.
66
+ 3. **Execute** — Run action groups: `:goss` (async, HTTP) and `:bolt` (sync, Puppet tasks). Filter with `--only-actions` / `--except-actions`.
67
+ 4. **Cleanup** — `terraform destroy` unless `--no-destroy-nodes`.
68
+
69
+ ### Platform Abstraction (`lib/cem_acpt/platform/`)
70
+
71
+ `Platform::Base` defines the interface; `Platform::TestBase` extends it for test-node platforms. `Platform::Gcp` is the only concrete implementation today, but platforms are loaded dynamically by name from config — so adding e.g. AWS means a new file here plus a Terraform tree under `lib/terraform/`.
72
+
73
+ ### Actions (`lib/cem_acpt/actions.rb`)
74
+
75
+ The `Actions` class orchestrates test execution. Actions register themselves via `register_action`/`register_group` and run in `order` order. Goss actions run asynchronously via `async-http`; Bolt actions run synchronously.
76
+
77
+ ### Transports
78
+
79
+ - **SSH** (`lib/cem_acpt/utils/ssh.rb`) — Linux nodes
80
+ - **WinRM** (`lib/cem_acpt/utils/winrm_runner.rb`) — Windows nodes
81
+ - **Goss HTTP API** (`lib/cem_acpt/goss/api.rb`) — assertions, on a port exposed by the provisioned node
82
+
83
+ ### Terraform Templates (`lib/terraform/`)
84
+
85
+ Terraform HCL ships inside the gem:
86
+ - `lib/terraform/gcp/linux/` and `lib/terraform/gcp/windows/` — test-node provisioning
87
+ - `lib/terraform/image/gcp/linux/` and `lib/terraform/image/gcp/windows/` — image-building provisioning
88
+
89
+ ### Logging (`lib/cem_acpt/logging/`)
90
+
91
+ Supports simultaneous STDOUT + file logging. `-I` / `--CI` enables GitHub Actions–formatted output. `--trace` enables Ruby `TracePoint` debugging. Most subsystems include `CemAcpt::Logging` to get a `logger` method.
92
+
93
+ ## Where to Add Things
94
+
95
+ | Adding… | Touch |
96
+ | ----------------------------- | ---------------------------------------------------------------------------------------------- |
97
+ | A new platform (e.g. AWS) | `lib/cem_acpt/platform/<name>.rb` (subclass `Platform::TestBase`) + `lib/terraform/<name>/...` |
98
+ | A new action group | Register in `lib/cem_acpt/actions.rb`; add a subdir under `lib/cem_acpt/<group>/` |
99
+ | A new config option | Add to `lib/cem_acpt/config/cem_acpt.rb` (or `cem_acpt_image.rb`) and wire into `cli.rb` |
100
+ | A new Bolt helper | `lib/cem_acpt/bolt/` — see `inventory.rb`, `tasks.rb`, `tests.rb` for the existing pattern |
101
+ | A new utility (SSH/WinRM/etc) | `lib/cem_acpt/utils/` |
102
+
103
+ ## Test Structure
104
+
105
+ ### Unit tests (this repo)
106
+
107
+ Specs live under `spec/`, mirroring the layout of `lib/`. Fixtures live in `spec/fixtures/`. Run with `bundle exec rake spec`.
108
+
109
+ ### Acceptance tests (consuming module)
110
+
111
+ Acceptance test cases live in the **consuming module** (e.g. `sce_linux`, `sce_windows`), not in this gem. They follow this layout:
112
+
113
+ ```
114
+ spec/acceptance/<framework>_<os>-<version>_<firewall>_<profile>_<level>/
115
+ manifest.pp # Puppet manifest to apply
116
+ goss.yaml # Goss assertions
117
+ bolt.yaml # (optional) Bolt task assertions
118
+ ```
119
+
120
+ ## Conventions
121
+
122
+ - Document Ruby code with YARD comments.
123
+ - All changes should have tests.
124
+ - Subsystem-specific error classes live alongside the subsystem (e.g. `lib/cem_acpt/bolt/errors.rb`); follow that pattern rather than reusing generic `StandardError`.
125
+ - Use `CemAcpt::Utils::FinalizerQueue` for ordered cleanup of provisioned resources rather than ad-hoc `ensure` blocks.
126
+ - Mix in `CemAcpt::Logging` to get a logger; don't instantiate one directly.
data/Gemfile.lock CHANGED
@@ -1,10 +1,11 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cem_acpt (0.10.10)
4
+ cem_acpt (0.11.1)
5
5
  async-http (>= 0.60, < 0.70)
6
6
  bcrypt_pbkdf (>= 1.0, < 2.0)
7
7
  deep_merge (>= 1.2, < 2.0)
8
+ dotenv (>= 3.2, < 4.0)
8
9
  ed25519 (>= 1.0, < 2.0)
9
10
  puppet-modulebuilder (>= 0.0.1)
10
11
  winrm (>= 2.3, < 3.0)
@@ -44,6 +45,7 @@ GEM
44
45
  deep_merge (1.2.2)
45
46
  diff-lcs (1.6.1)
46
47
  docile (1.4.1)
48
+ dotenv (3.2.0)
47
49
  ed25519 (1.3.0)
48
50
  erubi (1.13.1)
49
51
  ffi (1.17.1)
data/README.md CHANGED
@@ -16,7 +16,7 @@ gem install cem_acpt
16
16
 
17
17
  ### Quickstart
18
18
 
19
- Make sure Terraform and the gcloud CLI are installed and in your PATH. Instructions for installing Terraform can be found [here](https://learn.hashicorp.com/tutorials/terraform/install-cli) and instructions for installing the gcloud CLI can be found [here](https://cloud.google.com/sdk/docs/install).Then, navigate to the root of the `cem_linux` module and run the following command:
19
+ Make sure Terraform and the gcloud CLI are installed and in your PATH. Instructions for installing Terraform can be found [here](https://learn.hashicorp.com/tutorials/terraform/install-cli) and instructions for installing the gcloud CLI can be found [here](https://cloud.google.com/sdk/docs/install).Then, navigate to the root of the `sce_linux` module and run the following command:
20
20
 
21
21
  ```bash
22
22
  cem_acpt --config ./cem_acpt_config.yaml
@@ -140,7 +140,7 @@ All Bolt tasks are ran with the `--format json` flag, which returns a JSON docum
140
140
 
141
141
  Example:
142
142
 
143
- In this example, we will go over how a Bolt task's output would be evaluated by a Bolt test hash. This example assumes one Bolt task named `cem_linux::audit_sssd_certmap` that takes no parameters was ran successfully against two nodes.
143
+ In this example, we will go over how a Bolt task's output would be evaluated by a Bolt test hash. This example assumes one Bolt task named `sce_linux::audit_sssd_certmap` that takes no parameters was ran successfully against two nodes.
144
144
 
145
145
  Bolt task JSON output:
146
146
 
@@ -150,7 +150,7 @@ Bolt task JSON output:
150
150
  {
151
151
  "target":"35.212.146.14",
152
152
  "action":"task",
153
- "object":"cem_linux::audit_sssd_certmap",
153
+ "object":"sce_linux::audit_sssd_certmap",
154
154
  "status":"success",
155
155
  "value":{
156
156
  "sssd_certmap_exists":false
@@ -159,7 +159,7 @@ Bolt task JSON output:
159
159
  {
160
160
  "target":"35.212.197.53",
161
161
  "action":"task",
162
- "object":"cem_linux::audit_sssd_certmap",
162
+ "object":"sce_linux::audit_sssd_certmap",
163
163
  "status":"success",
164
164
  "value":{
165
165
  "sssd_certmap_exists":false
@@ -174,7 +174,7 @@ Bolt task JSON output:
174
174
  Bolt test hash in `bolt.yaml`:
175
175
 
176
176
  ```yaml
177
- 'cem_linux::audit_sssd_certmap':
177
+ 'sce_linux::audit_sssd_certmap':
178
178
  status: 'success'
179
179
  value:
180
180
  match: 'false'
@@ -335,6 +335,19 @@ images:
335
335
 
336
336
  See [sample_config.yaml](sample_config.yaml) for a more complete example.
337
337
 
338
- ### Testing with cem_windows
338
+ ### Testing with sce_windows
339
339
 
340
- While testing with cem_windows follows pretty much the same outline as cem_linux, there are a few extra step that we have to do when bootstrapping the generated node. Two of the most prominents steps are enabling long path and using NSSM to start the goss service. When we enable long path on Windows, it allows the command `puppet module install` to install dependencies correctly (specifically the dsc modules). As for [NSSM](https://nssm.cc/), stands for Non-sucking service manager, it is necessary for us to use this tool because without it, we will not be able to create services for Goss. Windows services cannot run from an executable but rather through a Windows service project that can be build with Visual Studio. NSSM allows us to bypass having to create Windows service project for Goss and create services directly from the Goss executable.
340
+ While testing with sce_windows follows pretty much the same outline as sce_linux, there are a few extra step that we have to do when bootstrapping the generated node. Two of the most prominents steps are enabling long path and using NSSM to start the goss service. When we enable long path on Windows, it allows the command `puppet module install` to install dependencies correctly (specifically the dsc modules). As for [NSSM](https://nssm.cc/), stands for Non-sucking service manager, it is necessary for us to use this tool because without it, we will not be able to create services for Goss. Windows services cannot run from an executable but rather through a Windows service project that can be build with Visual Studio. NSSM allows us to bypass having to create Windows service project for Goss and create services directly from the Goss executable.
341
+
342
+ #### Configuring the GCS bucket
343
+
344
+ The Windows test path uploads the Puppet module tarball to a GCS bucket so the test instance can `gcloud storage cp` it back down. The bucket name is configurable via `platform.gcp.windows_bucket` (default: `win_cem_acpt`):
345
+
346
+ ```yaml
347
+ platform:
348
+ name: gcp
349
+ gcp:
350
+ windows_bucket: my-org-cem-acpt
351
+ ```
352
+
353
+ Alternatively, pass `--windows-bucket BUCKET` on the CLI or set `CEM_ACPT_PLATFORM__GCP__WINDOWS_BUCKET` in the environment. The bucket must exist and be writable by the account running `cem_acpt`; it must also be readable by the service account attached to the Windows test instance.
data/cem_acpt.gemspec CHANGED
@@ -30,6 +30,7 @@ Gem::Specification.new do |spec|
30
30
  spec.add_runtime_dependency 'async-http', '>= 0.60', '< 0.70'
31
31
  spec.add_runtime_dependency 'bcrypt_pbkdf', '>= 1.0', '< 2.0'
32
32
  spec.add_runtime_dependency 'deep_merge', '>= 1.2', '< 2.0'
33
+ spec.add_runtime_dependency 'dotenv', '>= 3.2', '< 4.0'
33
34
  spec.add_runtime_dependency 'ed25519', '>= 1.0', '< 2.0'
34
35
  spec.add_runtime_dependency 'puppet-modulebuilder', '>= 0.0.1'
35
36
  spec.add_runtime_dependency 'winrm', '>= 2.3', '< 3.0'