mirror of
https://github.com/inspec/inspec
synced 2024-11-24 21:53:15 +00:00
feature: attribute handling
This commit is contained in:
parent
753839f21f
commit
c7a49056c4
11 changed files with 123 additions and 6 deletions
2
examples/profile-attribute.yml
Normal file
2
examples/profile-attribute.yml
Normal file
|
@ -0,0 +1,2 @@
|
|||
user: bob
|
||||
password: secret
|
3
examples/profile-attribute/README.md
Normal file
3
examples/profile-attribute/README.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
# Example InSpec Profile with Attributes
|
||||
|
||||
This profile uses InSpec attributes to parameterize a profile.
|
20
examples/profile-attribute/controls/example.rb
Normal file
20
examples/profile-attribute/controls/example.rb
Normal file
|
@ -0,0 +1,20 @@
|
|||
# encoding: utf-8
|
||||
val_user = attribute('user', default: 'alice', required: true)
|
||||
val_password = attribute('password', required: true)
|
||||
|
||||
# that works
|
||||
describe 'bob' do
|
||||
it { should eq val_user.value }
|
||||
end
|
||||
|
||||
describe 'secret' do
|
||||
it { should eq val_password.value }
|
||||
end
|
||||
|
||||
describe val_user.value do
|
||||
it { should eq 'bob' }
|
||||
end
|
||||
|
||||
describe val_password.value do
|
||||
it { should eq 'secret' }
|
||||
end
|
8
examples/profile-attribute/inspec.yml
Normal file
8
examples/profile-attribute/inspec.yml
Normal file
|
@ -0,0 +1,8 @@
|
|||
name: profile-attribute
|
||||
title: InSpec Profile
|
||||
maintainer: The Authors
|
||||
copyright: The Authors
|
||||
copyright_email: you@example.com
|
||||
license: All Rights Reserved
|
||||
summary: An InSpec Compliance Profile
|
||||
version: 0.1.0
|
10
examples/profile-inheritance/inspec.yml
Normal file
10
examples/profile-inheritance/inspec.yml
Normal file
|
@ -0,0 +1,10 @@
|
|||
name: inheritance
|
||||
title: InSpec example inheritance
|
||||
maintainer: Chef Software, Inc.
|
||||
copyright: Chef Software, Inc.
|
||||
copyright_email: support@chef.io
|
||||
license: Apache 2 license
|
||||
summary: Demonstrates the use of InSpec profile inheritance
|
||||
version: 1.0.0
|
||||
supports:
|
||||
- os-family: unix
|
|
@ -9,6 +9,7 @@ require 'json'
|
|||
require 'pp'
|
||||
require 'utils/base_cli'
|
||||
require 'utils/json_log'
|
||||
require 'yaml'
|
||||
|
||||
class Inspec::InspecCLI < Inspec::BaseCLI # rubocop:disable Metrics/ClassLength
|
||||
class_option :diagnose, type: :boolean,
|
||||
|
@ -106,9 +107,18 @@ class Inspec::InspecCLI < Inspec::BaseCLI # rubocop:disable Metrics/ClassLength
|
|||
|
||||
desc 'exec PATHS', 'run all test files at the specified PATH.'
|
||||
exec_options
|
||||
option :attr_file, type: :array
|
||||
def exec(*targets)
|
||||
diagnose
|
||||
run_tests(targets, opts)
|
||||
o = opts.dup
|
||||
# parse attribute file
|
||||
unless o['attr_file'].nil?
|
||||
o['attrs'] = {}
|
||||
o['attr_file'].each do |file|
|
||||
o['attrs'] = o['attrs'].merge(YAML.load_file(file))
|
||||
end
|
||||
end
|
||||
run_tests(targets, o)
|
||||
end
|
||||
|
||||
desc 'detect', 'detect the target OS'
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# encoding: utf-8
|
||||
|
||||
module Inspec
|
||||
autoload :Attribute, 'inspec/objects/attribute'
|
||||
autoload :Control, 'inspec/objects/control'
|
||||
autoload :EachLoop, 'inspec/objects/each_loop'
|
||||
autoload :List, 'inspec/objects/list'
|
||||
|
|
35
lib/inspec/objects/attribute.rb
Normal file
35
lib/inspec/objects/attribute.rb
Normal file
|
@ -0,0 +1,35 @@
|
|||
# encoding:utf-8
|
||||
|
||||
module Inspec
|
||||
class Attribute
|
||||
attr_accessor :name
|
||||
def initialize(name, options)
|
||||
@name = name
|
||||
@opts = options
|
||||
@value = nil
|
||||
end
|
||||
|
||||
# implicit call is done by inspec to determine the value of an attribute
|
||||
def value(newvalue = nil)
|
||||
unless newvalue.nil?
|
||||
@value = newvalue
|
||||
end
|
||||
@value || default
|
||||
end
|
||||
|
||||
def default
|
||||
@opts[:default]
|
||||
end
|
||||
|
||||
def to_hash
|
||||
{
|
||||
name: @name,
|
||||
options: @opts,
|
||||
}
|
||||
end
|
||||
|
||||
def to_s
|
||||
"Attribute #{@name} with #{@value}"
|
||||
end
|
||||
end
|
||||
end
|
|
@ -57,6 +57,7 @@ module Inspec
|
|||
|
||||
def info
|
||||
res = params.dup
|
||||
# add information about the controls
|
||||
controls = res[:controls].map do |id, rule|
|
||||
next if id.to_s.empty?
|
||||
data = rule.dup
|
||||
|
@ -67,6 +68,9 @@ module Inspec
|
|||
[id, data]
|
||||
end
|
||||
res[:controls] = Hash[controls.compact]
|
||||
|
||||
# add information about the required attributes
|
||||
res[:attributes] = res[:attributes].map(&:to_hash) unless res[:attributes].nil? || res[:attributes].empty?
|
||||
res
|
||||
end
|
||||
|
||||
|
@ -248,13 +252,16 @@ module Inspec
|
|||
f = load_rule_filepath(prefix, rule)
|
||||
load_rule(rule, f, controls, groups)
|
||||
end
|
||||
params[:attributes] = runner.attributes
|
||||
else
|
||||
# load from context
|
||||
@runner_context.rules.values.each do |rule|
|
||||
f = load_rule_filepath(prefix, rule)
|
||||
load_rule(rule, f, controls, groups)
|
||||
end
|
||||
params[:attributes] = @runner_context.attributes
|
||||
end
|
||||
params
|
||||
end
|
||||
|
||||
def load_rule_filepath(prefix, rule)
|
||||
|
|
|
@ -6,10 +6,12 @@ require 'inspec/rule'
|
|||
require 'inspec/dsl'
|
||||
require 'inspec/require_loader'
|
||||
require 'securerandom'
|
||||
require 'inspec/objects/attribute'
|
||||
|
||||
module Inspec
|
||||
class ProfileContext # rubocop:disable Metrics/ClassLength
|
||||
attr_reader :rules
|
||||
attr_reader :attributes
|
||||
def initialize(profile_id, backend, conf)
|
||||
if backend.nil?
|
||||
fail 'ProfileContext is initiated with a backend == nil. ' \
|
||||
|
@ -21,7 +23,7 @@ module Inspec
|
|||
@conf = conf.dup
|
||||
@rules = {}
|
||||
@require_loader = ::Inspec::RequireLoader.new
|
||||
|
||||
@attributes = []
|
||||
reload_dsl
|
||||
end
|
||||
|
||||
|
@ -84,6 +86,19 @@ module Inspec
|
|||
end
|
||||
end
|
||||
|
||||
def register_value(&block)
|
||||
@values.push(block)
|
||||
end
|
||||
|
||||
def register_attribute(name, options = {})
|
||||
# we need to return an attribute object, in order to allow lazy access
|
||||
attr = Attribute.new(name, options)
|
||||
# set value
|
||||
attr.value(@conf['attrs'][attr.name]) unless @conf['attrs'].nil?
|
||||
@attributes.push(attr)
|
||||
attr
|
||||
end
|
||||
|
||||
def set_header(field, val)
|
||||
@current_load[field] = val
|
||||
end
|
||||
|
@ -180,9 +195,9 @@ module Inspec
|
|||
profile_context_owner.register_rule(control, &block) unless control.nil?
|
||||
end
|
||||
|
||||
# TODO: mock method for attributes; import attribute handling
|
||||
define_method :attributes do |_name, _options|
|
||||
nil
|
||||
# method for attributes; import attribute handling
|
||||
define_method :attribute do |name, options|
|
||||
profile_context_owner.register_attribute(name, options)
|
||||
end
|
||||
|
||||
define_method :skip_control do |id|
|
||||
|
|
|
@ -15,7 +15,7 @@ require 'inspec/metadata'
|
|||
module Inspec
|
||||
class Runner # rubocop:disable Metrics/ClassLength
|
||||
extend Forwardable
|
||||
attr_reader :backend, :rules
|
||||
attr_reader :backend, :rules, :attributes
|
||||
def initialize(conf = {})
|
||||
@rules = {}
|
||||
@conf = conf.dup
|
||||
|
@ -26,6 +26,9 @@ module Inspec
|
|||
RunnerRspec.new(@conf)
|
||||
end
|
||||
|
||||
# list of profile attributes
|
||||
@attributes = []
|
||||
load_attributes(@conf)
|
||||
configure_transport
|
||||
end
|
||||
|
||||
|
@ -110,6 +113,9 @@ module Inspec
|
|||
tests = [tests] unless tests.is_a? Array
|
||||
tests.each { |t| add_test_to_context(t, ctx) }
|
||||
|
||||
# merge all collect all attributes
|
||||
@attributes |= ctx.attributes
|
||||
|
||||
# process the resulting rules
|
||||
filter_controls(ctx.rules, options[:controls]).each do |rule_id, rule|
|
||||
register_rule(rule_id, rule)
|
||||
|
|
Loading…
Reference in a new issue