-
Notifications
You must be signed in to change notification settings - Fork 59
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
Migrate to chef_handler from resource-based audit #71
Closed
Closed
Changes from 11 commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
d175f74
Migrated to chef_handler so reporting on a chef-client run won't incl…
8d8532c
Fixed bug where compliance_profile didn't have access to node
91e4022
Silence logging when running in quiet mode
ff15b5b
Fixed reporting issue with creating results
5c5d80b
Fixed error with initializing report_results
70cd08a
Added better logging to compliance run
03330e5
Fixed bug with how results are initialized, refactored reporting
5bf6c3a
Fixed another bug with results initialization
5425db1
Fixed misnamed method name
b5fb990
Properly handle http in report
0b87d3d
Fixed problem with owners being properly reported by profile
2e18a99
Added debug logging for troubleshooting
ec73452
Fixed bug where node name was not provided
43939a0
Made environment _default if it doesn't exist
79185ca
Changed node to fqdn and updated environment
20bca56
Removed puts statements
7386313
Rewrote unit tests to reflect smaller cookbook footprint
69c8ecc
Reverted back to dokken kitchen.yml and added vagrant alternative
3c01d23
Fixed rubocop warnings, set environment if it is defined
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,78 +1,37 @@ | ||
--- | ||
driver: | ||
name: dokken | ||
name: vagrant | ||
chef_version: 12.7.2 | ||
privileged: true # because Docker and SystemD/Upstart | ||
|
||
transport: | ||
name: dokken | ||
|
||
provisioner: | ||
name: dokken | ||
name: chef_zero | ||
|
||
verifier: | ||
name: inspec | ||
sudo: false | ||
|
||
platforms: | ||
- name: ubuntu-12.04 | ||
driver: | ||
image: ubuntu:12.04 | ||
- name: ubuntu-14.04 | ||
driver: | ||
image: ubuntu:14.04 | ||
- name: ubuntu-15.10 | ||
driver: | ||
image: ubuntu:15.10 | ||
pid_one_command: /bin/systemd | ||
- name: centos-6.6 | ||
driver: | ||
image: centos:6.6 | ||
- name: centos-6.7 | ||
driver: | ||
image: centos:6.7 | ||
intermediate_instructions: | ||
- RUN yum install -y initscripts | ||
- name: centos-7 | ||
driver: | ||
image: centos:7 | ||
pid_one_command: /usr/lib/systemd/systemd | ||
- name: oracle-6.6 | ||
driver: | ||
image: oraclelinux:6.6 | ||
- name: oracle-6.7 | ||
driver: | ||
image: oraclelinux:6.7 | ||
- name: oracle-7.1 | ||
driver: | ||
image: oraclelinux:7.1 | ||
pid_one_command: /usr/lib/systemd/systemd | ||
- name: debian-7 | ||
driver: | ||
image: debian:7 | ||
intermediate_instructions: | ||
- RUN /usr/bin/apt-get update | ||
- RUN /usr/bin/apt-get install -y procps | ||
- name: debian-8 | ||
driver: | ||
image: debian:8 | ||
pid_one_command: /bin/systemd | ||
- name: centos-7.2 | ||
|
||
suites: | ||
- name: default # compliance reporting via chef-server | ||
run_list: | ||
- recipe[audit::default] | ||
attributes: | ||
audit: | ||
profiles: &profiles | ||
base/ssh: true | ||
base/linux: true | ||
- name: compliance # compliance direct reporting | ||
run_list: | ||
- recipe[audit::default] | ||
attributes: | ||
audit: | ||
server: <%= ENV['COMPLIANCE_API'] %> | ||
token: <%= ENV['COMPLIANCE_ACCESSTOKEN'] %> | ||
owner: admin | ||
profiles: *profiles | ||
# - name: default # compliance reporting via chef-server | ||
# run_list: | ||
# - recipe[audit::default] | ||
# attributes: | ||
# audit: | ||
# server: <%= ENV['CHEF_SERVER_URL'] %> | ||
# profiles: &profiles | ||
# base/ssh: true | ||
# base/linux: true | ||
- name: default # compliance direct reporting | ||
run_list: | ||
- recipe[audit::default] | ||
attributes: | ||
audit: | ||
server: <%= ENV['COMPLIANCE_API'] %> | ||
token: <%= ENV['COMPLIANCE_ACCESSTOKEN'] %> | ||
owner: admin | ||
profiles: &profiles | ||
base/ssh: true | ||
base/linux: true | ||
# profiles: *profiles |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
# encoding: utf-8 | ||
|
||
require 'chef/handler' | ||
|
||
class Chef | ||
class Handler | ||
# Creates a compliance audit report | ||
class AuditReport < ::Chef::Handler | ||
def report | ||
return if audit_scheduler.should_skip_audit? | ||
|
||
ensure_inspec_installed | ||
report_results = initialize_report_results | ||
# fetch first so dependencies can be used | ||
compliance_profiles.each do |profile| | ||
profile.fetch | ||
end | ||
# add results of executed profiles to final report results | ||
compliance_profiles.each do |profile| | ||
report_results[:reports][profile.name] = profile.execute | ||
end | ||
report_results[:profile] = profile_owners_by_profile | ||
server_connection.report report_results | ||
audit_scheduler.record_completed_run | ||
end | ||
|
||
def audit_scheduler | ||
@audit_scheduler ||= ::Audit::AuditScheduler.new(node['audit']['interval']['enabled'], node['audit']['interval']['time']) | ||
end | ||
|
||
def initialize_report_results | ||
value = { | ||
node: node['name'], | ||
os: { | ||
release: node['platform_version'], | ||
family: node['platform'], | ||
}, | ||
environment: node['environment'], | ||
reports: {}, | ||
profile: {}, | ||
} | ||
Chef::Log.debug "Initialized report results on node #{value['node']} and environment #{value['environment']}" | ||
value | ||
end | ||
|
||
def inspec_version | ||
node['audit']['inspec_version'] | ||
end | ||
|
||
def ensure_inspec_installed | ||
Chef::Log.debug "Ensuring inspec #{inspec_version} is installed" | ||
require 'inspec' | ||
# load the supermarket plugin | ||
require 'bundles/inspec-supermarket/api' | ||
require 'bundles/inspec-supermarket/target' | ||
|
||
# load the compliance api plugin | ||
require 'bundles/inspec-compliance/api' | ||
|
||
if Inspec::VERSION != inspec_version && inspec_version != 'latest' | ||
Chef::Log.warn "Wrong version of inspec (#{Inspec::VERSION}), please "\ | ||
'remove old versions (/opt/chef/embedded/bin/gem uninstall inspec).' | ||
else | ||
Chef::Log.warn "Using inspec version: (#{Inspec::VERSION})" | ||
end | ||
end | ||
|
||
def compliance_profiles | ||
@compliance_profiles ||= initialize_compliance_profiles | ||
end | ||
|
||
def profile_owners_by_profile | ||
owners_by_profile = {} | ||
compliance_profiles.each do |profile| | ||
owners_by_profile[profile.name] = profile.owner | ||
end | ||
owners_by_profile | ||
end | ||
|
||
def initialize_compliance_profiles | ||
profiles = [] | ||
node['audit']['profiles'].each do |owner_profile, value| | ||
case value | ||
when Hash | ||
enabled = !value['disabled'] | ||
path = value['source'] | ||
else | ||
enabled = value | ||
end | ||
fail "Invalid profile name '#{owner_profile}'. "\ | ||
"Must contain /, e.g. 'john/ssh'" if owner_profile !~ %r{\/} | ||
owner, name = owner_profile.split('/').last(2) | ||
platform_windows = node['platform'] == 'windows' | ||
quiet = node['audit']['quiet'] | ||
profiles.push ::Audit::ComplianceProfile.new(owner, name, enabled, path, server_connection, platform_windows, quiet) | ||
end | ||
profiles | ||
end | ||
|
||
def server_connection | ||
@server_connection ||= initialize_server_connection | ||
end | ||
|
||
def initialize_server_connection | ||
token = node['audit']['token'] | ||
server = node['audit']['server'] | ||
unless token.nil? | ||
Chef::Log.info "Connecting to compliance server #{server} with provided token" | ||
org = node['audit']['owner'] | ||
org = parse_org(server) if org.nil? | ||
::Audit::ComplianceServerConnection.new(server, org, token, node['audit']['refresh_token']) | ||
else | ||
server = chef_server_url if server.nil? | ||
org = parse_org(server) | ||
base_server = server | ||
base_server.slice!("/organizations/#{org}") | ||
Chef::Log.info "Connecting to chef server #{server}" | ||
::Audit::ChefServerConnection.new(base_server, org) | ||
end | ||
end | ||
|
||
def chef_server_url | ||
Chef::Config[:chef_server_url] | ||
end | ||
|
||
def parse_org(url) | ||
url.split('/').last | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
# encoding: utf-8 | ||
module Audit | ||
class AuditScheduler | ||
def initialize(interval_enabled, interval_time) | ||
@interval_enabled = interval_enabled | ||
@interval_time = interval_time | ||
end | ||
|
||
def should_skip_audit? | ||
if should_run_on_schedule? | ||
if scheduled_to_run? | ||
Chef::Log.warn 'Running the compliance audit of this node since it is set to run '\ | ||
"every #{schedule_interval} seconds and last ran on #{last_run_time}." | ||
else | ||
Chef::Log.warn 'Skipping The compliance audit of this node since it is set to run '\ | ||
"every #{schedule_interval} seconds and is scheduled to run during a chef-client "\ | ||
"run after #{next_scheduled_time}" | ||
return true | ||
end | ||
else | ||
Chef::Log.warn 'Running the compliance audit of this node every time chef-client runs.'\ | ||
'To change this, configure it to run on an interval' | ||
end | ||
false | ||
end | ||
|
||
def record_completed_run | ||
FileUtils.touch schedule_file | ||
end | ||
|
||
def should_run_on_schedule? | ||
@interval_enabled | ||
end | ||
|
||
def schedule_interval | ||
@interval_time | ||
end | ||
|
||
def scheduled_to_run? | ||
schedule_file_modified = ::File.mtime(schedule_file) | ||
seconds_since_last_run = Time.now - schedule_file_modified | ||
scheduled = schedule_interval < seconds_since_last_run | ||
Chef::Log.debug "Run scheduled is #{scheduled} where interval is set to #{schedule_interval} "\ | ||
"and it has been #{seconds_since_last_run} seconds since #{schedule_file} last ran "\ | ||
"at #{schedule_file_modified}" | ||
end | ||
|
||
def schedule_file | ||
::File.join(Chef::Config[:file_cache_path], 'compliance', 'schedule') | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
# encoding: utf-8 | ||
|
||
require 'uri' | ||
|
||
module Audit | ||
class ChefServerConnection | ||
attr_accessor :server, :org | ||
def initialize(server, org) | ||
@server = server | ||
@org = org | ||
puts "Creating chef server connection for server #{@server} and org #{@org}" | ||
end | ||
|
||
def fetch(profile) | ||
reqpath ="organizations/#{org}/owners/#{profile.owner}/compliance/#{profile.name}/tar" | ||
url = construct_url(server + '/compliance/', reqpath) | ||
Chef::Log.info "Load profile from: #{url}" | ||
Chef::Config[:verify_api_cert] = false # FIXME | ||
Chef::Config[:ssl_verify_mode] = :verify_none # FIXME | ||
rest = Chef::ServerAPI.new(url, Chef::Config) | ||
tf = ::Audit::HttpProcessor.with_http_rescue do | ||
rest.binmode_streaming_request(url) | ||
end | ||
tf | ||
end | ||
|
||
def construct_url(server, path) | ||
path.sub!(%r{^/}, '') # sanitize input | ||
puts 'Using server ' + server | ||
server = URI(server) | ||
server.path = server.path + path if path | ||
server | ||
end | ||
|
||
def report(report_results) | ||
Chef::Config[:verify_api_cert] = false | ||
Chef::Config[:ssl_verify_mode] = :verify_none | ||
|
||
url = construct_url(server + '/compliance/', ::File.join('organizations', org, 'inspec')) | ||
Chef::Log.info "Report to: #{url}" | ||
|
||
rest = Chef::ServerAPI.new(url, Chef::Config) | ||
::Audit::HttpProcessor.with_http_rescue do | ||
rest.post(url, report_results) | ||
end | ||
end | ||
end | ||
end |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like a step backwards? Or was this just for your testing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I couldn't run
dokken
on my windows machine. Plus I'm not convinced this ever worked, at least for the chef server. So it was for my testing. I'd be happy to roll it back, but don't seedokken
as adding any benefit.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Usually docker tests are faster / I think you can run it in travis
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah so faster tests + CI but no windows development support.I would understand if the former was deemed more valuable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I propose to add multiple kitchen files as we are doing in https://github.com/chef/inspec
Reason: we cannot run vagrant in travis. Still like to see the vagrant option within the cookbook. Just move it to .kitchen.vagrant.yml
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I reverted back to
dokken
per @chris-rock and @bigbam505 suggestions. There is an alternative for vagrant called.kitchen.vagrant.yml