Module: Inspec::DSL
- Included in:
- ControlEvalContext
- Defined in:
- lib/inspec/dsl_shared.rb,
lib/inspec/dsl.rb
Overview
Contains methods we would like in multiple DSL
Defined Under Namespace
Modules: RequireOverride
Instance Attribute Summary collapse
-
#backend ⇒ Object
Returns the value of attribute backend.
Class Method Summary collapse
- .filter_included_controls(context, profile, opts, &block) ⇒ Object
- .load_spec_files_for_profile(bind_context, opts, &block) ⇒ Object
-
.method_missing_resource(backend, id, *arguments) ⇒ Object
Try to load and instantiate a missing resource or raise LoadError if unable.
Instance Method Summary collapse
- #include_controls(id, version = nil, &block) ⇒ Object (also: #include_rules)
-
#method_missing(method_name, *arguments, &block) ⇒ Object
Support for Outer Profile DSL plugins This is called when an unknown method is encountered “bare” in a control file - outside of a control or describe block.
- #require_controls(id, version = nil, &block) ⇒ Object (also: #require_rules)
- #require_resource(options = {}) ⇒ Object
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method_name, *arguments, &block) ⇒ Object
Support for Outer Profile DSL plugins This is called when an unknown method is encountered “bare” in a control file - outside of a control or describe block.
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/inspec/dsl.rb', line 100 def method_missing(method_name, *arguments, &block) # Check to see if there is a outer_profile_dsl plugin activator hook with the method name registry = Inspec::Plugin::V2::Registry.instance hook = registry.find_activators(plugin_type: :outer_profile_dsl, activator_name: method_name).first if hook # OK, load the hook if it hasn't been already. We'll then know a module, # which we can then inject into the context hook.activate # Inject the module's methods into the context # implementation_class is the field name, but this is actually a module. self.class.include(hook.implementation_class) # Now that the module is loaded, it defined one or more methods # (presumably the one we were looking for.) # We still haven't called it, so do so now. send(method_name, *arguments, &block) else begin Inspec::DSL.method_missing_resource(backend, method_name, *arguments) rescue LoadError super end end end |
Instance Attribute Details
#backend ⇒ Object
Returns the value of attribute backend.
11 12 13 |
# File 'lib/inspec/dsl.rb', line 11 def backend @backend end |
Class Method Details
.filter_included_controls(context, profile, opts, &block) ⇒ Object
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
# File 'lib/inspec/dsl.rb', line 169 def self.filter_included_controls(context, profile, opts, &block) mock = Inspec::Backend.create(Inspec::Config.mock) include_ctx = Inspec::ProfileContext.for_profile(profile, mock) include_ctx.load(block) if block_given? include_ctx.control_eval_context.conf = opts[:conf] control_eval_ctx = include_ctx.control_eval_context # remove all rules that were not registered context.all_rules.each do |r| id = Inspec::Rule.rule_id(r) fid = Inspec::Rule.profile_id(r) + "/" + id if !opts[:include_all] && !(include_ctx.rules[id] || include_ctx.rules[fid]) context.remove_rule(fid) end unless control_eval_ctx.controls_list_empty? # filter the dependent profile controls which are not in the --controls options list context.remove_rule(fid) unless control_eval_ctx.control_exist_in_controls_list?(id) end unless control_eval_ctx. # filter included controls using --tags tag_ids = control_eval_ctx.(r) context.remove_rule(fid) unless control_eval_ctx.(tag_ids) end end end |
.load_spec_files_for_profile(bind_context, opts, &block) ⇒ Object
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/inspec/dsl.rb', line 124 def self.load_spec_files_for_profile(bind_context, opts, &block) dependencies = opts[:dependencies] profile_id = opts[:profile_id] profile_version = opts[:profile_version] new_profile_id = nil if profile_version new_profile_id = "#{profile_id}-#{profile_version}" else dependencies.list.each do |key, value| # 1. Fetching VERSION from a profile dependency name which is in a format NAME-VERSION. # 2. Matching original profile dependency name with profile name used with include or require control DSL. source_version = value.source_version unless source_version.nil? || source_version.empty? profile_id_key = key.split("-#{source_version}")[0] new_profile_id = key if profile_id_key == profile_id end end end # If dep profile does not contain a source version, key does not contain a version as well. In that case new_profile_id will be always nil and instead profile_id would be used to fetch profile from dependency list. dep_entry = new_profile_id ? dependencies.list[new_profile_id] : dependencies.list[profile_id] if dep_entry.nil? raise <<~EOF Cannot load '#{profile_id}' since it is not listed as a dependency of #{bind_context.profile_name}. Dependencies available from this context are: #{dependencies.list.keys.join("\n ")} EOF end # Do not load any controls if the profile is not supported return unless dep_entry.profile.supports_platform? context = dep_entry.profile.runner_context # if we don't want all the rules, then just make 1 pass to get all rule_IDs # that we want to keep from the original if !opts[:include_all] || !(opts[:conf]["profile"]..empty?) || !opts[:conf]["profile"].include_controls_list.empty? filter_included_controls(context, dep_entry.profile, opts, &block) end # interpret the block and skip/modify as required context.load(block) if block_given? bind_context.add_subcontext(context) end |
.method_missing_resource(backend, id, *arguments) ⇒ Object
Try to load and instantiate a missing resource or raise LoadError if unable. Requiring the resource registers it and generates a method for it so you should only hit this once per missing resource.
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/inspec/dsl.rb', line 41 def self.method_missing_resource(backend, id, *arguments) return unless backend begin require "inspec/resources/#{id}" rescue LoadError => e # InSpec 7+ Fallback Support for Resource Packs # Use Deprecator to lookup the matching gem # if a gem matches, try to load the resource from the gem gem_name = Inspec::Deprecation::Deprecator.new.match_gem_for_fallback_resource_name(id.to_s) if gem_name # Install if needed cfg = Inspec::Config.cached unless cfg.[:auto_install_gems] Inspec.deprecate(:core_resource_moved_to_rp, "The resource pack gem '#{gem_name}' is required for resource '#{id}' support (consider --auto-install-gems).") end Inspec::Plugin::V2::Installer.instance.ensure_installed gem_name # Load the gem, add gemspecs to the path, load any deps, load resource libraries into registry # This is plugin API orthodoxy but is impossible to program # Inspec::Plugin::V2::Registry.instance.find_activator(gem_name).activate loader = Inspec::Plugin::V2::Loader.new # 1. Activate gem and deps. loader.activate_managed_gems_for_plugin(gem_name) # 2. Load all libraries from the gem path gem_path = loader.find_gem_directory(gem_name) resources_path = File.join(gem_path, "lib", gem_name, "resources", "*.rb") legacy_library_path = File.join(gem_path, "libraries", "*.rb") Dir.glob([resources_path, legacy_library_path]).each do |resource_lib| require resource_lib end # Resources now available in Inspec::Resource.registry else # TODO: InSpec 7: Replace with Fallbacks for inspec-aws-resources and inspec-azure-resources include DeprecatedCloudResourcesList cloud_resource = id.start_with?("aws_") ? "aws" : "azure" # Deprecated AWS and Azure resources in InSpec 5. if CLOUD_RESOURCES_DEPRECATED.include? id Inspec.deprecate(:"#{cloud_resource}_resources_in_resource_pack", "Resource '#{id}'") else # OK, give up entirely raise LoadError, "#{e.}" end end end klass = Inspec::Resource.registry[id.to_s] klass.new(backend, id, *arguments) end |
Instance Method Details
#include_controls(id, version = nil, &block) ⇒ Object Also known as: include_rules
18 19 20 21 |
# File 'lib/inspec/dsl.rb', line 18 def include_controls(id, version = nil, &block) opts = { profile_id: id, include_all: true, backend: @backend, conf: @conf, dependencies: @dependencies, profile_version: version } ::Inspec::DSL.load_spec_files_for_profile(self, opts, &block) end |
#require_controls(id, version = nil, &block) ⇒ Object Also known as: require_rules
13 14 15 16 |
# File 'lib/inspec/dsl.rb', line 13 def require_controls(id, version = nil, &block) opts = { profile_id: id, include_all: false, backend: @backend, conf: @conf, dependencies: @dependencies, profile_version: version } ::Inspec::DSL.load_spec_files_for_profile(self, opts, &block) end |
#require_resource(options = {}) ⇒ Object
26 27 28 29 30 31 32 33 |
# File 'lib/inspec/dsl.rb', line 26 def require_resource( = {}) raise "You must specify a specific resource name when calling require_resource()" if [:resource].nil? from_profile = [:profile] || profile_name target_name = [:as] || [:resource] res = resource_class(from_profile, [:resource]) add_resource(target_name, res) end |