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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@
/tmp/
w10_20h2.xml
w10_2004.xml
.env
# rspec failure tracking
.rspec_status
.rspec_status
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
abide_dev_utils (0.18.7)
abide_dev_utils (0.18.8)
cmdparse (~> 3.0)
facterdb (~> 4.1.0)
google-cloud-storage (~> 1.34)
Expand Down
2 changes: 1 addition & 1 deletion lib/abide_dev_utils/sce/benchmark.rb
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ def profiles_levels_by_profile(prof)
def filtered_profiles_levels(prof: nil, lvl: nil)
return profiles_levels if (prof.nil? || prof.empty?) && (lvl.nil? || lvl.empty?)
if prof && lvl && !prof.empty? && !lvl.empty?
return profiles_levels_by_profile(prof).concat(profiles_levels_by_level(lvl))
return profiles_levels_by_profile(prof) & profiles_levels_by_level(lvl)
end
return profiles_levels_by_profile(prof) unless prof&.empty?

Expand Down
8 changes: 8 additions & 0 deletions lib/abide_dev_utils/sce/generate/reference.rb
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ def initialize(benchmarks, module_name, file: 'REFERENCE.md', opts: {})
end

def generate(doc_title = 'Reference')
default_profile_for_sce_linux!
@strings = Strings.new(opts: @opts)
md.add_title(doc_title)
benchmarks.each do |benchmark|
Expand Down Expand Up @@ -121,6 +122,13 @@ def generate(doc_title = 'Reference')
private

attr_reader :benchmarks, :md

def default_profile_for_sce_linux!
return unless @module_name.split('-').last == 'sce_linux'
return unless @opts[:select_profile].nil? || @opts[:select_profile].empty?

@opts[:select_profile] = ['server']
end
end

class ConfigExampleError < StandardError; end
Expand Down
2 changes: 1 addition & 1 deletion lib/abide_dev_utils/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# frozen_string_literal: true

module AbideDevUtils
VERSION = "0.18.7"
VERSION = "0.18.8"
end
10 changes: 10 additions & 0 deletions spec/abide_dev_utils/sce/benchmark_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@
)
end

context 'when filtering controls by profile and level' do
it 'excludes profiles not in the filter when both prof and lvl are given' do
ctrl = test_objs.last.flat_map(&:controls)
.find { |c| c.profiles_levels.any? { |pl| pl.start_with?('workstation;;;') } }
skip 'no control with workstation profile found in fixtures' unless ctrl
result = ctrl.filtered_profiles_levels(prof: %w[server], lvl: %w[level_1 level_2])
expect(result.none? { |pl| pl.start_with?('workstation;;;') }).to be(true)
end
end

context 'when supplied a PuppetModule' do
it 'creates benchmark objects correctly' do
expect(test_objs.last.empty?).not_to be_truthy
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# frozen_string_literal: true

require 'spec_helper'
require 'abide_dev_utils/sce/generate/reference'

RSpec.describe(AbideDevUtils::Sce::Generate::Reference::MarkdownGenerator) do
before do
md_double = double('Markdown').as_null_object # rubocop:disable RSpec/VerifiedDoubles
allow(AbideDevUtils::Markdown).to receive(:new).and_return(md_double)
end

context 'with puppetlabs-sce_linux and no select_profile' do
it 'defaults select_profile to server' do
gen = described_class.new([], 'puppetlabs-sce_linux', file: '/dev/null', opts: {})
gen.generate
expect(gen.instance_variable_get(:@opts)[:select_profile]).to eq(['server'])
end
end

context 'with puppetlabs-sce_linux and explicit select_profile' do
it 'does not override select_profile' do
gen = described_class.new([], 'puppetlabs-sce_linux', file: '/dev/null',
opts: { select_profile: ['server'] })
gen.generate
expect(gen.instance_variable_get(:@opts)[:select_profile]).to eq(['server'])
end
end

context 'with a non-sce_linux module and no select_profile' do
it 'does not set a default select_profile' do
gen = described_class.new([], 'puppetlabs-sce_windows', file: '/dev/null', opts: {})
gen.generate
expect(gen.instance_variable_get(:@opts)[:select_profile].nil?).to be(true)
end
end
end
111 changes: 111 additions & 0 deletions specifications/CEM-6541.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
## Background

The `REFERENCE.md` generated for `sce_linux` on the Forge lists `workstation` profile entries for
many controls. SCE documentation explicitly states that only the `server` profile is supported;
`workstation` is neither tested nor supported.

Two bugs in `abide_dev_utils` cause this:

**Bug 1 — `filtered_profiles_levels` uses OR logic instead of AND (`benchmark.rb:225`).**
When both `--select-profile` (`-p`) and `--select-level` (`-l`) are passed, the method returns
the *union* of profile-filtered and level-filtered entries:

```ruby
return profiles_levels_by_profile(prof).concat(profiles_levels_by_level(lvl))
```

`profiles_levels_by_level` returns every profile at the requested levels — including
`workstation` — regardless of what was passed via `-p`. So even when running:

```
bundle exec abide sce generate reference -p server,classified,public,sensitive -l level_1,level_2,...
```

`workstation` entries at `level_1` and `level_2` are included because they are matched by the
level filter and then concatenated in.

**Bug 2 — No default profile filter for `sce_linux` when `-p` is omitted (`reference.rb`).**
When `abide sce generate reference` is run without `-p`, `@opts[:select_profile]` is `nil`.
`Control#filtered_profiles_levels` treats `nil` as "no filter", returning all profiles including
`workstation`.

## Change

**File:** `lib/abide_dev_utils/sce/benchmark.rb` (modified)

Change `concat` to array intersection (`&`) in `Control#filtered_profiles_levels` so that when
both `prof` and `lvl` are given, only entries matching *both* filters are returned:

```ruby
# before
return profiles_levels_by_profile(prof).concat(profiles_levels_by_level(lvl))

# after
return profiles_levels_by_profile(prof) & profiles_levels_by_level(lvl)
```

**File:** `lib/abide_dev_utils/sce/generate/reference.rb` (modified)

In `MarkdownGenerator#generate`, default `@opts[:select_profile]` to `['server']` for `sce_linux`
when no profile was explicitly provided. This covers invocations that omit `-p` entirely:

```ruby
def generate(doc_title = 'Reference')
if @module_name.split('-').last == 'sce_linux' &&
(@opts[:select_profile].nil? || @opts[:select_profile].empty?)
@opts[:select_profile] = ['server']
end
@strings = Strings.new(opts: @opts)
...
```

**File:** `spec/abide_dev_utils/sce/benchmark_spec.rb` (modified)

Add a test that verifies `filtered_profiles_levels` with both `prof` and `lvl` excludes profiles
not in the filter (i.e., does not include `workstation` when only `server` is requested).

**File:** `spec/abide_dev_utils/sce/generate/reference/markdown_generator_spec.rb` (new)

Unit tests for the `MarkdownGenerator` opts-defaulting behavior:

```ruby
RSpec.describe(AbideDevUtils::Sce::Generate::Reference::MarkdownGenerator) do
context 'with puppetlabs-sce_linux and no select_profile' do
it 'defaults select_profile to server' do ...
end
context 'with puppetlabs-sce_linux and explicit select_profile' do
it 'does not override select_profile' do ...
end
context 'with a non-sce_linux module and no select_profile' do
it 'does not set a default select_profile' do ...
end
end
```

**File:** `lib/abide_dev_utils/version.rb` (modified)

Bump version from `0.18.7` to `0.18.8`.

## Functional behavior

After these changes:

- Running with both `-p server,...` and `-l level_1,...` returns only controls that match both
filters — `workstation` entries at the requested levels are no longer included.
- Running without `-p` against `sce_linux` defaults the profile filter to `['server']`, so
`workstation` entries are excluded in that case too.
- Passing `-p server,workstation` explicitly still includes `workstation` (escape hatch preserved).

## Non-goals

- Removing `workstation` profile data from the `sce_linux` mapping YAML files.
- Applying the `sce_linux` default profile to `sce_windows` (separate ticket if needed).

## Acceptance criteria

- [ ] Running `bundle exec abide sce generate reference -p server,classified,public,sensitive -l level_1,level_2,mac-1,mac-2,mac-3` against `sce_linux` produces a REFERENCE.md with no `workstation` entries.
- [ ] Running `bundle exec abide sce generate reference` against `sce_linux` without `-p` produces a REFERENCE.md with no `workstation` entries.
- [ ] Running with `-p server,workstation` still includes `workstation` entries (escape hatch not broken).
- [ ] `bundle exec rspec spec/abide_dev_utils/sce/benchmark_spec.rb` passes including the new `filtered_profiles_levels` intersection test.
- [ ] `bundle exec rspec spec/abide_dev_utils/sce/generate/reference/markdown_generator_spec.rb` passes with all three unit tests.
- [ ] `lib/abide_dev_utils/version.rb` reads `VERSION = "0.18.8"`.
Loading