mirror of
https://github.com/inspec/inspec
synced 2024-11-14 17:07:09 +00:00
56549aed82
The resource itself only offers contents and params right now. It resolved all include calls it can find and creates the aggregated config object. This is limited in functionality. One last (set of) PR(s) is needed to add an interface that makes querying this config file easier. It is due to the file's inherent complexity that I want to explore which methods are needed to be effective. In the meantime, this resource offers accessors to the underlying data that are stable. Signed-off-by: Dominik Richter <dominik.richter@gmail.com>
95 lines
3.2 KiB
Ruby
95 lines
3.2 KiB
Ruby
# encoding: utf-8
|
|
# author: Dominik Richter
|
|
# author: Christoph Hartmann
|
|
|
|
require 'utils/nginx_parser'
|
|
|
|
# STABILITY: Experimental
|
|
# This resouce needs a proper interace to the underlying data, which is currently missing.
|
|
# Until it is added, we will keep it experimental.
|
|
#
|
|
# TODO: Support it on Windows. To do so, we need to recognize the base os and how
|
|
# it combines the file path. Calling `File.join` or similar methods may lead to errors
|
|
# when running remotely.
|
|
module Inspec::Resources
|
|
class NginxConf < Inspec.resource(1)
|
|
name 'nginx_conf'
|
|
desc 'Use the nginx_conf InSpec resource to test configuration data '\
|
|
'for the NginX web server located in /etc/nginx/nginx.conf on '\
|
|
'Linux and UNIX platforms.'
|
|
example "
|
|
describe nginx_conf.params ...
|
|
describe nginx_conf('/path/to/my/nginx.conf').params ...
|
|
"
|
|
|
|
attr_reader :contents
|
|
|
|
def initialize(conf_path = nil)
|
|
@conf_path = conf_path || '/etc/nginx/nginx.conf'
|
|
@contents = {}
|
|
return skip_resource 'The `nginx_conf` resource is currently not supported on Windows.' if inspec.os.windows?
|
|
end
|
|
|
|
def params
|
|
@params ||= parse_nginx(@conf_path)
|
|
rescue StandardError => e
|
|
skip_resource e.message
|
|
@params = {}
|
|
end
|
|
|
|
def to_s
|
|
"nginx_conf #{@conf_path}"
|
|
end
|
|
|
|
private
|
|
|
|
def read_content(path)
|
|
return @contents[path] if @contents.key?(path)
|
|
file = inspec.file(path)
|
|
if !file.file?
|
|
return skip_resource "Can't find file \"#{path}\""
|
|
end
|
|
@contents[path] = file.content
|
|
end
|
|
|
|
def parse_nginx(path)
|
|
return nil if inspec.os.windows?
|
|
content = read_content(path)
|
|
data = NginxConfig.parse(content)
|
|
resolve_references(data, File.dirname(path))
|
|
rescue StandardError => _
|
|
raise "Cannot parse NginX config in #{path}."
|
|
end
|
|
|
|
# Cycle through the complete parsed data structure and try to find any
|
|
# calls to `include`. In NginX, this is used to embed data from other
|
|
# files into the current data structure.
|
|
#
|
|
# The method steps through the object structure that is passed in to
|
|
# find any calls to 'include' and returns the object structure with the
|
|
# included data merged in.
|
|
#
|
|
# @param data [Hash] data structure from NginxConfig.parse
|
|
# @param rel_path [String] the relative path from which this config is read
|
|
# @return [Hash] data structure with references included
|
|
def resolve_references(data, rel_path)
|
|
# Walk through all array entries to find more references
|
|
return data.map { |x| resolve_references(x, rel_path) } if data.is_a?(Array)
|
|
|
|
# Return any data that we cannot step into to find more `include` calls
|
|
return data unless data.is_a?(Hash)
|
|
|
|
# Any call to `include` gets its data read, parsed, and merged back
|
|
# into the current data structure
|
|
if data.key?('include')
|
|
data.delete('include').flatten
|
|
.map { |x| File.expand_path(x, rel_path) }
|
|
.map { |path| parse_nginx(path) }
|
|
.map { |e| data.merge!(e) }
|
|
end
|
|
|
|
# Walk through the remaining hash fields to find more references
|
|
Hash[data.map { |k, v| [k, resolve_references(v, rel_path)] }]
|
|
end
|
|
end
|
|
end
|