mirror of
https://github.com/inspec/inspec
synced 2025-02-16 22:18:38 +00:00
Add wildcard/multiple server support to nginx_conf resource (#2141)
* Add wildcard/multiple server support to nginx_conf Signed-off-by: Jerry Aldrich <jerryaldrichiii@gmail.com> * separate the merge function for maps in nginx_conf Signed-off-by: Dominik Richter <dominik.richter@gmail.com>
This commit is contained in:
parent
48b0e6a667
commit
9773e1cd94
10 changed files with 146 additions and 22 deletions
|
@ -3,6 +3,7 @@
|
|||
# author: Christoph Hartmann
|
||||
|
||||
require 'utils/nginx_parser'
|
||||
require 'utils/find_files'
|
||||
require 'forwardable'
|
||||
|
||||
# STABILITY: Experimental
|
||||
|
@ -25,6 +26,8 @@ module Inspec::Resources
|
|||
|
||||
extend Forwardable
|
||||
|
||||
include FindFiles
|
||||
|
||||
attr_reader :contents
|
||||
|
||||
def initialize(conf_path = nil)
|
||||
|
@ -93,13 +96,37 @@ module Inspec::Resources
|
|||
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) }
|
||||
.map { |e| data.merge!(e) }
|
||||
.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
|
||||
|
||||
# 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
|
||||
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
|
||||
end
|
||||
|
||||
class NginxConfHttp
|
||||
|
|
|
@ -139,6 +139,8 @@ class MockLoader
|
|||
'/etc/nginx/nginx.conf' => mockfile.call('nginx.conf'),
|
||||
'/etc/nginx/proxy.conf' => mockfile.call('nginx_proxy.conf'),
|
||||
'/etc/nginx/conf/mime.types' => mockfile.call('nginx_mime.types'),
|
||||
'/etc/nginx/conf.d/foobar.conf' => mockfile.call('nginx_confd_foobar.conf'),
|
||||
'/etc/nginx/conf.d/multiple.conf' => mockfile.call('nginx_confd_multiple.conf'),
|
||||
'/etc/xinetd.conf' => mockfile.call('xinetd.conf'),
|
||||
'/etc/xinetd.d' => mockfile.call('xinetd.d'),
|
||||
'/etc/xinetd.d/chargen-stream' => mockfile.call('xinetd.d_chargen-stream'),
|
||||
|
@ -297,6 +299,10 @@ class MockLoader
|
|||
'find /etc/httpd/conf-enabled/*.conf -type l -maxdepth 1' => cmd.call('find-httpd-conf-enabled-link'),
|
||||
'find /etc/apache2/conf-enabled/*.conf -type f -maxdepth 1' => cmd.call('find-apache2-conf-enabled'),
|
||||
'find /etc/apache2/conf-enabled/*.conf -type l -maxdepth 1' => cmd.call('find-apache2-conf-enabled-link'),
|
||||
'find /etc/nginx/nginx.conf' => cmd.call('find-nginx-conf'),
|
||||
'find /etc/nginx/conf/mime.types' => cmd.call('find-nginx-mime-types'),
|
||||
'find /etc/nginx/proxy.conf' => cmd.call('find-nginx-proxy-conf'),
|
||||
'find /etc/nginx/conf.d/*.conf' => cmd.call('find-nginx-confd-multiple-conf'),
|
||||
# mount
|
||||
"mount | grep -- ' on /'" => cmd.call("mount"),
|
||||
"mount | grep -- ' on /mnt/iso-disk'" => cmd.call("mount-multiple"),
|
||||
|
|
1
test/unit/mock/cmd/find-nginx-conf
Normal file
1
test/unit/mock/cmd/find-nginx-conf
Normal file
|
@ -0,0 +1 @@
|
|||
/etc/nginx/nginx.conf
|
2
test/unit/mock/cmd/find-nginx-confd-multiple-conf
Normal file
2
test/unit/mock/cmd/find-nginx-confd-multiple-conf
Normal file
|
@ -0,0 +1,2 @@
|
|||
/etc/nginx/conf.d/foobar.conf
|
||||
/etc/nginx/conf.d/multiple.conf
|
1
test/unit/mock/cmd/find-nginx-mime-types
Normal file
1
test/unit/mock/cmd/find-nginx-mime-types
Normal file
|
@ -0,0 +1 @@
|
|||
/etc/nginx/conf/mime.types
|
1
test/unit/mock/cmd/find-nginx-proxy-conf
Normal file
1
test/unit/mock/cmd/find-nginx-proxy-conf
Normal file
|
@ -0,0 +1 @@
|
|||
/etc/nginx/proxy.conf
|
|
@ -8,6 +8,7 @@ events { # events test
|
|||
http {
|
||||
include conf/mime.types; # relative path
|
||||
include /etc/nginx/proxy.conf; # absolute path
|
||||
include /etc/nginx/conf.d/*.conf; # wildcard path
|
||||
|
||||
index index.html index.htm index.php;
|
||||
default_type application/octet-stream; # parameter with '/'
|
||||
|
@ -18,7 +19,7 @@ http {
|
|||
|
||||
# multi server tests
|
||||
server {
|
||||
listen 85;
|
||||
listen 80;
|
||||
server_name domain1.com www.domain1.com;
|
||||
location ~ \.php$ {
|
||||
fastcgi_pass 127.0.0.1:1025;
|
||||
|
@ -26,7 +27,7 @@ http {
|
|||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
listen 443;
|
||||
server_name domain2.com www.domain2.com;
|
||||
# multiple locations test
|
||||
location ~ ^/(images|javascript|js|css|flash|media|static)/ {
|
||||
|
|
7
test/unit/mock/files/nginx_confd_foobar.conf
Normal file
7
test/unit/mock/files/nginx_confd_foobar.conf
Normal file
|
@ -0,0 +1,7 @@
|
|||
server {
|
||||
listen 8081;
|
||||
server_name foobar.com www.foobar.com;
|
||||
location ~ ^/flash/ {
|
||||
root /var/www/virtual/www.foobar.com/htdocs;
|
||||
}
|
||||
}
|
15
test/unit/mock/files/nginx_confd_multiple.conf
Normal file
15
test/unit/mock/files/nginx_confd_multiple.conf
Normal file
|
@ -0,0 +1,15 @@
|
|||
server {
|
||||
listen 8083;
|
||||
server_name example1.com www.example1.com;
|
||||
location ~ ^/static/ {
|
||||
root /var/www/virtual/www.example1.com/htdocs;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 8084;
|
||||
server_name example2.com www.example2.com;
|
||||
location ~ ^/media/ {
|
||||
root /var/www/virtual/www.example2.com/htdocs;
|
||||
}
|
||||
}
|
|
@ -25,25 +25,73 @@ describe 'Inspec::Resources::NginxConf' do
|
|||
it 'reads the nginx_conf with all referenced include calls' do
|
||||
_(nginx_conf.params).must_be_kind_of Hash
|
||||
_(nginx_conf.contents).must_be_kind_of Hash
|
||||
_(nginx_conf.contents.keys).must_equal %w(/etc/nginx/nginx.conf /etc/nginx/conf/mime.types /etc/nginx/proxy.conf)
|
||||
_(nginx_conf.contents.keys).must_equal %w(
|
||||
/etc/nginx/nginx.conf
|
||||
/etc/nginx/conf/mime.types
|
||||
/etc/nginx/proxy.conf
|
||||
/etc/nginx/conf.d/foobar.conf
|
||||
/etc/nginx/conf.d/multiple.conf
|
||||
)
|
||||
|
||||
# global entries
|
||||
_(nginx_conf.params['user']).must_equal [["www", "www"]] # multiple
|
||||
_(nginx_conf.params['error_log']).must_equal [["logs/error.log"]] # with /
|
||||
# verify user
|
||||
_(nginx_conf.params['user']).must_equal [['www', 'www']] # multiple
|
||||
|
||||
# verify http, events, and servers
|
||||
_(nginx_conf.params['events']).must_equal [{"worker_connections"=>[["4096"]]}]
|
||||
# verify error_log
|
||||
_(nginx_conf.params['error_log']).must_equal [['logs/error.log']] # with /
|
||||
|
||||
# verify events
|
||||
_(nginx_conf.params['events']).must_equal [{'worker_connections'=>[['4096']]}]
|
||||
|
||||
# verify http
|
||||
_(nginx_conf.params['http'].length).must_equal 1
|
||||
_(nginx_conf.params['http'][0]['server'].length).must_equal 2
|
||||
|
||||
# verify server count
|
||||
_(nginx_conf.params['http'][0]['server'].length).must_equal 5
|
||||
|
||||
# verify index
|
||||
_(nginx_conf.params['http'][0]['index']).must_equal [['index.html', 'index.htm', 'index.php']]
|
||||
|
||||
# verify default_type (parameter with '/')
|
||||
_(nginx_conf.params['http'][0]['default_type']).must_equal [['application/octet-stream']]
|
||||
|
||||
# verify relative include
|
||||
# verify log_format (multi-line parameter)
|
||||
_(nginx_conf.params['http'][0]['log_format']).must_equal [['main', 'multi', 'line']]
|
||||
|
||||
# verify types (relative include test)
|
||||
_(nginx_conf.params['http'][0]['types']).must_equal [{'text/html'=>[['html', 'htm', 'shtml']]}]
|
||||
# verify absolute include
|
||||
|
||||
# verify proxy_redirect (absolute include test)
|
||||
_(nginx_conf.params['http'][0]['proxy_redirect']).must_equal [['off']]
|
||||
|
||||
# verify multiline
|
||||
_(nginx_conf.params['http'][0]['log_format']).must_equal [['main', 'multi', 'line']]
|
||||
# verify server in main nginx.conf
|
||||
_(nginx_conf.params['http'][0]['server'][0]['listen']).must_equal [['80']]
|
||||
_(nginx_conf.params['http'][0]['server'][0]['server_name']).must_equal [['domain1.com', 'www.domain1.com']]
|
||||
_(nginx_conf.params['http'][0]['server'][0]['location'][0]['_']).must_equal ["~", "\\.php$"]
|
||||
_(nginx_conf.params['http'][0]['server'][0]['location'][0]['fastcgi_pass']).must_equal [["127.0.0.1:1025"]]
|
||||
|
||||
# verify another server in main nginx.conf (multi-server and multi-location test)
|
||||
_(nginx_conf.params['http'][0]['server'][1]['listen']).must_equal [['443']]
|
||||
_(nginx_conf.params['http'][0]['server'][1]['server_name']).must_equal [['domain2.com', 'www.domain2.com']]
|
||||
_(nginx_conf.params['http'][0]['server'][1]['location'][0]['_']).must_equal ['~', '^/(images|javascript|js|css|flash|media|static)/']
|
||||
_(nginx_conf.params['http'][0]['server'][1]['location'][0]['root']).must_equal [['/var/www/virtual/big.server.com/htdocs']]
|
||||
_(nginx_conf.params['http'][0]['server'][1]['location'][1]['_']).must_equal ['/']
|
||||
_(nginx_conf.params['http'][0]['server'][1]['location'][1]['proxy_pass']).must_equal [['http://127.0.0.1:8080']]
|
||||
|
||||
# verify a server in conf.d (wildcard include test)
|
||||
_(nginx_conf.params['http'][0]['server'][2]['listen']).must_equal [['8081']]
|
||||
_(nginx_conf.params['http'][0]['server'][2]['server_name']).must_equal [['foobar.com', 'www.foobar.com']]
|
||||
_(nginx_conf.params['http'][0]['server'][2]['location'][0]['_']).must_equal ['~', '^/flash/']
|
||||
_(nginx_conf.params['http'][0]['server'][2]['location'][0]['root']).must_equal [['/var/www/virtual/www.foobar.com/htdocs']]
|
||||
|
||||
# verify servers in conf.d files (wildcard include test)
|
||||
_(nginx_conf.params['http'][0]['server'][3]['listen']).must_equal [['8083']]
|
||||
_(nginx_conf.params['http'][0]['server'][3]['server_name']).must_equal [['example1.com', 'www.example1.com']]
|
||||
_(nginx_conf.params['http'][0]['server'][3]['location'][0]['_']).must_equal ['~', '^/static/']
|
||||
_(nginx_conf.params['http'][0]['server'][3]['location'][0]['root']).must_equal [['/var/www/virtual/www.example1.com/htdocs']]
|
||||
_(nginx_conf.params['http'][0]['server'][4]['listen']).must_equal [['8084']]
|
||||
_(nginx_conf.params['http'][0]['server'][4]['server_name']).must_equal [['example2.com', 'www.example2.com']]
|
||||
_(nginx_conf.params['http'][0]['server'][4]['location'][0]['_']).must_equal ['~', '^/media/']
|
||||
_(nginx_conf.params['http'][0]['server'][4]['location'][0]['root']).must_equal [['/var/www/virtual/www.example2.com/htdocs']]
|
||||
end
|
||||
|
||||
it 'skips the resource if it cannot parse the config' do
|
||||
|
@ -67,18 +115,25 @@ describe 'Inspec::Resources::NginxConf' do
|
|||
_(http.entries).must_be_kind_of Array
|
||||
_(http.entries.length).must_equal 1
|
||||
_(http.entries[0]).must_be_kind_of Inspec::Resources::NginxConfHttpEntry
|
||||
http.entries.each do |entry|
|
||||
_(entry).must_be_kind_of Inspec::Resources::NginxConfHttpEntry
|
||||
end
|
||||
end
|
||||
|
||||
it 'provides aggregated access to all servers' do
|
||||
_(http.servers).must_be_kind_of Array
|
||||
_(http.servers.length).must_equal 2
|
||||
_(http.servers[0]).must_be_kind_of Inspec::Resources::NginxConfServer
|
||||
_(http.servers.length).must_equal 5
|
||||
http.servers.each do |server|
|
||||
_(server).must_be_kind_of Inspec::Resources::NginxConfServer
|
||||
end
|
||||
end
|
||||
|
||||
it 'provides aggregated access to all locations' do
|
||||
_(http.locations).must_be_kind_of Array
|
||||
_(http.locations.length).must_equal 3
|
||||
_(http.locations[0]).must_be_kind_of Inspec::Resources::NginxConfLocation
|
||||
_(http.locations.length).must_equal 6
|
||||
http.locations.each do |location|
|
||||
_(location).must_be_kind_of Inspec::Resources::NginxConfLocation
|
||||
end
|
||||
end
|
||||
|
||||
it 'doesnt fail on params == nil' do
|
||||
|
@ -98,14 +153,20 @@ describe 'Inspec::Resources::NginxConf' do
|
|||
|
||||
it 'provides aggregated access to all servers' do
|
||||
_(entry.servers).must_be_kind_of Array
|
||||
_(entry.servers.length).must_equal 2
|
||||
_(entry.servers.length).must_equal 5
|
||||
_(entry.servers[0]).must_be_kind_of Inspec::Resources::NginxConfServer
|
||||
entry.servers.each do |server|
|
||||
_(server).must_be_kind_of Inspec::Resources::NginxConfServer
|
||||
end
|
||||
end
|
||||
|
||||
it 'provides aggregated access to all locations' do
|
||||
_(entry.locations).must_be_kind_of Array
|
||||
_(entry.locations.length).must_equal 3
|
||||
_(entry.locations.length).must_equal 6
|
||||
_(entry.locations[0]).must_be_kind_of Inspec::Resources::NginxConfLocation
|
||||
entry.locations.each do |location|
|
||||
_(location).must_be_kind_of Inspec::Resources::NginxConfLocation
|
||||
end
|
||||
end
|
||||
|
||||
it 'doesnt fail on params == nil' do
|
||||
|
@ -136,7 +197,7 @@ describe 'Inspec::Resources::NginxConf' do
|
|||
let(:entry) { nginx_conf.servers[0] }
|
||||
|
||||
it 'pretty-prints in CLI' do
|
||||
_(entry.inspect).must_equal 'nginx_conf /etc/nginx/nginx.conf, server domain1.com:85'
|
||||
_(entry.inspect).must_equal 'nginx_conf /etc/nginx/nginx.conf, server domain1.com:80'
|
||||
end
|
||||
|
||||
it 'provides access to all its parameters' do
|
||||
|
@ -150,7 +211,9 @@ describe 'Inspec::Resources::NginxConf' do
|
|||
it 'provides access to all its locations' do
|
||||
_(entry.locations).must_be_kind_of Array
|
||||
_(entry.locations.length).must_equal 1
|
||||
_(entry.locations[0]).must_be_kind_of Inspec::Resources::NginxConfLocation
|
||||
entry.locations.each do |location|
|
||||
_(location).must_be_kind_of Inspec::Resources::NginxConfLocation
|
||||
end
|
||||
end
|
||||
|
||||
it 'doesnt fail on params == nil' do
|
||||
|
|
Loading…
Add table
Reference in a new issue