class Inspec::Resources::NginxConf

Attributes

contents[R]

Public Class Methods

new(conf_path = nil) click to toggle source
# File lib/inspec/resources/nginx_conf.rb, line 32
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?

  read_content(@conf_path)
end

Public Instance Methods

http() click to toggle source
# File lib/inspec/resources/nginx_conf.rb, line 47
def http
  NginxConfHttp.new(params["http"], self)
end
method_missing(name) click to toggle source
Calls superclass method
# File lib/inspec/resources/nginx_conf.rb, line 57
def method_missing(name)
  return super if name.to_s.match?(/^to_/)

  v = params[name.to_s]
  return v.flatten unless v.nil?

  nil
end
params() click to toggle source
# File lib/inspec/resources/nginx_conf.rb, line 40
def params
  @params ||= parse_nginx(@conf_path)
rescue StandardError => e
  skip_resource e.message
  @params = {}
end
respond_to_missing?(name, include_all = false) click to toggle source
Calls superclass method
# File lib/inspec/resources/nginx_conf.rb, line 66
def respond_to_missing?(name, include_all = false)
  return super if name.to_s.match?(/^to_/)

  true
end
to_s() click to toggle source
# File lib/inspec/resources/nginx_conf.rb, line 53
def to_s
  "nginx_conf #{@conf_path}"
end

Private Instance Methods

merge_config!(data, conf) click to toggle source

Deep merge fields from NginxConfig.parse. A regular merge would overwrite values so a deep merge is needed. @param data [Hash] data structure from NginxConfig.parse @param conf [Hash] data structure to be deep merged into data @return [Hash] data structure with conf and data deep merged

# File lib/inspec/resources/nginx_conf.rb, line 132
def merge_config!(data, conf)
  # Catch edge-cases
  return if data.nil? || conf.nil?

  # Step through all conf items and create combined return value
  data.merge!(conf) do |_, v1, v2|
    if v1.is_a?(Array) && v2.is_a?(Array)
      # If both the data field and the conf field are arrays, then combine them
      v1 + v2
    elsif v1.is_a?(Hash) && v2.is_a?(Hash)
      # If both the data field and the conf field are maps, then deep merge them
      merge_config!(v1, v2)
    else
      # All other cases, just use the new value (regular merge behavior)
      v2
    end
  end
end
parse_nginx(path) click to toggle source
# File lib/inspec/resources/nginx_conf.rb, line 80
def parse_nginx(path)
  return nil if inspec.os.windows?

  content = read_content(path)

  # Don't attempt to parse file if it contains only comments or is empty
  # https://regexper.com/#%2F%5E%5Cs*%23%7C%5E%24%2F
  return {} if content.lines.reject { |l| l =~ /^\s*#|^$/ }.empty?

  data = NginxConfig.parse(content)
  resolve_references(data, File.dirname(path))
rescue StandardError => _
  raise "Cannot parse NginX config in #{path}."
end
read_content(path) click to toggle source
# File lib/inspec/resources/nginx_conf.rb, line 74
def read_content(path)
  return @contents[path] if @contents.key?(path)

  @contents[path] = read_file_content(path, allow_empty: true)
end
resolve_references(data, rel_path) click to toggle source

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

# File lib/inspec/resources/nginx_conf.rb, line 106
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 { |x| find_files(x) }.flatten
      .map { |path| parse_nginx(path) }
      .each { |conf| merge_config!(data, conf) }
  end

  # Walk through the remaining hash fields to find more references
  Hash[data.map { |k, v| [k, resolve_references(v, rel_path)] }]
end