Skip to content

Commit

Permalink
Fixes #14158 - Add support for tailoring files
Browse files Browse the repository at this point in the history
  • Loading branch information
Ondrej Prazak committed Nov 22, 2016
1 parent 8b2eb7f commit 7f320bd
Show file tree
Hide file tree
Showing 36 changed files with 542 additions and 91 deletions.
8 changes: 8 additions & 0 deletions .rubocop.yml
Expand Up @@ -18,3 +18,11 @@ Style/HashSyntax:

Metrics/LineLength:
Enabled: false

Style/CollectionMethods:
PreferredMethods:
find: find
detect: find

Style/FrozenStringLiteralComment:
Enabled: false
3 changes: 3 additions & 0 deletions .rubocop_todo.yml
Expand Up @@ -258,3 +258,6 @@ Performance/Count:

Style/StringLiteralsInInterpolation:
Enabled: false

Style/FrozenStringLiteralComment:
Enabled: false
15 changes: 15 additions & 0 deletions app/assets/javascripts/foreman_openscap/policy_edit.js
Expand Up @@ -13,6 +13,21 @@ function scap_content_selected(element){
})
}

function tailoring_file_selected(element) {
var attrs = attribute_hash(['tailoring_file_id']);
var url = $(element).attr('data-url');
tfm.tools.showSpinner();
$.ajax({
data: attrs,
type: 'post',
url: url,
complete: function() { reloadOnAjaxComplete($(element));},
success: function(request) {
$('#tailoring_file_profile_select').html(request);
}
})
}

function previous_step(previous) {
$('#policy_current_step').val(previous);
$('#new_policy').submit();
Expand Down
14 changes: 12 additions & 2 deletions app/controllers/api/v2/compliance/policies_controller.rb
Expand Up @@ -4,7 +4,7 @@ class PoliciesController < ::Api::V2::BaseController
include Foreman::Controller::SmartProxyAuth
include Foreman::Controller::Parameters::PolicyApi

add_smart_proxy_filters :content, :features => 'Openscap'
add_smart_proxy_filters [:content, :tailoring], :features => 'Openscap'

before_filter :find_resource, :except => %w(index create)

Expand Down Expand Up @@ -83,6 +83,16 @@ def content
:filename => @scap_content.original_filename
end

api :GET, '/compliance/policies/:id/tailoring', N_("Show a policy's Tailoring file")
param :id, :identifier, :required => true

def tailoring
@tailoring_file = @policy.tailoring_file
send_data @tailoring_file.scap_file,
:type => 'application/xml',
:filename => @tailoring_file.original_filename
end

private
def find_resource
not_found and return if params[:id].blank?
Expand All @@ -91,7 +101,7 @@ def find_resource

def action_permission
case params[:action]
when 'content'
when 'content', 'tailoring'
:view
else
super
Expand Down
Expand Up @@ -4,8 +4,8 @@ module Foreman::Controller::Parameters::PolicyApi
class_methods do
def filter_params_list
[:description, :name, :period, :scap_content_id, :scap_content_profile_id,
:weekday, :day_of_month, :cron_line, :location_ids => [], :organization_ids => [],
:hostgroup_ids => []]
:weekday, :day_of_month, :cron_line, :tailoring_file_id, :tailoring_file_profile_id,
:location_ids => [], :organization_ids => [], :hostgroup_ids => []]
end

def policy_params_filter
Expand Down
@@ -0,0 +1,15 @@
module Foreman::Controller::Parameters::TailoringFile
extend ActiveSupport::Concern

class_methods do
def tailoring_file_params_filter
Foreman::ParameterFilter.new(::ForemanOpenscap::TailoringFile).tap do |filter|
filter.permit :name, :scap_file, :original_filename, :location_ids => [], :organization_ids => []
end
end
end

def tailoring_file_params
self.class.tailoring_file_params_filter.filter_params(params, parameter_filter_context)
end
end
17 changes: 13 additions & 4 deletions app/controllers/policies_controller.rb
Expand Up @@ -4,16 +4,16 @@ class PoliciesController < ApplicationController

before_filter :find_by_id, :only => [:show, :edit, :update, :parse, :destroy]
before_filter :find_multiple, :only => [:select_multiple_hosts, :update_multiple_hosts, :disassociate_multiple_hosts, :remove_policy_from_multiple_hosts]
before_filter :find_tailoring_file, :only => [:tailoring_file_selected]

def model_of_controller
::ForemanOpenscap::Policy
end

def index
@policies = resource_base
.search_for(params[:search], :order => params[:order])
.paginate(:page => params[:page], :per_page => params[:per_page])
.includes(:scap_content, :scap_content_profile)
@policies = resource_base.search_for(params[:search], :order => params[:order])
.paginate(:page => params[:page], :per_page => params[:per_page])
.includes(:scap_content, :scap_content_profile, :tailoring_file)
if @policies.empty? && ForemanOpenscap::ScapContent.unconfigured?
redirect_to scap_contents_path
end
Expand Down Expand Up @@ -70,6 +70,11 @@ def scap_content_selected
end
end

def tailoring_file_selected
@policy ||= ::ForemanOpenscap::Policy.new
render :partial => 'tailoring_file_selected', :locals => { :policy => @policy, :tailoring_file => @tailoring_file }
end

def select_multiple_hosts; end

def update_multiple_hosts
Expand Down Expand Up @@ -114,6 +119,10 @@ def find_by_id
@policy = resource_base.find(params[:id])
end

def find_tailoring_file
@tailoring_file = ForemanOpenscap::TailoringFile.find(params[:tailoring_file_id]) if params[:tailoring_file_id].present?
end

def find_multiple
# Lets search by name or id and make sure one of them exists first
if params[:host_ids].present?
Expand Down
60 changes: 60 additions & 0 deletions app/controllers/tailoring_files_controller.rb
@@ -0,0 +1,60 @@
class TailoringFilesController < ApplicationController
include Foreman::Controller::AutoCompleteSearch
include Foreman::Controller::Parameters::TailoringFile

before_filter :find_tailoring_file, :only => [:destroy, :update, :edit]
before_filter :handle_file_upload, :only => [:create, :update]

def model_of_controller
::ForemanOpenscap::TailoringFile
end

def index
@tailoring_files = resource_base.search_for(params[:search], :order => params[:order])
.paginate(:page => params[:page], :per_page => params[:per_page])
end

def new
@tailoring_file = ::ForemanOpenscap::TailoringFile.new
end

def create
@tailoring_file = ForemanOpenscap::TailoringFile.new(tailoring_file_params)
if @tailoring_file.save
process_success
else
process_error
end
end

def edit
end

def update
if @tailoring_file.update_attributes(tailoring_file_params)
process_success
else
process_error
end
end

def destroy
if @tailoring_file.destroy
process_success
else
process_error :object => @tailoring_file
end
end

private

def find_tailoring_file
@tailoring_file = resource_base.find(params[:id])
end

def handle_file_upload
return unless params[:tailoring_file] && raw_file = params[:tailoring_file][:scap_file]
params[:tailoring_file][:original_filename] = raw_file.original_filename
params[:tailoring_file][:scap_file] = raw_file.tempfile.read if raw_file.respond_to?(:tempfile) && raw_file.tempfile.respond_to?(:read)
end
end
23 changes: 23 additions & 0 deletions app/helpers/policies_helper.rb
Expand Up @@ -5,6 +5,14 @@ def profiles_selection
return []
end

def policy_profile_from_scap_content(policy)
policy.scap_content_profile.nil? ? "Default" : policy.scap_content_profile.title
end

def effective_policy_profile(policy)
policy.tailoring_file ? policy.tailoring_file_profile.title : policy_profile_from_scap_content(policy)
end

def scap_content_selector(form)
scap_contents = ::ForemanOpenscap::ScapContent.all
if scap_contents.length > 1
Expand Down Expand Up @@ -38,6 +46,21 @@ def scap_content_profile_selector(form)
end
end

def tailoring_file_selector(form)
select_f form, :tailoring_file_id, ForemanOpenscap::TailoringFile.all, :id, :name,
{ :include_blank => _('Choose Tailoring File') },
{ :label => _('Tailoring File'),
:onchange => 'tailoring_file_selected(this)',
:'data-url' => method_path('tailoring_file_selected') }
end

def tailoring_file_profile_selector(form, tailoring_file)
select_f form, :tailoring_file_profile_id, tailoring_file.scap_content_profiles, :id, :title,
{ :selected => tailoring_file.scap_content_profiles.first.id },
{ :label => _("XCCDF Profile in Tailoring File"),
:help_inline => _("This profile will be used to override the one from scap content") }
end

def submit_or_cancel_policy(form, overwrite = nil, args = { })
args[:cancel_path] ||= send("#{controller_name}_path")
content_tag(:div, :class => "clearfix") do
Expand Down
8 changes: 6 additions & 2 deletions app/lib/proxy_api/openscap.rb
Expand Up @@ -10,8 +10,12 @@ def fetch_policies_for_scap_content(scap_file)
parse(post(scap_file, "scap_content/policies"))
end

def validate_scap_content(scap_file)
parse(post(scap_file, "scap_content/validator"))
def fetch_profiles_for_tailoring_file(scap_file)
parse(post(scap_file, "tailoring_file/profiles"))
end

def validate_scap_file(scap_file, type)
parse(post(scap_file, "scap_file/validator/#{type}"))
end

def policy_html_guide(scap_file, policy)
Expand Down
43 changes: 43 additions & 0 deletions app/models/concerns/foreman_openscap/data_stream_content.rb
@@ -0,0 +1,43 @@
module ForemanOpenscap
module DataStreamContent
require 'digest/sha2'

extend ActiveSupport::Concern

included do
validates :digest, :presence => true, :uniqueness => true
validates :scap_file, :presence => true

validates_with ForemanOpenscap::DataStreamValidator

after_save :create_profiles

before_validation :redigest, :if => lambda { |ds_content| ds_content.persisted? && ds_content.scap_file_changed? }
before_destroy ActiveRecord::Base::EnsureNotUsedBy.new(:policies)
end

def proxy_url
@proxy_url ||= SmartProxy.with_features('Openscap').find do |proxy|
available = ProxyAPI::AvailableProxy.new(:url => proxy.url)
available.available?
end.try(:url)
@proxy_url
end

def digest
self[:digest] ||= Digest::SHA256.hexdigest(scap_file.to_s)
end

private

def redigest
self[:digest] = Digest::SHA256.hexdigest(scap_file.to_s)
end

def create_profiles
fetch_profiles.each do |key, title|
ScapContentProfile.where(:profile_id => key, :title => title, "#{self.class.to_s.demodulize.underscore}_id".to_sym => id).first_or_create
end
end
end
end
18 changes: 16 additions & 2 deletions app/models/foreman_openscap/policy.rb
Expand Up @@ -6,6 +6,8 @@ class Policy < ActiveRecord::Base

belongs_to :scap_content
belongs_to :scap_content_profile
belongs_to :tailoring_file
belongs_to :tailoring_file_profile, :class_name => ForemanOpenscap::ScapContentProfile
has_many :policy_arf_reports
has_many :arf_reports, :through => :policy_arf_reports, :dependent => :destroy
has_many :asset_policies
Expand Down Expand Up @@ -166,9 +168,11 @@ def unassign_hosts(hosts)
def to_enc
{
'id' => self.id,
'profile_id' => self.scap_content_profile.try(:profile_id) || '',
'profile_id' => profile_for_scan,
'content_path' => "/var/lib/openscap/content/#{self.scap_content.digest}.xml",
'download_path' => "/compliance/policies/#{self.id}/content" # default to proxy path
'tailoring_path' => tailoring_file ? "/var/lib/openscap/tailoring/#{self.tailoring_file.digest}.xml" : '',
'download_path' => "/compliance/policies/#{self.id}/content", # default to proxy path
'tailoring_download_path' => "/compliance/policies/#{self.id}/tailoring"
}.merge(period_enc)
end

Expand Down Expand Up @@ -283,6 +287,16 @@ def assign_policy_to_hostgroups
end
end

def profile_for_scan
if tailoring_file_profile
tailoring_file_profile.profile_id
elsif scap_content_profile
scap_content_profile.profile_id
else
''
end
end

def find_scap_puppetclass
Puppetclass.find_by_name(SCAP_PUPPET_CLASS)
end
Expand Down

0 comments on commit 7f320bd

Please sign in to comment.