mirror of
https://github.com/inspec/inspec
synced 2024-11-10 07:04:15 +00:00
introduce secrets backend
This commit is contained in:
parent
c7a49056c4
commit
f1faf47112
12 changed files with 99 additions and 41 deletions
|
@ -1,3 +1,14 @@
|
||||||
# Example InSpec Profile with Attributes
|
# Example InSpec Profile with Attributes
|
||||||
|
|
||||||
This profile uses InSpec attributes to parameterize a profile.
|
This profile uses InSpec attributes to parameterize a profile.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```
|
||||||
|
$ inspec exec examples/profile-attribute --attrs examples/profile-attribute.yml
|
||||||
|
....
|
||||||
|
|
||||||
|
Finished in 0.00178 seconds (files took 0.48529 seconds to load)
|
||||||
|
4 examples, 0 failures
|
||||||
|
|
||||||
|
```
|
||||||
|
|
|
@ -1,20 +1,11 @@
|
||||||
# encoding: utf-8
|
# encoding: utf-8
|
||||||
val_user = attribute('user', default: 'alice', required: true)
|
val_user = attribute('user', default: 'alice', description: 'An identification for the user')
|
||||||
val_password = attribute('password', required: true)
|
val_password = attribute('password', description: 'A value for the password')
|
||||||
|
|
||||||
# that works
|
describe val_user do
|
||||||
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' }
|
it { should eq 'bob' }
|
||||||
end
|
end
|
||||||
|
|
||||||
describe val_password.value do
|
describe val_password do
|
||||||
it { should eq 'secret' }
|
it { should eq 'secret' }
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
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,7 +9,6 @@ require 'json'
|
||||||
require 'pp'
|
require 'pp'
|
||||||
require 'utils/base_cli'
|
require 'utils/base_cli'
|
||||||
require 'utils/json_log'
|
require 'utils/json_log'
|
||||||
require 'yaml'
|
|
||||||
|
|
||||||
class Inspec::InspecCLI < Inspec::BaseCLI # rubocop:disable Metrics/ClassLength
|
class Inspec::InspecCLI < Inspec::BaseCLI # rubocop:disable Metrics/ClassLength
|
||||||
class_option :diagnose, type: :boolean,
|
class_option :diagnose, type: :boolean,
|
||||||
|
@ -107,17 +106,11 @@ class Inspec::InspecCLI < Inspec::BaseCLI # rubocop:disable Metrics/ClassLength
|
||||||
|
|
||||||
desc 'exec PATHS', 'run all test files at the specified PATH.'
|
desc 'exec PATHS', 'run all test files at the specified PATH.'
|
||||||
exec_options
|
exec_options
|
||||||
option :attr_file, type: :array
|
|
||||||
def exec(*targets)
|
def exec(*targets)
|
||||||
diagnose
|
diagnose
|
||||||
o = opts.dup
|
o = opts.dup
|
||||||
# parse attribute file
|
|
||||||
unless o['attr_file'].nil?
|
# run tests
|
||||||
o['attrs'] = {}
|
|
||||||
o['attr_file'].each do |file|
|
|
||||||
o['attrs'] = o['attrs'].merge(YAML.load_file(file))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
run_tests(targets, o)
|
run_tests(targets, o)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ module Inspec
|
||||||
autoload :CLI, 'inspec/plugins/cli'
|
autoload :CLI, 'inspec/plugins/cli'
|
||||||
autoload :Fetcher, 'inspec/plugins/fetcher'
|
autoload :Fetcher, 'inspec/plugins/fetcher'
|
||||||
autoload :SourceReader, 'inspec/plugins/source_reader'
|
autoload :SourceReader, 'inspec/plugins/source_reader'
|
||||||
|
autoload :Secret, 'inspec/plugins/secret'
|
||||||
end
|
end
|
||||||
|
|
||||||
# PLEASE NOTE: The Plugin system is an internal mechanism for connecting
|
# PLEASE NOTE: The Plugin system is an internal mechanism for connecting
|
||||||
|
|
15
lib/inspec/plugins/secret.rb
Normal file
15
lib/inspec/plugins/secret.rb
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
# author: Dominik Richter
|
||||||
|
# author: Christoph Hartmann
|
||||||
|
|
||||||
|
require 'utils/plugin_registry'
|
||||||
|
|
||||||
|
module Inspec
|
||||||
|
module Plugins
|
||||||
|
class Secret < PluginRegistry::Plugin
|
||||||
|
def self.plugin_registry
|
||||||
|
Inspec::SecretsBackend
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -86,17 +86,13 @@ module Inspec
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def register_value(&block)
|
|
||||||
@values.push(block)
|
|
||||||
end
|
|
||||||
|
|
||||||
def register_attribute(name, options = {})
|
def register_attribute(name, options = {})
|
||||||
# we need to return an attribute object, in order to allow lazy access
|
# we need to return an attribute object, to allow dermination of default values
|
||||||
attr = Attribute.new(name, options)
|
attr = Attribute.new(name, options)
|
||||||
# set value
|
# read value from given gived values
|
||||||
attr.value(@conf['attrs'][attr.name]) unless @conf['attrs'].nil?
|
attr.value(@conf['attributes'][attr.name]) unless @conf['attributes'].nil?
|
||||||
@attributes.push(attr)
|
@attributes.push(attr)
|
||||||
attr
|
attr.value
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_header(field, val)
|
def set_header(field, val)
|
||||||
|
|
|
@ -10,6 +10,7 @@ require 'inspec/backend'
|
||||||
require 'inspec/profile_context'
|
require 'inspec/profile_context'
|
||||||
require 'inspec/profile'
|
require 'inspec/profile'
|
||||||
require 'inspec/metadata'
|
require 'inspec/metadata'
|
||||||
|
require 'inspec/secrets'
|
||||||
# spec requirements
|
# spec requirements
|
||||||
|
|
||||||
module Inspec
|
module Inspec
|
||||||
|
@ -28,6 +29,7 @@ module Inspec
|
||||||
|
|
||||||
# list of profile attributes
|
# list of profile attributes
|
||||||
@attributes = []
|
@attributes = []
|
||||||
|
|
||||||
load_attributes(@conf)
|
load_attributes(@conf)
|
||||||
configure_transport
|
configure_transport
|
||||||
end
|
end
|
||||||
|
@ -48,6 +50,21 @@ module Inspec
|
||||||
@backend = Inspec::Backend.create(@conf)
|
@backend = Inspec::Backend.create(@conf)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# determine all attributes before the execution, fetch data from secrets backend
|
||||||
|
def load_attributes(options)
|
||||||
|
attributes = {}
|
||||||
|
# read endpoints for secrets eg. yml file
|
||||||
|
secrets_targets = options['attrs']
|
||||||
|
unless secrets_targets.nil?
|
||||||
|
secrets_targets.each do |target|
|
||||||
|
secrets = Inspec::SecretsBackend.resolve(target)
|
||||||
|
# merge hash values
|
||||||
|
attributes = attributes.merge(secrets.attributes) unless secrets.nil? || secrets.attributes.nil?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
options['attributes'] = attributes
|
||||||
|
end
|
||||||
|
|
||||||
def add_target(target, options = {})
|
def add_target(target, options = {})
|
||||||
profile = Inspec::Profile.for_target(target, options)
|
profile = Inspec::Profile.for_target(target, options)
|
||||||
fail "Could not resolve #{target} to valid input." if profile.nil?
|
fail "Could not resolve #{target} to valid input." if profile.nil?
|
||||||
|
|
19
lib/inspec/secrets.rb
Normal file
19
lib/inspec/secrets.rb
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
# author: Christoph Hartmann
|
||||||
|
# author: Dominik Richter
|
||||||
|
|
||||||
|
require 'inspec/plugins'
|
||||||
|
require 'utils/plugin_registry'
|
||||||
|
|
||||||
|
module Inspec
|
||||||
|
SecretsBackend = PluginRegistry.new
|
||||||
|
|
||||||
|
def self.secrets(version)
|
||||||
|
if version != 1
|
||||||
|
fail 'Only secrets version 1 is supported!'
|
||||||
|
end
|
||||||
|
Inspec::Plugins::Secret
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
require 'inspec/secrets/yaml'
|
23
lib/inspec/secrets/yaml.rb
Normal file
23
lib/inspec/secrets/yaml.rb
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
require 'yaml'
|
||||||
|
|
||||||
|
module Secrets
|
||||||
|
class YAML < Inspec.secrets(1)
|
||||||
|
name 'yaml'
|
||||||
|
|
||||||
|
attr_reader :attributes
|
||||||
|
|
||||||
|
def self.resolve(target)
|
||||||
|
unless target.is_a?(String) && File.file?(target) && target.end_with?('.yml')
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
new(target)
|
||||||
|
end
|
||||||
|
|
||||||
|
# array of yaml file paths
|
||||||
|
def initialize(target)
|
||||||
|
@attributes = ::YAML.load_file(target)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -55,6 +55,8 @@ module Inspec
|
||||||
desc: 'Which formatter to use: progress, documentation, json'
|
desc: 'Which formatter to use: progress, documentation, json'
|
||||||
option :color, type: :boolean, default: true,
|
option :color, type: :boolean, default: true,
|
||||||
desc: 'Use colors in output.'
|
desc: 'Use colors in output.'
|
||||||
|
option :attrs, type: :array,
|
||||||
|
desc: 'Load attributes file (experimental)'
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -39,7 +39,6 @@ describe 'inspec exec with json formatter' do
|
||||||
actual = profile.dup
|
actual = profile.dup
|
||||||
key = actual.delete('controls').keys
|
key = actual.delete('controls').keys
|
||||||
.find { |x| x =~ /generated from example.rb/ }
|
.find { |x| x =~ /generated from example.rb/ }
|
||||||
|
|
||||||
actual.must_equal({
|
actual.must_equal({
|
||||||
"name" => "profile",
|
"name" => "profile",
|
||||||
"title" => "InSpec Example Profile",
|
"title" => "InSpec Example Profile",
|
||||||
|
@ -55,6 +54,7 @@ describe 'inspec exec with json formatter' do
|
||||||
"controls/example.rb" => {"title"=>"/tmp profile", "controls"=>["tmp-1.0", key]},
|
"controls/example.rb" => {"title"=>"/tmp profile", "controls"=>["tmp-1.0", key]},
|
||||||
"controls/gordon.rb" => {"title"=>"Gordon Config Checks", "controls"=>["gordon-1.0"]},
|
"controls/gordon.rb" => {"title"=>"Gordon Config Checks", "controls"=>["gordon-1.0"]},
|
||||||
},
|
},
|
||||||
|
"attributes" => []
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue