inspec/lib/resources/nginx_conf.rb

96 lines
3.2 KiB
Ruby
Raw Normal View History

# 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