abide_dev_utils 0.2.3 → 0.5.0
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.
- checksums.yaml +4 -4
- data/.dockerignore +1 -0
- data/Dockerfile +23 -0
- data/README.md +20 -0
- data/abide_dev_utils.gemspec +2 -0
- data/lib/abide_dev_utils/cli.rb +2 -0
- data/lib/abide_dev_utils/cli/abstract.rb +2 -0
- data/lib/abide_dev_utils/cli/comply.rb +97 -0
- data/lib/abide_dev_utils/cli/jira.rb +4 -2
- data/lib/abide_dev_utils/cli/puppet.rb +11 -2
- data/lib/abide_dev_utils/cli/test.rb +1 -1
- data/lib/abide_dev_utils/cli/xccdf.rb +7 -3
- data/lib/abide_dev_utils/comply.rb +130 -0
- data/lib/abide_dev_utils/config.rb +24 -1
- data/lib/abide_dev_utils/errors/xccdf.rb +4 -0
- data/lib/abide_dev_utils/jira.rb +17 -0
- data/lib/abide_dev_utils/ppt/new_obj.rb +86 -47
- data/lib/abide_dev_utils/resources/generic_spec.erb +13 -0
- data/lib/abide_dev_utils/version.rb +1 -1
- data/lib/abide_dev_utils/xccdf.rb +1 -1
- data/lib/abide_dev_utils/xccdf/cis/hiera.rb +22 -7
- metadata +35 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: a27976b9f740b67261fa080eeba927bc6fc98e73ffb592fafdd91d4d612cc51f
         | 
| 4 | 
            +
              data.tar.gz: 64778a0d476e2f96d70a14ab318b517c597aa3c5e33afd8939173385b013fe6c
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: e31df40e6dd34a57156ff517d39fcc036f5655ce2f31bf86b1ebb66754304575b7379e0a3751ae378bc81bc1520dbe095255012dc7e10b24e4f6c3f4a85e6551
         | 
| 7 | 
            +
              data.tar.gz: c9dd204d55a37d389c0c8a4d3d281310b87241cbbd149ca029a3fa6a38fd8414bcb350467cd348cdd330fe946e6ee75625bfe2828319ad25d9eb8ed5cc37a9a3
         | 
    
        data/.dockerignore
    ADDED
    
    | @@ -0,0 +1 @@ | |
| 1 | 
            +
            Gemfile.lock
         | 
    
        data/Dockerfile
    ADDED
    
    | @@ -0,0 +1,23 @@ | |
| 1 | 
            +
            FROM ruby:2.7.3-alpine
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            ARG version
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            RUN mkdir /extvol && \
         | 
| 6 | 
            +
                apk update && \
         | 
| 7 | 
            +
                apk add git build-base
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            VOLUME /extvol
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            WORKDIR /usr/src/app
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            RUN mkdir -p ./lib/abide_dev_utils/
         | 
| 14 | 
            +
            COPY Gemfile abide_dev_utils.gemspec ./
         | 
| 15 | 
            +
            COPY lib/abide_dev_utils/version.rb lib/abide_dev_utils
         | 
| 16 | 
            +
            RUN bundle install
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            COPY . .
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            RUN bundle exec rake build && \
         | 
| 21 | 
            +
                gem install pkg/abide_dev_utils-${version}.gem
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            ENTRYPOINT [ "abide" ]
         | 
    
        data/README.md
    CHANGED
    
    | @@ -29,6 +29,10 @@ Issues and pull requests are welcome! | |
| 29 29 |  | 
| 30 30 | 
             
            * Create Jira issues in bulk from coverage reports
         | 
| 31 31 |  | 
| 32 | 
            +
            ### Puppet Comply Report Generation
         | 
| 33 | 
            +
             | 
| 34 | 
            +
            * Allows you ot programatically generate compliance reports from Puppet Comply
         | 
| 35 | 
            +
             | 
| 32 36 | 
             
            ### Supports Configuration via Local YAML file
         | 
| 33 37 |  | 
| 34 38 | 
             
            * Fully configurable via the `~/.abide_dev.yaml` file
         | 
| @@ -128,6 +132,8 @@ Install the gem: | |
| 128 132 | 
             
              * `--absolute-template-dir`, `-A` - Allows you to specify an absolute path with `--template-dir`. This is useful if your template directory is not relative to your module's root directory
         | 
| 129 133 | 
             
              * `--template-name`, `-n` - Allows you to specify a template name if it is different than the `TYPE` parameter
         | 
| 130 134 | 
             
              * `--vars`, `-V` - Comma-separated key=value pairs to pass in to the template renderer. This allows you to pass arbitrary values that can be used in your templates.
         | 
| 135 | 
            +
              * `--spec-template`, `-S` - Path to an ERB template to use for rspec test generation instead of the default
         | 
| 136 | 
            +
              * `--force`, `-f` - Skips any prompts and executes the command
         | 
| 131 137 |  | 
| 132 138 | 
             
            `abide puppet new` exposes a few variables for you to use in your templates by default:
         | 
| 133 139 |  | 
| @@ -179,8 +185,10 @@ $ ls manifests | |
| 179 185 | 
             
            init.pp
         | 
| 180 186 | 
             
            $ abide puppet new control_class 'test_module::controls::test_new_control'
         | 
| 181 187 | 
             
            Created file /Users/the.dude/test_module/manifests/controls/test_new_control.pp
         | 
| 188 | 
            +
            Created file /Users/the.dude/test_module/spec/classes/controls/test_new_control_spec.rb
         | 
| 182 189 | 
             
            $ abide puppet new util_class 'test_module::utils::test_new_util' -v 'testvar1=dude,testvar2=sweet'
         | 
| 183 190 | 
             
            Created file /Users/the.dude/test_module/manifests/utils/test_new_util.pp
         | 
| 191 | 
            +
            Created file /Users/the.dude/test_module/spec/classes/utils/test_new_util_spec.rb
         | 
| 184 192 | 
             
            $ cat manifests/controls/test_new_control.pp
         | 
| 185 193 | 
             
            # @api private
         | 
| 186 194 | 
             
            class test_module::controls::test_new_control (
         | 
| @@ -204,6 +212,9 @@ class test_module::utils::test_new_util ( | |
| 204 212 |  | 
| 205 213 | 
             
            ```
         | 
| 206 214 |  | 
| 215 | 
            +
            **NOTE**: You can use two special prefixes on your template files to denote where the rspec test should be generated for that object.
         | 
| 216 | 
            +
            If the prefix `c-` is used, the test will be generated in the `spec/classes` directory. If the prefix `d-` is used, the test will be generated in the `spec/defines` directory. For example, to create a template for a defined type, name the template something like this: `d-my_defined_type.pp.erb`.
         | 
| 217 | 
            +
             | 
| 207 218 | 
             
            ### XCCDF Command Reference
         | 
| 208 219 |  | 
| 209 220 | 
             
            #### to_hiera
         | 
| @@ -224,6 +235,15 @@ NOTE: When converting XCCDF files to Hiera, control names are sanitized. This me | |
| 224 235 | 
             
              * `--out-file`, `-o` - A path to a file where you would like to save the generated Hiera
         | 
| 225 236 | 
             
              * `--parent-key-prefix`, `-p` - Allows you to append a prefix to all top-level Hiera keys
         | 
| 226 237 |  | 
| 238 | 
            +
            ## Docker
         | 
| 239 | 
            +
             | 
| 240 | 
            +
            A Dockerfile has been provided in this repo for convenience since Ruby environments can be painful to deal with. To abide_dev_utils with Docker:
         | 
| 241 | 
            +
             | 
| 242 | 
            +
            * Build the Dockerfile: `docker build . -t abide_dev_utils --build-arg version=<semver>`
         | 
| 243 | 
            +
            * Run the commands using the container: `docker run -it abide_dev_utils --help`
         | 
| 244 | 
            +
            * The container declares a volume for external resources such as files. To use the volume, add the following flag to your `docker run` commands: `-v /path/to/my/files:/extvol`
         | 
| 245 | 
            +
              * When using the volume, all paths should be absolute based on the root directory `/extvol`
         | 
| 246 | 
            +
             | 
| 227 247 | 
             
            ## Development
         | 
| 228 248 |  | 
| 229 249 | 
             
            After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
         | 
    
        data/abide_dev_utils.gemspec
    CHANGED
    
    | @@ -37,10 +37,12 @@ Gem::Specification.new do |spec| | |
| 37 37 | 
             
              spec.add_dependency 'puppet', '>= 6.19'
         | 
| 38 38 | 
             
              spec.add_dependency 'jira-ruby', '~> 2.1'
         | 
| 39 39 | 
             
              spec.add_dependency 'ruby-progressbar', '~> 1.11'
         | 
| 40 | 
            +
              spec.add_dependency 'selenium-webdriver', '~> 4.0.0.beta4'
         | 
| 40 41 |  | 
| 41 42 | 
             
              # Dev dependencies
         | 
| 42 43 | 
             
              spec.add_development_dependency 'bundler'
         | 
| 43 44 | 
             
              spec.add_development_dependency 'rake'
         | 
| 45 | 
            +
              spec.add_development_dependency 'console'
         | 
| 44 46 | 
             
              spec.add_development_dependency 'github_changelog_generator'
         | 
| 45 47 | 
             
              spec.add_development_dependency 'gem-release'
         | 
| 46 48 | 
             
              spec.add_development_dependency 'rspec', '~> 3.10'
         | 
    
        data/lib/abide_dev_utils/cli.rb
    CHANGED
    
    | @@ -3,6 +3,7 @@ | |
| 3 3 | 
             
            require 'cmdparse'
         | 
| 4 4 | 
             
            require 'abide_dev_utils/version'
         | 
| 5 5 | 
             
            require 'abide_dev_utils/constants'
         | 
| 6 | 
            +
            require 'abide_dev_utils/cli/comply'
         | 
| 6 7 | 
             
            require 'abide_dev_utils/cli/puppet'
         | 
| 7 8 | 
             
            require 'abide_dev_utils/cli/xccdf'
         | 
| 8 9 | 
             
            require 'abide_dev_utils/cli/test'
         | 
| @@ -21,6 +22,7 @@ module Abide | |
| 21 22 | 
             
                  parser.main_options.banner = ROOT_CMD_BANNER
         | 
| 22 23 | 
             
                  parser.add_command(CmdParse::HelpCommand.new, default: true)
         | 
| 23 24 | 
             
                  parser.add_command(CmdParse::VersionCommand.new(add_switches: true))
         | 
| 25 | 
            +
                  parser.add_command(ComplyCommand.new)
         | 
| 24 26 | 
             
                  parser.add_command(PuppetCommand.new)
         | 
| 25 27 | 
             
                  parser.add_command(XccdfCommand.new)
         | 
| 26 28 | 
             
                  parser.add_command(TestCommand.new)
         | 
| @@ -0,0 +1,97 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'abide_dev_utils/comply'
         | 
| 4 | 
            +
            require 'abide_dev_utils/cli/abstract'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            module Abide
         | 
| 7 | 
            +
              module CLI
         | 
| 8 | 
            +
                class ComplyCommand < AbideCommand
         | 
| 9 | 
            +
                  CMD_NAME = 'comply'
         | 
| 10 | 
            +
                  CMD_SHORT = 'Commands related to Puppet Comply'
         | 
| 11 | 
            +
                  CMD_LONG = 'Namespace for commands related to Puppet Comply'
         | 
| 12 | 
            +
                  def initialize
         | 
| 13 | 
            +
                    super(CMD_NAME, CMD_SHORT, CMD_LONG, takes_commands: true)
         | 
| 14 | 
            +
                    add_command(ComplyReportCommand.new)
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                class ComplyReportCommand < AbideCommand
         | 
| 19 | 
            +
                  CMD_NAME = 'report'
         | 
| 20 | 
            +
                  CMD_SHORT = 'Generates a yaml report of Puppet Comply scan results'
         | 
| 21 | 
            +
                  CMD_LONG = <<~LONGCMD
         | 
| 22 | 
            +
                    Generates a yaml file that shows the scan results of all nodes in Puppet Comply.
         | 
| 23 | 
            +
                    This command utilizes Selenium WebDriver and the Google Chrome browser to automate
         | 
| 24 | 
            +
                    clicking through the Comply UI and building a report. In order to use this command,
         | 
| 25 | 
            +
                    you MUST have Google Chrome installed and you MUST install the chromedriver binary.
         | 
| 26 | 
            +
                    More info and instructions can be found here:
         | 
| 27 | 
            +
                    https://www.selenium.dev/documentation/en/getting_started_with_webdriver/.
         | 
| 28 | 
            +
                  LONGCMD
         | 
| 29 | 
            +
                  CMD_COMPLY_URL = 'The URL (including https://) of Puppet Comply'
         | 
| 30 | 
            +
                  CMD_COMPLY_PASSWORD = 'The password for Puppet Comply'
         | 
| 31 | 
            +
                  OPT_STATUS_DESC = <<~EODESC
         | 
| 32 | 
            +
                    A comma-separated list of check statuses to ONLY include in the report.
         | 
| 33 | 
            +
                    Valid statuses are: pass, fail, error, notapplicable, notchecked, unknown, informational
         | 
| 34 | 
            +
                  EODESC
         | 
| 35 | 
            +
                  OPT_IGNORE_NODES = <<~EOIGN
         | 
| 36 | 
            +
                    A comma-separated list of node certnames to ignore building reports for. This
         | 
| 37 | 
            +
                    options is mutually exclusive with --only and, if both are set, --only will take precedence
         | 
| 38 | 
            +
                    over this option.
         | 
| 39 | 
            +
                  EOIGN
         | 
| 40 | 
            +
                  OPT_ONLY_NODES = <<~EOONLY
         | 
| 41 | 
            +
                    A comma-separated list of node certnames to ONLY build reports for. No other
         | 
| 42 | 
            +
                    nodes will have reports built for them except the ones specified. This option
         | 
| 43 | 
            +
                    is mutually exclusive with --ignore and, if both are set, this options will
         | 
| 44 | 
            +
                    take precedence over --ignore.
         | 
| 45 | 
            +
                  EOONLY
         | 
| 46 | 
            +
                  def initialize
         | 
| 47 | 
            +
                    super(CMD_NAME, CMD_SHORT, CMD_LONG, takes_commands: false)
         | 
| 48 | 
            +
                    argument_desc(COMPLY_URL: CMD_COMPLY_URL, COMPLY_PASSWORD: CMD_COMPLY_PASSWORD)
         | 
| 49 | 
            +
                    options.on('-o [FILE]', '--out-file [FILE]', 'Path to save the report') { |f| @data[:file] = f }
         | 
| 50 | 
            +
                    options.on('-u [USERNAME]', '--username [USERNAME]', 'The username for Comply (defaults to comply)') do |u|
         | 
| 51 | 
            +
                      @data[:username] = u
         | 
| 52 | 
            +
                    end
         | 
| 53 | 
            +
                    options.on('-s [STATUS]', '--status [STATUS]', OPT_STATUS_DESC) do |s|
         | 
| 54 | 
            +
                      status_array = s.nil? ? nil : s.split(',').map(&:downcase)
         | 
| 55 | 
            +
                      status_array&.map! { |i| i == 'notchecked' ? 'not checked' : i }
         | 
| 56 | 
            +
                      @data[:status] = status_array
         | 
| 57 | 
            +
                    end
         | 
| 58 | 
            +
                    options.on('-O [CERTNAME]', '--only [CERTNAME]', OPT_ONLY_NODES) do |o|
         | 
| 59 | 
            +
                      only_array = o.nil? ? nil : s.split(',').map(&:downcase)
         | 
| 60 | 
            +
                      @data[:only] = only_array
         | 
| 61 | 
            +
                    end
         | 
| 62 | 
            +
                    options.on('-I [CERTNAME]', '--ignore [CERTNAME]', OPT_IGNORE_NODES) do |i|
         | 
| 63 | 
            +
                      ignore_array = i.nil? ? nil : i.split(',').map(&:downcase)
         | 
| 64 | 
            +
                      @data[:ignore] = ignore_array
         | 
| 65 | 
            +
                    end
         | 
| 66 | 
            +
                  end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                  def help_arguments
         | 
| 69 | 
            +
                    <<~ARGHELP
         | 
| 70 | 
            +
                      Arguments:
         | 
| 71 | 
            +
                          COMPLY_URL        #{CMD_COMPLY_URL}
         | 
| 72 | 
            +
                          COMPLY_PASSWORD   #{CMD_COMPLY_PASSWORD}
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                    ARGHELP
         | 
| 75 | 
            +
                  end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                  def execute(comply_url = nil, comply_password = nil)
         | 
| 78 | 
            +
                    Abide::CLI::VALIDATE.filesystem_path(`command -v chromedriver`.strip)
         | 
| 79 | 
            +
                    conf = config_section('comply')
         | 
| 80 | 
            +
                    comply_url = conf.fetch(:url) if comply_url.nil?
         | 
| 81 | 
            +
                    comply_password = comply_password.nil? ? conf.fetch(:password, Abide::CLI::PROMPT.password) : comply_password
         | 
| 82 | 
            +
                    username = @data.fetch(:username, nil).nil? ? conf.fetch(:username, 'comply') : @data[:username]
         | 
| 83 | 
            +
                    status = @data.fetch(:status, nil).nil? ? conf.fecth(:status, nil) : @data[:status]
         | 
| 84 | 
            +
                    ignorelist = @data.fetch(:ignore, nil).nil? ? conf.fetch(:ignore, nil) : @data[:ignore]
         | 
| 85 | 
            +
                    onlylist = @data.fetch(:only, nil).nil? ? conf.fetch(:only, nil) : @data[:only]
         | 
| 86 | 
            +
                    report = AbideDevUtils::Comply.scan_report(comply_url,
         | 
| 87 | 
            +
                                                               comply_password,
         | 
| 88 | 
            +
                                                               username: username,
         | 
| 89 | 
            +
                                                               status: status,
         | 
| 90 | 
            +
                                                               ignorelist: ignorelist,
         | 
| 91 | 
            +
                                                               onlylist: onlylist)
         | 
| 92 | 
            +
                    outfile = @data.fetch(:file, nil).nil? ? conf.fetch(:report_path, 'comply_scan_report.yaml') : @data[:file]
         | 
| 93 | 
            +
                    Abide::CLI::OUTPUT.yaml(report, file: outfile)
         | 
| 94 | 
            +
                  end
         | 
| 95 | 
            +
                end
         | 
| 96 | 
            +
              end
         | 
| 97 | 
            +
            end
         | 
| @@ -1,10 +1,12 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 |  | 
| 3 3 | 
             
            require 'json'
         | 
| 4 | 
            +
            require 'abide_dev_utils/config'
         | 
| 4 5 | 
             
            require 'abide_dev_utils/jira'
         | 
| 5 6 |  | 
| 6 7 | 
             
            module Abide
         | 
| 7 8 | 
             
              module CLI
         | 
| 9 | 
            +
                CONFIG = AbideDevUtils::Config
         | 
| 8 10 | 
             
                JIRA = AbideDevUtils::Jira
         | 
| 9 11 |  | 
| 10 12 | 
             
                class JiraCommand < CmdParse::Command
         | 
| @@ -57,8 +59,8 @@ module Abide | |
| 57 59 | 
             
                  def execute(issue)
         | 
| 58 60 | 
             
                    client = JIRA.client(options: {})
         | 
| 59 61 | 
             
                    issue = client.Issue.find(issue)
         | 
| 60 | 
            -
                    console = @data[:file].nil? | 
| 61 | 
            -
                    out_json = issue.attrs.select { |_,v| !v.nil? || !v.empty? }
         | 
| 62 | 
            +
                    console = @data[:file].nil?
         | 
| 63 | 
            +
                    out_json = issue.attrs.select { |_, v| !v.nil? || !v.empty? }
         | 
| 62 64 | 
             
                    Abide::CLI::OUTPUT.json(out_json, console: console, file: @data[:file])
         | 
| 63 65 | 
             
                  end
         | 
| 64 66 | 
             
                end
         | 
| @@ -87,6 +87,16 @@ module Abide | |
| 87 87 | 
             
                      '--vars [VARNAME=VALUE]',
         | 
| 88 88 | 
             
                      'Allows you to specify comma-separated variable names and values that will be converted into a hash that is available for you to use in your templates'
         | 
| 89 89 | 
             
                    ) { |v| @data[:vars] = v }
         | 
| 90 | 
            +
                    options.on(
         | 
| 91 | 
            +
                      '-S [PATH]',
         | 
| 92 | 
            +
                      '--spec-template [PATH]',
         | 
| 93 | 
            +
                      'Path to an ERB template to use for rspec test generation instead of the default'
         | 
| 94 | 
            +
                    )
         | 
| 95 | 
            +
                    options.on(
         | 
| 96 | 
            +
                      '-f',
         | 
| 97 | 
            +
                      '--force',
         | 
| 98 | 
            +
                      'Skips any prompts and executes the command'
         | 
| 99 | 
            +
                    ) { |_| @data[:force] = true }
         | 
| 90 100 | 
             
                  end
         | 
| 91 101 |  | 
| 92 102 | 
             
                  def execute(type, name)
         | 
| @@ -97,8 +107,7 @@ module Abide | |
| 97 107 | 
             
                      opts: @data,
         | 
| 98 108 | 
             
                      vars: @data.fetch(:vars, '').split(',').map { |i| i.split('=') }.to_h # makes the str a hash
         | 
| 99 109 | 
             
                    )
         | 
| 100 | 
            -
                     | 
| 101 | 
            -
                    Abide::CLI::OUTPUT.simple(result)
         | 
| 110 | 
            +
                    builder.build
         | 
| 102 111 | 
             
                  end
         | 
| 103 112 | 
             
                end
         | 
| 104 113 | 
             
              end
         | 
| @@ -35,10 +35,10 @@ module Abide | |
| 35 35 | 
             
                    @litmus_im = [CMD_LIT_BASE, "'litmus:install_module'"]
         | 
| 36 36 | 
             
                    @litmus_ap = [CMD_LIT_BASE, "'litmus:acceptance:parallel'"]
         | 
| 37 37 | 
             
                    @litmus_td = [CMD_LIT_BASE, "'litmus:tear_down'"]
         | 
| 38 | 
            -
                    validate_env_and_opts
         | 
| 39 38 | 
             
                  end
         | 
| 40 39 |  | 
| 41 40 | 
             
                  def execute(suite)
         | 
| 41 | 
            +
                    validate_env_and_opts
         | 
| 42 42 | 
             
                    case suite.downcase
         | 
| 43 43 | 
             
                    when /^a[A-Za-z]*/
         | 
| 44 44 | 
             
                      run_command(@validate)
         | 
| @@ -27,7 +27,12 @@ module Abide | |
| 27 27 | 
             
                    long_desc(CMD_LONG)
         | 
| 28 28 | 
             
                    options.on('-b [TYPE]', '--benchmark-type [TYPE]', 'XCCDF Benchmark type') { |b| @data[:type] = b }
         | 
| 29 29 | 
             
                    options.on('-o [FILE]', '--out-file [FILE]', 'Path to save file') { |f| @data[:file] = f }
         | 
| 30 | 
            -
                    options.on('-p [PREFIX]', '--parent-key-prefix [PREFIX]', 'A prefix to append to the parent key')  | 
| 30 | 
            +
                    options.on('-p [PREFIX]', '--parent-key-prefix [PREFIX]', 'A prefix to append to the parent key') do |p|
         | 
| 31 | 
            +
                      @data[:parent_key_prefix] = p
         | 
| 32 | 
            +
                    end
         | 
| 33 | 
            +
                    options.on('-N', '--number-fmt', 'Format Hiera control names based off of control number instead of name.') do
         | 
| 34 | 
            +
                      @data[:num] = true
         | 
| 35 | 
            +
                    end
         | 
| 31 36 | 
             
                  end
         | 
| 32 37 |  | 
| 33 38 | 
             
                  def execute(xccdf_file)
         | 
| @@ -40,8 +45,7 @@ module Abide | |
| 40 45 |  | 
| 41 46 | 
             
                  def to_hiera(xccdf_file)
         | 
| 42 47 | 
             
                    xfile = AbideDevUtils::XCCDF.to_hiera(xccdf_file, @data)
         | 
| 43 | 
            -
                    console  | 
| 44 | 
            -
                    Abide::CLI::OUTPUT.yaml(xfile, console: console, file: @data[:file])
         | 
| 48 | 
            +
                    Abide::CLI::OUTPUT.yaml(xfile, console: @data[:file].nil?, file: @data[:file])
         | 
| 45 49 | 
             
                  end
         | 
| 46 50 | 
             
                end
         | 
| 47 51 | 
             
              end
         | 
| @@ -0,0 +1,130 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'yaml'
         | 
| 4 | 
            +
            require 'selenium-webdriver'
         | 
| 5 | 
            +
            require 'abide_dev_utils/output'
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            module AbideDevUtils
         | 
| 8 | 
            +
              module Comply
         | 
| 9 | 
            +
                def self.scan_report(url, password, username: 'comply', status: nil, ignorelist: nil, onlylist: nil)
         | 
| 10 | 
            +
                  begin
         | 
| 11 | 
            +
                    AbideDevUtils::Output.simple 'Starting headless Chrome...'
         | 
| 12 | 
            +
                    options = Selenium::WebDriver::Chrome::Options.new
         | 
| 13 | 
            +
                    options.args = %w[
         | 
| 14 | 
            +
                      --headless
         | 
| 15 | 
            +
                      --test-type
         | 
| 16 | 
            +
                      --disable-gpu
         | 
| 17 | 
            +
                      --no-first-run
         | 
| 18 | 
            +
                      --no-default-browser-check
         | 
| 19 | 
            +
                      --ignore-certificate-errors
         | 
| 20 | 
            +
                      --start-maximized
         | 
| 21 | 
            +
                    ]
         | 
| 22 | 
            +
                    driver = Selenium::WebDriver.for :chrome, options: options
         | 
| 23 | 
            +
                    driver.get(url)
         | 
| 24 | 
            +
                    bypass_ssl_warning_page(driver)
         | 
| 25 | 
            +
                    AbideDevUtils::Output.simple "Logging into Comply at #{url}..."
         | 
| 26 | 
            +
                    login_to_comply(driver, username: username, password: password)
         | 
| 27 | 
            +
                    AbideDevUtils::Output.simple 'Finding nodes with scan reports...'
         | 
| 28 | 
            +
                    links = find_node_report_links(driver)
         | 
| 29 | 
            +
                    AbideDevUtils::Output.simple 'Building scan reports, this may take a while...'
         | 
| 30 | 
            +
                    build_report(driver, links, status: status, ignorelist: ignorelist, onlylist: onlylist)
         | 
| 31 | 
            +
                  ensure
         | 
| 32 | 
            +
                    driver.quit
         | 
| 33 | 
            +
                  end
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                def self.ignore_no_such_element
         | 
| 37 | 
            +
                  begin
         | 
| 38 | 
            +
                    yield
         | 
| 39 | 
            +
                  rescue Selenium::WebDriver::Error::NoSuchElementError => e
         | 
| 40 | 
            +
                    AbideDevUtils::Output.simple "Ignored exception #{e}", stream: $stderr
         | 
| 41 | 
            +
                  end
         | 
| 42 | 
            +
                end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                def self.wait_on(timeout = 10)
         | 
| 45 | 
            +
                  Selenium::WebDriver::Wait.new(timeout: timeout).until do
         | 
| 46 | 
            +
                    yield
         | 
| 47 | 
            +
                  end
         | 
| 48 | 
            +
                end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                def self.bypass_ssl_warning_page(driver)
         | 
| 51 | 
            +
                  ignore_no_such_element do
         | 
| 52 | 
            +
                    driver.find_element(id: 'details-button').click
         | 
| 53 | 
            +
                    driver.find_element(id: 'proceed-link').click
         | 
| 54 | 
            +
                  end
         | 
| 55 | 
            +
                end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                def self.login_to_comply(driver, username: 'comply', password: 'compliance')
         | 
| 58 | 
            +
                  wait_on { driver.find_element(id: 'username') }
         | 
| 59 | 
            +
                  driver.find_element(id: 'username').send_keys username
         | 
| 60 | 
            +
                  driver.find_element(id: 'password').send_keys password
         | 
| 61 | 
            +
                  driver.find_element(id: 'kc-login').click
         | 
| 62 | 
            +
                end
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                def self.find_node_report_links(driver)
         | 
| 65 | 
            +
                  wait_on { driver.find_element(class: 'metric-containers-failed-hosts-count') }
         | 
| 66 | 
            +
                  hosts = driver.find_element(class: 'metric-containers-failed-hosts-count')
         | 
| 67 | 
            +
                  table = hosts.find_element(class: 'rc-table')
         | 
| 68 | 
            +
                  table_body = table.find_element(tag_name: 'tbody')
         | 
| 69 | 
            +
                  wait_on { table_body.find_element(tag_name: 'a') }
         | 
| 70 | 
            +
                  table_body.find_elements(tag_name: 'a')
         | 
| 71 | 
            +
                end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                def self.build_report(driver, links, status: nil, ignorelist: nil, onlylist: nil)
         | 
| 74 | 
            +
                  all_checks = {}
         | 
| 75 | 
            +
                  original_window = driver.window_handle
         | 
| 76 | 
            +
                  links.each do |link|
         | 
| 77 | 
            +
                    if !onlylist.nil? && !onlylist.empty?
         | 
| 78 | 
            +
                      next unless onlylist.include?(link.text)
         | 
| 79 | 
            +
                    elsif !ignorelist.nil? && !ignorelist.empty?
         | 
| 80 | 
            +
                      next if ignorelist.include?(link.text)
         | 
| 81 | 
            +
                    end
         | 
| 82 | 
            +
                    begin
         | 
| 83 | 
            +
                      node_name = link.text
         | 
| 84 | 
            +
                      progress = AbideDevUtils::Output.progress title: "Builingd report for #{node_name}", total: nil
         | 
| 85 | 
            +
                      link_url = link.attribute('href')
         | 
| 86 | 
            +
                      driver.manage.new_window(:tab)
         | 
| 87 | 
            +
                      wait_on { driver.window_handles.length == 2 }
         | 
| 88 | 
            +
                      progress.increment
         | 
| 89 | 
            +
                      driver.switch_to.window driver.window_handles[1]
         | 
| 90 | 
            +
                      driver.get(link_url)
         | 
| 91 | 
            +
                      wait_on { driver.find_element(class: 'details-scan-info') }
         | 
| 92 | 
            +
                      progress.increment
         | 
| 93 | 
            +
                      wait_on { driver.find_element(class: 'details-table') }
         | 
| 94 | 
            +
                      progress.increment
         | 
| 95 | 
            +
                      report = {}
         | 
| 96 | 
            +
                      report['scan_results'] = {}
         | 
| 97 | 
            +
                      scan_info_table = driver.find_element(class: 'details-scan-info')
         | 
| 98 | 
            +
                      scan_info_table_rows = scan_info_table.find_elements(tag_name: 'tr')
         | 
| 99 | 
            +
                      progress.increment
         | 
| 100 | 
            +
                      check_table_body = driver.find_element(tag_name: 'tbody')
         | 
| 101 | 
            +
                      check_table_rows = check_table_body.find_elements(tag_name: 'tr')
         | 
| 102 | 
            +
                      progress.increment
         | 
| 103 | 
            +
                      scan_info_table_rows.each do |row|
         | 
| 104 | 
            +
                        key = row.find_element(tag_name: 'h5').text
         | 
| 105 | 
            +
                        value = row.find_element(tag_name: 'strong').text
         | 
| 106 | 
            +
                        report[key.downcase.gsub(/:/, '').gsub(/ /, '_')] = value
         | 
| 107 | 
            +
                        progress.increment
         | 
| 108 | 
            +
                      end
         | 
| 109 | 
            +
                      check_table_rows.each do |row|
         | 
| 110 | 
            +
                        chk_objs = row.find_elements(tag_name: 'td')
         | 
| 111 | 
            +
                        chk_objs.map!(&:text)
         | 
| 112 | 
            +
                        if status.nil? || status.include?(chk_objs[1].downcase)
         | 
| 113 | 
            +
                          report['scan_results'][chk_objs[0][/^[0-9.]+/, 0]] = {
         | 
| 114 | 
            +
                            'name' => chk_objs[0].gsub(/\n/, ' '),
         | 
| 115 | 
            +
                            'status' => chk_objs[1]
         | 
| 116 | 
            +
                          }
         | 
| 117 | 
            +
                        end
         | 
| 118 | 
            +
                        progress.increment
         | 
| 119 | 
            +
                      end
         | 
| 120 | 
            +
                      all_checks[node_name] = report
         | 
| 121 | 
            +
                      driver.close
         | 
| 122 | 
            +
                      AbideDevUtils::Output.simple "Created report for #{node_name}"
         | 
| 123 | 
            +
                    ensure
         | 
| 124 | 
            +
                      driver.switch_to.window original_window
         | 
| 125 | 
            +
                    end
         | 
| 126 | 
            +
                  end
         | 
| 127 | 
            +
                  all_checks
         | 
| 128 | 
            +
                end
         | 
| 129 | 
            +
              end
         | 
| 130 | 
            +
            end
         | 
| @@ -7,18 +7,41 @@ module AbideDevUtils | |
| 7 7 | 
             
                DEFAULT_PATH = "#{File.expand_path('~')}/.abide_dev.yaml"
         | 
| 8 8 |  | 
| 9 9 | 
             
                def self.to_h(path = DEFAULT_PATH)
         | 
| 10 | 
            +
                  return {} unless File.file?(path)
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  h = YAML.safe_load(File.open(path), [Symbol])
         | 
| 13 | 
            +
                  h.transform_keys(&:to_sym)
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                def to_h(path = DEFAULT_PATH)
         | 
| 17 | 
            +
                  return {} unless File.file?(path)
         | 
| 18 | 
            +
             | 
| 10 19 | 
             
                  h = YAML.safe_load(File.open(path), [Symbol])
         | 
| 11 20 | 
             
                  h.transform_keys(&:to_sym)
         | 
| 12 21 | 
             
                end
         | 
| 13 22 |  | 
| 14 23 | 
             
                def self.config_section(section, path = DEFAULT_PATH)
         | 
| 15 24 | 
             
                  h = to_h(path)
         | 
| 16 | 
            -
                  s = h | 
| 25 | 
            +
                  s = h.fetch(section.to_sym, nil)
         | 
| 26 | 
            +
                  return {} if s.nil?
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  s.transform_keys(&:to_sym)
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                def config_section(section, path = DEFAULT_PATH)
         | 
| 32 | 
            +
                  h = to_h(path)
         | 
| 33 | 
            +
                  s = h.fetch(section.to_sym, nil)
         | 
| 34 | 
            +
                  return {} if s.nil?
         | 
| 35 | 
            +
             | 
| 17 36 | 
             
                  s.transform_keys(&:to_sym)
         | 
| 18 37 | 
             
                end
         | 
| 19 38 |  | 
| 20 39 | 
             
                def self.fetch(key, default = nil, path = DEFAULT_PATH)
         | 
| 21 40 | 
             
                  to_h(path).fetch(key, default)
         | 
| 22 41 | 
             
                end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                def fetch(key, default = nil, path = DEFAULT_PATH)
         | 
| 44 | 
            +
                  to_h(path).fetch(key, default)
         | 
| 45 | 
            +
                end
         | 
| 23 46 | 
             
              end
         | 
| 24 47 | 
             
            end
         | 
| @@ -8,5 +8,9 @@ module AbideDevUtils | |
| 8 8 | 
             
                class XPathSearchError < GenericError
         | 
| 9 9 | 
             
                  @default = 'XPath seach failed to find anything at:'
         | 
| 10 10 | 
             
                end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                class StrategyInvalidError < GenericError
         | 
| 13 | 
            +
                  @default = 'Invalid strategy selected. Should be either \'name\' or \'num\''
         | 
| 14 | 
            +
                end
         | 
| 11 15 | 
             
              end
         | 
| 12 16 | 
             
            end
         | 
    
        data/lib/abide_dev_utils/jira.rb
    CHANGED
    
    | @@ -86,6 +86,8 @@ module AbideDevUtils | |
| 86 86 |  | 
| 87 87 | 
             
                def self.client(options: {})
         | 
| 88 88 | 
             
                  opts = merge_options(options)
         | 
| 89 | 
            +
                  return client_from_prompts if opts.empty?
         | 
| 90 | 
            +
             | 
| 89 91 | 
             
                  opts[:username] = AbideDevUtils::Prompt.username if opts[:username].nil?
         | 
| 90 92 | 
             
                  opts[:password] = AbideDevUtils::Prompt.password if opts[:password].nil?
         | 
| 91 93 | 
             
                  opts[:site] = AbideDevUtils::Prompt.single_line('Jira URL') if opts[:site].nil?
         | 
| @@ -133,6 +135,16 @@ module AbideDevUtils | |
| 133 135 | 
             
                  end
         | 
| 134 136 | 
             
                end
         | 
| 135 137 |  | 
| 138 | 
            +
                # def self.new_issues_from_comply_report(client, project, report, dry_run: false)
         | 
| 139 | 
            +
                #   dr_prefix = dry_run ? 'DRY RUN: ' : ''
         | 
| 140 | 
            +
                #   i_attrs = all_project_issues_attrs(project)
         | 
| 141 | 
            +
                #   rep_sums = summaries_from_coverage_report(report)
         | 
| 142 | 
            +
                #   rep_sums.each do |k, v|
         | 
| 143 | 
            +
                #     next if summary_exist?(k, i_attrs)
         | 
| 144 | 
            +
             | 
| 145 | 
            +
                #     progress = AbideDevUtils::Output.progress(title: "#{dr_prefix}Creating Tasks", total: nil)
         | 
| 146 | 
            +
                #     v.each do |s|
         | 
| 147 | 
            +
             | 
| 136 148 | 
             
                def self.merge_options(options)
         | 
| 137 149 | 
             
                  config.merge(options)
         | 
| 138 150 | 
             
                end
         | 
| @@ -165,6 +177,11 @@ module AbideDevUtils | |
| 165 177 | 
             
                  summaries.transform_keys { |k| "#{COV_PARENT_SUMMARY_PREFIX}#{benchmark}-#{k}"}
         | 
| 166 178 | 
             
                end
         | 
| 167 179 |  | 
| 180 | 
            +
                # def self.summaries_from_comply_report(report)
         | 
| 181 | 
            +
                #   summaries = {}
         | 
| 182 | 
            +
                #   report.each do |_, v|
         | 
| 183 | 
            +
                # end
         | 
| 184 | 
            +
             | 
| 168 185 | 
             
                class Dummy
         | 
| 169 186 | 
             
                  def attrs
         | 
| 170 187 | 
             
                    { 'fields' => {
         | 
| @@ -2,6 +2,7 @@ | |
| 2 2 |  | 
| 3 3 | 
             
            require 'erb'
         | 
| 4 4 | 
             
            require 'pathname'
         | 
| 5 | 
            +
            require 'abide_dev_utils/output'
         | 
| 5 6 | 
             
            require 'abide_dev_utils/prompt'
         | 
| 6 7 | 
             
            require 'abide_dev_utils/errors/ppt'
         | 
| 7 8 |  | 
| @@ -9,6 +10,10 @@ module AbideDevUtils | |
| 9 10 | 
             
              module Ppt
         | 
| 10 11 | 
             
                class NewObjectBuilder
         | 
| 11 12 | 
             
                  DEFAULT_EXT = '.pp'
         | 
| 13 | 
            +
                  VALID_EXT = /(\.pp|\.rb)\.erb$/.freeze
         | 
| 14 | 
            +
                  TMPL_PATTERN = /^[a-zA-Z][^\s]*\.erb$/.freeze
         | 
| 15 | 
            +
                  OBJ_PREFIX = /^(c-|d-)/.freeze
         | 
| 16 | 
            +
                  PREFIX_TEST_PATH = { 'c-' => 'classes', 'd-' => 'defines' }.freeze
         | 
| 12 17 |  | 
| 13 18 | 
             
                  def initialize(obj_type, obj_name, opts: {}, vars: {})
         | 
| 14 19 | 
             
                    @obj_type = obj_type
         | 
| @@ -17,25 +22,17 @@ module AbideDevUtils | |
| 17 22 | 
             
                    @vars = vars
         | 
| 18 23 | 
             
                    class_vars
         | 
| 19 24 | 
             
                    validate_class_vars
         | 
| 25 | 
            +
                    @tmpl_data = template_data(@opts.fetch(:tmpl_name, @obj_type))
         | 
| 20 26 | 
             
                  end
         | 
| 21 27 |  | 
| 22 | 
            -
                  attr_reader :obj_type, :obj_name, : | 
| 23 | 
            -
             | 
| 24 | 
            -
                  def render
         | 
| 25 | 
            -
                    ERB.new(File.read(@tmpl_path.to_s), 0, '<>-').result(binding)
         | 
| 26 | 
            -
                  end
         | 
| 28 | 
            +
                  attr_reader :obj_type, :obj_name, :root_dir, :tmpl_dir, :obj_path, :vars, :tmpl_data
         | 
| 27 29 |  | 
| 28 30 | 
             
                  def build
         | 
| 29 | 
            -
                     | 
| 30 | 
            -
                     | 
| 31 | 
            -
             | 
| 32 | 
            -
                     | 
| 33 | 
            -
                     | 
| 34 | 
            -
                    content = render
         | 
| 35 | 
            -
                    File.open(obj_path, 'w') { |f| f.write(render) } unless content.empty?
         | 
| 36 | 
            -
                    raise AbideDevUtils::Errors::Ppt::FailedToCreateFileError, obj_path unless File.file?(obj_path)
         | 
| 37 | 
            -
             | 
| 38 | 
            -
                    "Created file #{obj_path}"
         | 
| 31 | 
            +
                    force = @opts.fetch(:force, false)
         | 
| 32 | 
            +
                    obj_cont = force ? true : continue?(obj_path)
         | 
| 33 | 
            +
                    spec_cont = force ? true : continue?(@tmpl_data[:spec_path])
         | 
| 34 | 
            +
                    write_file(obj_path, @tmpl_data[:path]) if obj_cont
         | 
| 35 | 
            +
                    write_file(@tmpl_data[:spec_path], @spec_tmpl) if spec_cont
         | 
| 39 36 | 
             
                  end
         | 
| 40 37 |  | 
| 41 38 | 
             
                  # If a method gets called on the Hiera object which is not defined,
         | 
| @@ -59,42 +56,98 @@ module AbideDevUtils | |
| 59 56 |  | 
| 60 57 | 
             
                  private
         | 
| 61 58 |  | 
| 59 | 
            +
                  def continue?(path)
         | 
| 60 | 
            +
                    continue = if File.exist?(path)
         | 
| 61 | 
            +
                                 AbideDevUtils::Prompt.yes_no('File exists, would you like to overwrite?')
         | 
| 62 | 
            +
                               else
         | 
| 63 | 
            +
                                 true
         | 
| 64 | 
            +
                               end
         | 
| 65 | 
            +
                    AbideDevUtils::Output.simple("Not overwriting file #{path}") unless continue
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                    continue
         | 
| 68 | 
            +
                  end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                  def write_file(path, tmpl_path)
         | 
| 71 | 
            +
                    dir, = Pathname.new(path).split
         | 
| 72 | 
            +
                    Pathname.new(dir).mkpath unless Dir.exist?(dir)
         | 
| 73 | 
            +
                    content = render(tmpl_path)
         | 
| 74 | 
            +
                    File.open(path, 'w') { |f| f.write(content) } unless content.empty?
         | 
| 75 | 
            +
                    raise AbideDevUtils::Errors::Ppt::FailedToCreateFileError, path unless File.file?(path)
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                    AbideDevUtils::Output.simple("Created file #{path}")
         | 
| 78 | 
            +
                  end
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                  def build_obj; end
         | 
| 81 | 
            +
             | 
| 62 82 | 
             
                  def class_vars
         | 
| 63 | 
            -
                    @tmpl_name = @opts.fetch(:tmpl_name, "#{@obj_type}.erb")
         | 
| 64 83 | 
             
                    @root_dir = Pathname.new(@opts.fetch(:root_dir, Dir.pwd))
         | 
| 65 84 | 
             
                    @tmpl_dir = if @opts.fetch(:absolute_template_dir, false)
         | 
| 66 85 | 
             
                                  @opts.fetch(:tmpl_dir)
         | 
| 67 86 | 
             
                                else
         | 
| 68 | 
            -
                                  "#{@ | 
| 87 | 
            +
                                  "#{@root_dir}/#{@opts.fetch(:tmpl_dir, 'object_templates')}"
         | 
| 69 88 | 
             
                                end
         | 
| 70 | 
            -
                    @tmpl_path = Pathname.new("#{@tmpl_dir}/#{@opts.fetch(:tmpl_name, "#{@obj_type}.erb")}")
         | 
| 71 | 
            -
                    @type_path_map = @opts.fetch(:type_path_map, {})
         | 
| 72 89 | 
             
                    @obj_path = new_obj_path
         | 
| 90 | 
            +
                    @spec_tmpl = @opts.fetch(:spec_template, File.expand_path(File.join(__dir__, '../resources/generic_spec.erb')))
         | 
| 73 91 | 
             
                  end
         | 
| 74 92 |  | 
| 75 93 | 
             
                  def validate_class_vars
         | 
| 76 94 | 
             
                    raise AbideDevUtils::Errors::PathNotDirectoryError, @root_dir unless Dir.exist? @root_dir
         | 
| 77 95 | 
             
                    raise AbideDevUtils::Errors::PathNotDirectoryError, @tmpl_dir unless Dir.exist? @tmpl_dir
         | 
| 78 | 
            -
                    raise AbideDevUtils::Errors::Ppt::TemplateNotFoundError, @tmpl_path.to_s unless @tmpl_path.file?
         | 
| 79 96 | 
             
                  end
         | 
| 80 97 |  | 
| 81 98 | 
             
                  def basename(obj_name)
         | 
| 82 99 | 
             
                    obj_name.split('::')[-1]
         | 
| 83 100 | 
             
                  end
         | 
| 84 101 |  | 
| 85 | 
            -
                  def  | 
| 86 | 
            -
                     | 
| 87 | 
            -
             | 
| 88 | 
            -
             | 
| 89 | 
            -
             | 
| 102 | 
            +
                  def prefix
         | 
| 103 | 
            +
                    pfx = basename.match(OBJ_PREFIX)
         | 
| 104 | 
            +
                    return pfx[1] unless pfx.empty?
         | 
| 105 | 
            +
                  end
         | 
| 106 | 
            +
             | 
| 107 | 
            +
                  def templates
         | 
| 108 | 
            +
                    return [] if Dir.entries(tmpl_dir).empty?
         | 
| 109 | 
            +
             | 
| 110 | 
            +
                    file_names = Dir.entries(tmpl_dir).select { |f| f.match?(TMPL_PATTERN) }
         | 
| 111 | 
            +
                    file_names.map { |i| File.join(tmpl_dir, i) }
         | 
| 112 | 
            +
                  end
         | 
| 113 | 
            +
             | 
| 114 | 
            +
                  def template_data(query)
         | 
| 115 | 
            +
                    raise AbideDevUtils::Errors::Ppt::TemplateNotFoundError, @tmpl_dir if Dir.entries(@tmpl_dir).empty?
         | 
| 116 | 
            +
             | 
| 117 | 
            +
                    data = {}
         | 
| 118 | 
            +
                    pattern = /#{Regexp.quote(query)}/
         | 
| 119 | 
            +
                    templates.each do |i|
         | 
| 120 | 
            +
                      pn = Pathname.new(i)
         | 
| 121 | 
            +
                      next unless pn.basename.to_s.match?(pattern)
         | 
| 122 | 
            +
             | 
| 123 | 
            +
                      data[:path] = pn.to_s
         | 
| 124 | 
            +
                      data[:fname] = pn.basename.to_s
         | 
| 90 125 | 
             
                    end
         | 
| 126 | 
            +
                    raise AbideDevUtils::Errors::Ppt::TemplateNotFoundError, @tmpl_dir unless data.key?(:fname)
         | 
| 127 | 
            +
             | 
| 128 | 
            +
                    data[:ext] = data[:fname].match?(VALID_EXT) ? data[:fname].match(VALID_EXT)[1] : '.pp'
         | 
| 129 | 
            +
                    data[:pfx] = data[:fname].match?(OBJ_PREFIX) ? data[:fname].match(OBJ_PREFIX)[1] : 'c-'
         | 
| 130 | 
            +
                    data[:spec_base] = PREFIX_TEST_PATH[data[:pfx]]
         | 
| 131 | 
            +
                    data[:obj_name] = normalize_obj_name(data.dup)
         | 
| 132 | 
            +
                    data[:spec_name] = "#{@obj_name.split('::')[-1]}_spec.rb"
         | 
| 133 | 
            +
                    data[:spec_path] = spec_path(data[:spec_base], data[:spec_name])
         | 
| 134 | 
            +
                    data
         | 
| 135 | 
            +
                  end
         | 
| 136 | 
            +
             | 
| 137 | 
            +
                  def normalize_obj_name(data)
         | 
| 138 | 
            +
                    new_name = data[:fname].slice(/^(?:#{Regexp.quote(data[:pfx])})?(?<name>[^\s.]+)(?:#{Regexp.quote(data[:ext])})?\.erb$/, 'name')
         | 
| 139 | 
            +
                    "#{new_name}#{data[:ext]}"
         | 
| 140 | 
            +
                  end
         | 
| 141 | 
            +
             | 
| 142 | 
            +
                  def render(path)
         | 
| 143 | 
            +
                    ERB.new(File.read(path), 0, '<>-').result(binding)
         | 
| 91 144 | 
             
                  end
         | 
| 92 145 |  | 
| 93 146 | 
             
                  def namespace_format(name)
         | 
| 94 147 | 
             
                    name.split(':').reject(&:empty?).join('::')
         | 
| 95 148 | 
             
                  end
         | 
| 96 149 |  | 
| 97 | 
            -
                  def  | 
| 150 | 
            +
                  def new_obj_path
         | 
| 98 151 | 
             
                    parts = @obj_name.split('::')[1..-2]
         | 
| 99 152 | 
             
                    parts.insert(0, 'manifests')
         | 
| 100 153 | 
             
                    parts.insert(-1, "#{basename(@obj_name)}#{DEFAULT_EXT}")
         | 
| @@ -102,27 +155,13 @@ module AbideDevUtils | |
| 102 155 | 
             
                    path.to_s
         | 
| 103 156 | 
             
                  end
         | 
| 104 157 |  | 
| 105 | 
            -
                  def  | 
| 106 | 
            -
                     | 
| 107 | 
            -
                     | 
| 108 | 
            -
             | 
| 109 | 
            -
                     | 
| 110 | 
            -
             | 
| 111 | 
            -
                     | 
| 112 | 
            -
                      abs_path = Pathname.new(map_val).absolute? ? map_val : "#{Dir.pwd}/#{map_val}"
         | 
| 113 | 
            -
                      "#{abs_path}/#{basename(@obj_name)}#{DEFAULT_EXT}"
         | 
| 114 | 
            -
                    end
         | 
| 115 | 
            -
                  end
         | 
| 116 | 
            -
             | 
| 117 | 
            -
                  def custom_obj_path_from_hash(map_val, obj_name)
         | 
| 118 | 
            -
                    raise AbideDevUtils::Errors::Ppt::CustomObjPathKeyError, map_val unless map_val.key?(:path)
         | 
| 119 | 
            -
             | 
| 120 | 
            -
                    abs_path = Pathname.new(map_val[:path]).absolute? ? map_val[:path] : "#{Dir.pwd}/#{map_val[:path]}"
         | 
| 121 | 
            -
                    if map_val.key?(:extension)
         | 
| 122 | 
            -
                      "#{abs_path}/#{basename(obj_name)}#{map_val[:extension]}"
         | 
| 123 | 
            -
                    else
         | 
| 124 | 
            -
                      "#{abs_path}/#{basename(obj_name)}#{DEFAULT_EXT}"
         | 
| 125 | 
            -
                    end
         | 
| 158 | 
            +
                  def spec_path(base_dir, spec_name)
         | 
| 159 | 
            +
                    parts = @obj_name.split('::')[1..-2]
         | 
| 160 | 
            +
                    parts.insert(0, 'spec')
         | 
| 161 | 
            +
                    parts.insert(1, base_dir)
         | 
| 162 | 
            +
                    parts.insert(-1, spec_name)
         | 
| 163 | 
            +
                    path = @root_dir + Pathname.new(parts.join('/'))
         | 
| 164 | 
            +
                    path.to_s
         | 
| 126 165 | 
             
                  end
         | 
| 127 166 | 
             
                end
         | 
| 128 167 | 
             
              end
         | 
| @@ -15,7 +15,7 @@ module AbideDevUtils | |
| 15 15 | 
             
                  type = opts.fetch(:type, 'cis')
         | 
| 16 16 | 
             
                  case type.downcase
         | 
| 17 17 | 
             
                  when 'cis'
         | 
| 18 | 
            -
                    AbideDevUtils::XCCDF::CIS::Hiera.new(xccdf_file, parent_key_prefix: opts[:parent_key_prefix])
         | 
| 18 | 
            +
                    AbideDevUtils::XCCDF::CIS::Hiera.new(xccdf_file, parent_key_prefix: opts[:parent_key_prefix], num: opts[:num])
         | 
| 19 19 | 
             
                  else
         | 
| 20 20 | 
             
                    AbideDevUtils::Output.simple("XCCDF type #{type} is unsupported!")
         | 
| 21 21 | 
             
                  end
         | 
| @@ -35,13 +35,13 @@ module AbideDevUtils | |
| 35 35 | 
             
                    # @param parent_key_prefix [String] a string to be prepended to the
         | 
| 36 36 | 
             
                    #   top-level key in the Hiera structure. Useful for namespacing
         | 
| 37 37 | 
             
                    #   the top-level key.
         | 
| 38 | 
            -
                    def initialize(xccdf_file, parent_key_prefix: nil)
         | 
| 38 | 
            +
                    def initialize(xccdf_file, parent_key_prefix: nil, num: false)
         | 
| 39 39 | 
             
                      @doc = parse(xccdf_file)
         | 
| 40 40 | 
             
                      @title = xpath(XPATHS[:benchmark][:title]).children.to_s
         | 
| 41 41 | 
             
                      @version = xpath(XPATHS[:benchmark][:version]).children.to_s
         | 
| 42 42 | 
             
                      @profiles = xpath(XPATHS[:profiles][:all])
         | 
| 43 43 | 
             
                      @parent_key = make_parent_key(@doc, parent_key_prefix)
         | 
| 44 | 
            -
                      @hash = make_hash(@doc, @parent_key)
         | 
| 44 | 
            +
                      @hash = make_hash(@doc, @parent_key, num)
         | 
| 45 45 | 
             
                    end
         | 
| 46 46 |  | 
| 47 47 | 
             
                    def yaml_title
         | 
| @@ -92,13 +92,16 @@ module AbideDevUtils | |
| 92 92 |  | 
| 93 93 | 
             
                    attr_accessor :doc, :hash, :parent_key, :profiles
         | 
| 94 94 |  | 
| 95 | 
            +
                    # Accepts a path to an xccdf xml file and returns a parsed Nokogiri object of the file
         | 
| 96 | 
            +
                    # @param xccdf_file [String] path to an xccdf xml file
         | 
| 97 | 
            +
                    # @return [Nokogiri::Node] A Nokogiri node object of the XML document
         | 
| 95 98 | 
             
                    def parse(xccdf_file)
         | 
| 96 99 | 
             
                      raise AbideDevUtils::Errors::FileNotFoundError, xccdf_file unless File.file?(xccdf_file)
         | 
| 97 100 |  | 
| 98 101 | 
             
                      Nokogiri.XML(File.open(xccdf_file))
         | 
| 99 102 | 
             
                    end
         | 
| 100 103 |  | 
| 101 | 
            -
                    def make_hash(doc, parent_key)
         | 
| 104 | 
            +
                    def make_hash(doc, parent_key, num)
         | 
| 102 105 | 
             
                      hash = { parent_key.to_sym => { title: @title, version: @version } }
         | 
| 103 106 | 
             
                      profiles = doc.xpath('xccdf:Benchmark/xccdf:Profile')
         | 
| 104 107 | 
             
                      profiles.each do |p|
         | 
| @@ -106,7 +109,7 @@ module AbideDevUtils | |
| 106 109 | 
             
                        hash[parent_key.to_sym][title.to_sym] = []
         | 
| 107 110 | 
             
                        selects = p.xpath('./xccdf:select')
         | 
| 108 111 | 
             
                        selects.each do |s|
         | 
| 109 | 
            -
                          hash[parent_key.to_sym][title.to_sym] << normalize_ctrl_name(s['idref'].to_s)
         | 
| 112 | 
            +
                          hash[parent_key.to_sym][title.to_sym] << normalize_ctrl_name(s['idref'].to_s, num)
         | 
| 110 113 | 
             
                        end
         | 
| 111 114 | 
             
                      end
         | 
| 112 115 | 
             
                      hash
         | 
| @@ -114,7 +117,7 @@ module AbideDevUtils | |
| 114 117 |  | 
| 115 118 | 
             
                    def normalize_str(str)
         | 
| 116 119 | 
             
                      nstr = str.downcase
         | 
| 117 | 
            -
                      nstr.gsub!(/[^a- | 
| 120 | 
            +
                      nstr.gsub!(/[^a-z0-9]$/, '')
         | 
| 118 121 | 
             
                      nstr.gsub!(/^[^a-z]/, '')
         | 
| 119 122 | 
             
                      nstr.gsub!(/^(l1_|l2_|ng_)/, '')
         | 
| 120 123 | 
             
                      nstr.delete!('(/|\\)')
         | 
| @@ -128,11 +131,23 @@ module AbideDevUtils | |
| 128 131 | 
             
                      prof_name
         | 
| 129 132 | 
             
                    end
         | 
| 130 133 |  | 
| 131 | 
            -
                    def normalize_ctrl_name(ctrl)
         | 
| 132 | 
            -
                       | 
| 134 | 
            +
                    def normalize_ctrl_name(ctrl, num)
         | 
| 135 | 
            +
                      return num_normalize_ctrl(ctrl) if num
         | 
| 136 | 
            +
             | 
| 137 | 
            +
                      name_normalize_ctrl(ctrl)
         | 
| 138 | 
            +
                    end
         | 
| 139 | 
            +
             | 
| 140 | 
            +
                    def name_normalize_ctrl(ctrl)
         | 
| 141 | 
            +
                      new_ctrl = ctrl.split('benchmarks_rule_')[-1].gsub(CONTROL_PREFIX, '')
         | 
| 133 142 | 
             
                      normalize_str(new_ctrl)
         | 
| 134 143 | 
             
                    end
         | 
| 135 144 |  | 
| 145 | 
            +
                    def num_normalize_ctrl(ctrl)
         | 
| 146 | 
            +
                      part = ctrl.split('benchmarks_rule_')[-1]
         | 
| 147 | 
            +
                      numpart = CONTROL_PREFIX.match(part).to_s.chop.gsub(UNDERSCORED, '_')
         | 
| 148 | 
            +
                      "c#{numpart}"
         | 
| 149 | 
            +
                    end
         | 
| 150 | 
            +
             | 
| 136 151 | 
             
                    def make_parent_key(doc, prefix)
         | 
| 137 152 | 
             
                      doc_title = normalize_str(doc.xpath(XPATHS[:benchmark][:title]).children.to_s)
         | 
| 138 153 | 
             
                      return doc_title if prefix.nil?
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: abide_dev_utils
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.5.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Heston Snodgrass
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: exe
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2021- | 
| 11 | 
            +
            date: 2021-06-16 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: nokogiri
         | 
| @@ -80,6 +80,20 @@ dependencies: | |
| 80 80 | 
             
                - - "~>"
         | 
| 81 81 | 
             
                  - !ruby/object:Gem::Version
         | 
| 82 82 | 
             
                    version: '1.11'
         | 
| 83 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 84 | 
            +
              name: selenium-webdriver
         | 
| 85 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 86 | 
            +
                requirements:
         | 
| 87 | 
            +
                - - "~>"
         | 
| 88 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 89 | 
            +
                    version: 4.0.0.beta4
         | 
| 90 | 
            +
              type: :runtime
         | 
| 91 | 
            +
              prerelease: false
         | 
| 92 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 93 | 
            +
                requirements:
         | 
| 94 | 
            +
                - - "~>"
         | 
| 95 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 96 | 
            +
                    version: 4.0.0.beta4
         | 
| 83 97 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 84 98 | 
             
              name: bundler
         | 
| 85 99 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -108,6 +122,20 @@ dependencies: | |
| 108 122 | 
             
                - - ">="
         | 
| 109 123 | 
             
                  - !ruby/object:Gem::Version
         | 
| 110 124 | 
             
                    version: '0'
         | 
| 125 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 126 | 
            +
              name: console
         | 
| 127 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 128 | 
            +
                requirements:
         | 
| 129 | 
            +
                - - ">="
         | 
| 130 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 131 | 
            +
                    version: '0'
         | 
| 132 | 
            +
              type: :development
         | 
| 133 | 
            +
              prerelease: false
         | 
| 134 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 135 | 
            +
                requirements:
         | 
| 136 | 
            +
                - - ">="
         | 
| 137 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 138 | 
            +
                    version: '0'
         | 
| 111 139 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 112 140 | 
             
              name: github_changelog_generator
         | 
| 113 141 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -242,11 +270,13 @@ executables: | |
| 242 270 | 
             
            extensions: []
         | 
| 243 271 | 
             
            extra_rdoc_files: []
         | 
| 244 272 | 
             
            files:
         | 
| 273 | 
            +
            - ".dockerignore"
         | 
| 245 274 | 
             
            - ".gitignore"
         | 
| 246 275 | 
             
            - ".rspec"
         | 
| 247 276 | 
             
            - ".rubocop.yml"
         | 
| 248 277 | 
             
            - ".rubocop_todo.yml"
         | 
| 249 278 | 
             
            - CHANGELOG.md
         | 
| 279 | 
            +
            - Dockerfile
         | 
| 250 280 | 
             
            - Gemfile
         | 
| 251 281 | 
             
            - LICENSE.txt
         | 
| 252 282 | 
             
            - README.md
         | 
| @@ -259,10 +289,12 @@ files: | |
| 259 289 | 
             
            - lib/abide_dev_utils.rb
         | 
| 260 290 | 
             
            - lib/abide_dev_utils/cli.rb
         | 
| 261 291 | 
             
            - lib/abide_dev_utils/cli/abstract.rb
         | 
| 292 | 
            +
            - lib/abide_dev_utils/cli/comply.rb
         | 
| 262 293 | 
             
            - lib/abide_dev_utils/cli/jira.rb
         | 
| 263 294 | 
             
            - lib/abide_dev_utils/cli/puppet.rb
         | 
| 264 295 | 
             
            - lib/abide_dev_utils/cli/test.rb
         | 
| 265 296 | 
             
            - lib/abide_dev_utils/cli/xccdf.rb
         | 
| 297 | 
            +
            - lib/abide_dev_utils/comply.rb
         | 
| 266 298 | 
             
            - lib/abide_dev_utils/config.rb
         | 
| 267 299 | 
             
            - lib/abide_dev_utils/constants.rb
         | 
| 268 300 | 
             
            - lib/abide_dev_utils/errors.rb
         | 
| @@ -278,6 +310,7 @@ files: | |
| 278 310 | 
             
            - lib/abide_dev_utils/ppt/coverage.rb
         | 
| 279 311 | 
             
            - lib/abide_dev_utils/ppt/new_obj.rb
         | 
| 280 312 | 
             
            - lib/abide_dev_utils/prompt.rb
         | 
| 313 | 
            +
            - lib/abide_dev_utils/resources/generic_spec.erb
         | 
| 281 314 | 
             
            - lib/abide_dev_utils/utils/general.rb
         | 
| 282 315 | 
             
            - lib/abide_dev_utils/validate.rb
         | 
| 283 316 | 
             
            - lib/abide_dev_utils/version.rb
         |