Navigation Menu

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add automate fetcher for chef solo #227

Merged
merged 1 commit into from May 19, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 11 additions & 2 deletions files/default/handler/audit_report.rb
Expand Up @@ -27,6 +27,7 @@ def report
interval_time = node['audit']['interval']['time']
profiles = node['audit']['profiles']
quiet = node['audit']['quiet']
fetcher = node['audit']['fetcher']

# load inspec, supermarket bundle and compliance bundle
load_needed_dependencies
Expand All @@ -36,7 +37,9 @@ def report
reporters.include?('chef-server-compliance') ||
reporters.include?('chef-server-visibility') ||
reporters.include?('chef-server-automate') ||
node['audit']['fetcher'] == 'chef-server'
%w{chef-server chef-server-compliance chef-server-visibility chef-server-automate}.include?(fetcher)

load_automate_fetcher if fetcher == 'chef-automate'

# ensure authentication for Chef Compliance is in place, see libraries/compliance.rb
login_to_compliance(server, user, token, refresh_token) if reporters.include?('chef-compliance')
Expand Down Expand Up @@ -95,11 +98,17 @@ def load_needed_dependencies

# we expect inspec to be loaded before
def load_chef_fetcher
Chef::Log.debug "Load vendored ruby files from: #{cookbook_vendor_path}"
Chef::Log.debug "Load Chef Server fetcher from: #{cookbook_vendor_path}"
$LOAD_PATH.unshift(cookbook_vendor_path)
require 'chef-server/fetcher'
end

def load_automate_fetcher
Chef::Log.debug "Load Chef Automate fetcher from: #{cookbook_vendor_path}"
$LOAD_PATH.unshift(cookbook_vendor_path)
require 'chef-automate/fetcher'
end

# sets format to json-min when chef-compliance, json when chef-automate
def get_opts(format, quiet)
output = quiet ? ::File::NULL : $stdout
Expand Down
69 changes: 69 additions & 0 deletions files/default/vendor/chef-automate/fetcher.rb
@@ -0,0 +1,69 @@
module ChefAutomate
class Fetcher < Compliance::Fetcher
name 'chef-automate'

# it positions itself before `compliance` fetcher
# only load it, if you want to use audit cookbook in Chef Solo with Chef Automate
priority 502

def self.resolve(target)
uri = if target.is_a?(String) && URI(target).scheme == 'compliance'
URI(target)
elsif target.respond_to?(:key?) && target.key?(:compliance)
URI("compliance://#{target[:compliance]}")
end

return nil if uri.nil?

# we have detailed information available in our lockfile, no need to ask the server
if target.respond_to?(:key?) && target.key?(:url)
profile_fetch_url = target[:url]
config = {}
else
# verifies that the target e.g base/ssh exists
profile = sanitize_profile_name(uri)
owner, id = profile.split('/')
profile_path = "/compliance/profiles/#{owner}/#{id}/tar"
dc = Chef::Config[:data_collector]
url = URI(dc[:server_url])
url.path = profile_path
profile_fetch_url = url.to_s
config = {
'token' => dc[:token],
}
end

new(profile_fetch_url, config)
rescue URI::Error => _e
nil
end

# returns a parsed url for `admin/profile` or `compliance://admin/profile`
# TODO: remove in future, copied from inspec to support older versions of inspec
def self.sanitize_profile_name(profile)
if URI(profile).scheme == 'compliance'
uri = URI(profile)
else
uri = URI("compliance://#{profile}")
end
uri.to_s.sub(%r{^compliance:\/\/}, '')
end

def initialize(url, opts)
options = {
'insecure' => true,
'token' => opts['token'],
'server_type' => 'automate',
'automate' => {
'ent' => '',
'token_type' => 'dctoken',
},
}
super(url, options)
end

def to_s
'Chef Automate for Chef Solo Fetcher'
end
end
end
2 changes: 1 addition & 1 deletion libraries/compliance.rb
Expand Up @@ -39,7 +39,7 @@ def upload_profile(config, owner, profile_name, path)
Compliance::API.upload(config, owner, profile_name, path)
end

# TODO: temporary, we should not use this
# TODO: temporary, we should use a stateless approach
# TODO: harmonize with CLI login_refreshtoken method
def login_to_compliance(server, user, access_token, refresh_token)
if !refresh_token.nil?
Expand Down