Skip to content

Commit

Permalink
adding inspec linting
Browse files Browse the repository at this point in the history
Signed-off-by: wdower <will@dower.dev>
  • Loading branch information
wdower committed May 9, 2024
1 parent dcfb14b commit a71fb0a
Show file tree
Hide file tree
Showing 54 changed files with 394 additions and 387 deletions.
58 changes: 58 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
AllCops:
Exclude:
- "libraries/**/*"

Layout/LineLength:
Max: 1500
AllowURI: true
IgnoreCopDirectives: true

Naming/FileName:
Enabled: false

Metrics/BlockLength:
Max: 1000

Lint/ConstantDefinitionInBlock:
Enabled: false

# Required for Profiles as it can introduce profile errors
Style/NumericPredicate:
Enabled: false

Style/WordArray:
Description: "Use %w or %W for an array of words. (https://rubystyle.guide#percent-w)"
Enabled: false

Style/RedundantPercentQ:
Enabled: true

Style/NestedParenthesizedCalls:
Enabled: false

Style/TrailingCommaInHashLiteral:
Description: "https://docs.rubocop.org/rubocop/cops_style.html#styletrailingcommainhashliteral"
Enabled: true
EnforcedStyleForMultiline: no_comma

Style/TrailingCommaInArrayLiteral:
Enabled: true
EnforcedStyleForMultiline: no_comma

Style/BlockDelimiters:
Enabled: false

Lint/AmbiguousBlockAssociation:
Enabled: false

Metrics/BlockNesting:
Enabled: false

Lint/ShadowingOuterLocalVariable:
Enabled: false

Style/FormatStringToken:
Enabled: false

Style/FrozenStringLiteralComment:
Enabled: false
24 changes: 24 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# frozen_string_literal: true

# !/usr/bin/env rake

require 'rake/testtask'
require 'rubocop/rake_task'

namespace :inspec do
desc 'validate the inspec profile'
task :check do
system 'bundle exec inspec check .'
end
end

begin
RuboCop::RakeTask.new(:lint) do |task|
task.options += %w[--display-cop-names --no-color --parallel]
end
rescue LoadError
puts 'rubocop is not available. Install the rubocop gem to run the lint tests.'
end

desc 'pre-commit checks'
task pre_commit_checks: [:lint, 'inspec:check']
13 changes: 6 additions & 7 deletions spec/mongo-inspec-profile/controls/SV-252134.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
To capture all operations in the audit, enable the audit system to log authorization successes by adding the following line to the /etc/mongod.conf file:
setParameter:
setParameter:
auditAuthorizationSuccess: true
Stop/start (restart) the mongod or mongos instance using this configuration.
Expand Down Expand Up @@ -82,17 +82,16 @@

describe.one do
describe mongodb_conf(input('mongod_config_path')) do
its(['auditLog','destination']){should eq "file"}
its(['auditLog','format']){should eq "BSON"}
its(['auditLog','path']){should match mongo_audit_file_path }
its(['auditLog','filter']){should match mongo_filter }
its(['auditLog', 'destination']) { should eq 'file' }
its(['auditLog', 'format']) { should eq 'BSON' }
its(['auditLog', 'path']) { should match mongo_audit_file_path }
its(['auditLog', 'filter']) { should match mongo_filter }
its(['setParameter', 'auditAuthorizationSuccess']) { should eq true }
end

describe mongodb_conf(input('mongod_config_path')) do
its(['auditLog', 'destination']) { should eq "syslog"}
its(['auditLog', 'destination']) { should eq 'syslog' }
its(['setParameter', 'auditAuthorizationSuccess']) { should eq true }
end
end

end
19 changes: 9 additions & 10 deletions spec/mongo-inspec-profile/controls/SV-252135.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
'
desc 'check', "MongoDB must not permit access to its audit logs by unprivileged users. The official installation packages restrict which operating system users and groups may read or modify files. The audit log destination is not configured or created at installation time and must be manually done with appropriate ownership and permissions applied with the MongoDB user and MongoDB group.
Check the MongoDB configuration file (default location: /etc/mongod.conf) for a key named auditLog with destination set to file.
Check the MongoDB configuration file (default location: /etc/mongod.conf) for a key named auditLog with destination set to file.
Example shown below:
Expand Down Expand Up @@ -65,17 +65,17 @@
Modify: 2020-03-16 12:50:48.722000000 -0400
Change: 2020-03-16 12:50:48.722000000 -0400
Birth: -"
desc 'fix', 'It is recommended to use the official installation packages provided by MongoDB. In the event the software was installed manually and permissions need to be restricted, consider a clean reinstallation.
desc 'fix', 'It is recommended to use the official installation packages provided by MongoDB. In the event the software was installed manually and permissions need to be restricted, consider a clean reinstallation.
If the key name auditLog.destination is set to either syslog or console, then this requirement is not applicable as there is no physical directory that MongoDB can secure. Site security requirements and operating system security requirements will need to be reviewed to ensure appropriate settings for syslog and console destinations.
To correct finding where a physical auditLog directory exists (where auditLog.destination is set to file), run these commands:
To correct finding where a physical auditLog directory exists (where auditLog.destination is set to file), run these commands:
chown mongod %MongoDB auditLog directory%
chgrp mongod %MongoDB auditLog directory%
chmod 700 %MongoDB auditLog directory%
(The path for the %MongoDB auditLog directory% will vary according to local circumstances. The auditLog directory will be found in the %MongoDB configuration file% whose default location is /etc/mongod.conf.)
(The path for the %MongoDB auditLog directory% will vary according to local circumstances. The auditLog directory will be found in the %MongoDB configuration file% whose default location is /etc/mongod.conf.)
To find the auditLog directory name, view and search for the entry in the %MongoDB configuration file% for the auditLog.path:
Expand All @@ -100,18 +100,18 @@
tag 'documentable'
tag cci: ['CCI-000162', 'CCI-000163', 'CCI-000164']
tag nist: ['AU-9 a', 'AU-9 a', 'AU-9 a']

mongo_owner = input('mongo_owner')
mongo_group = input('mongo_group')
mongo_permissions = input('mongo_permissions')
conf = mongodb_conf(input('mongod_config_path'))
conf = mongodb_conf(input('mongod_config_path'))
mongo_audit_file_path = input('mongo_audit_file_path')
mongo_audit_directory_path = input('mongo_audit_directory_path')
mongodb_audit_logs_params = conf.params['auditLog']

if mongodb_audit_logs_params['destination'] == 'file'
describe "Audit Log" do
it "should be configured correctly" do
describe 'Audit Log' do
it 'should be configured correctly' do
expect(mongodb_audit_logs_params['destination']).to eq('file')
expect(mongodb_audit_logs_params['format']).to eq('BSON')
expect(mongodb_audit_logs_params['path']).to eq(mongo_audit_file_path)
Expand All @@ -123,8 +123,7 @@

else
describe mongodb_conf(input('mongod_config_path')) do
its(['auditLog', 'destination']) { should eq "syslog"}
its(['auditLog', 'destination']) { should eq 'syslog' }
end
end

end
19 changes: 9 additions & 10 deletions spec/mongo-inspec-profile/controls/SV-252136.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@
If an attacker were to gain access to audit tools, they could analyze audit logs for system weaknesses or weaknesses in the auditing itself. An attacker could also manipulate logs to hide evidence of malicious activity.
'
desc 'check', 'To ensure audit configurations are protected from unauthorized modification, the default installation of MongoDB restricts permission on the configuration file.
desc 'check', 'To ensure audit configurations are protected from unauthorized modification, the default installation of MongoDB restricts permission on the configuration file.
Verify User ownership, Group ownership, and permissions on the MongoDB configuration file:
(default name and location is /etc/mongod.conf)
(The name and location for the MongoDB configuration file will vary according to local circumstances.)
(The name and location for the MongoDB configuration file will vary according to local circumstances.)
Using the default name and location the command would be:
Expand All @@ -30,19 +30,19 @@
If the filename is more permissive than 660, this is a finding.
Note that the audit destination cannot be modified at runtime.'
desc 'fix', 'Run these commands:
desc 'fix', 'Run these commands:
chown mongod %MongoDB configuration file%
chgrp mongod %MongoDB configuration file%
chown mongod %MongoDB configuration file%
chgrp mongod %MongoDB configuration file%
chmod 660 %MongoDB configuration file%
(The name and location for the %MongoDB configuration file% will vary according to local circumstances. The default name and location is /etc/mongod.conf.)
(The name and location for the %MongoDB configuration file% will vary according to local circumstances. The default name and location is /etc/mongod.conf.)
Using the default name and location the commands would be:
chown mongod /etc/mongod.conf
chgrp mongod /etc/mongod.conf
chmod 660 /etc/mongod.conf
chown mongod /etc/mongod.conf
chgrp mongod /etc/mongod.conf
chmod 660 /etc/mongod.conf
The output of the command:
Expand Down Expand Up @@ -80,5 +80,4 @@
it { should be_grouped_into input('mongo_group') }
it { should_not be_more_permissive_than(input('mongo_permissions')) }
end

end
3 changes: 1 addition & 2 deletions spec/mongo-inspec-profile/controls/SV-252137.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
tag nist: ['CM-7 a']

describe mongodb_conf(input('mongod_config_path')) do
its(['net','http']){should be nil}
its(['net', 'http']) { should be nil }
end

end
5 changes: 2 additions & 3 deletions spec/mongo-inspec-profile/controls/SV-252138.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,8 @@
tag 'documentable'
tag cci: ['CCI-000382']
tag nist: ['CM-7 b']

describe mongodb_conf(input('mongod_config_path')) do
its(['net','http']){should be nil}
its(['net', 'http']) { should be nil }
end

end
11 changes: 5 additions & 6 deletions spec/mongo-inspec-profile/controls/SV-252139.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,10 @@
tag nist: ['IA-5 (1) (c)', 'IA-5 (2) (b) (1)']

describe mongodb_conf(input('mongod_config_path')) do
its(['net','tls','mode']){should eq "requireTLS"}
its(['net','tls','certificateKeyFile']){should match input('certificate_key_file_dest')}
its(['net','tls','CAFile']){should match input('ca_file_dest')}
its(['net','tls','allowInvalidCertificates']){should eq false}
its(['net','tls','allowConnectionsWithoutCertificates']){should eq false}
its(['net', 'tls', 'mode']) { should eq 'requireTLS' }
its(['net', 'tls', 'certificateKeyFile']) { should match input('certificate_key_file_dest') }
its(['net', 'tls', 'CAFile']) { should match input('ca_file_dest') }
its(['net', 'tls', 'allowInvalidCertificates']) { should eq false }
its(['net', 'tls', 'allowConnectionsWithoutCertificates']) { should eq false }
end

end
50 changes: 24 additions & 26 deletions spec/mongo-inspec-profile/controls/SV-252140.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
Accordingly, a risk assessment is used in determining the authentication needs of the organization.
Scalability, practicality, and security are simultaneously considered in balancing the need to ensure ease of use for access to federal information and information systems with the need to protect and adequately mitigate risk to organizational operations, organizational assets, individuals, other organizations, and the Nation.'
desc 'check', "MongoDB grants access to data and commands through role-based authorization and provides built-in roles that provide the different levels of access commonly needed in a database system. Additionally, user-defined roles can be created.
desc 'check', "MongoDB grants access to data and commands through role-based authorization and provides built-in roles that provide the different levels of access commonly needed in a database system. Additionally, user-defined roles can be created.
Check a user's role to ensure correct privileges for the function:
Expand All @@ -22,35 +22,35 @@
The server will return a document with the all users in the data and their associated roles.
View a roles' privileges:
View a roles' privileges:
For each database, identify the privileges granted by a role:
use database
db.getRole( %rolename%, { showPrivileges: true } )
The server will return a document with the privileges and inheritedPrivileges arrays.
The server will return a document with the privileges and inheritedPrivileges arrays.
The privileges returned document lists the privileges directly specified by the role and excludes those privileges inherited from other roles.
The privileges returned document lists the privileges directly specified by the role and excludes those privileges inherited from other roles.
The inheritedPrivileges returned document lists all privileges granted by this role, both directly specified and inherited. If the role does not inherit from other roles, the two fields are the same.
If a user has a role with inappropriate privileges, this is a finding."
desc 'fix', "Administrators using MongoDB should document the appropriate privileges for various roles appropriate to the application.
For each database, identify the user's roles for the database.
For each database, identify the user's roles for the database.
use database
db.getUser(%username%)
The server will return a document with the user's roles.
To revoke a user's role from a database, run the following:
To revoke a user's role from a database, run the following:
db.revokeRolesFromUser( %username%, [ roles ], { writeConcern } )
To grant a role to a user run the following:
db.grantRolesToUser( %username%, [ roles ], { writeConcern } )"
impact 0.5
ref 'DPMS Target MongoDB Enterprise Advanced 4.x'
Expand All @@ -65,35 +65,33 @@
tag cci: ['CCI-001082']
tag nist: ['SC-2']

get_system_users = "EJSON.stringify(db.system.users.find().toArray())"
get_system_users = 'EJSON.stringify(db.system.users.find().toArray())'

run_get_system_users = "mongosh \"mongodb://#{input('mongo_dba')}:#{input('mongo_dba_password')}@#{input('mongo_host')}:#{input('mongo_port')}/admin?authSource=#{input 'mongo_auth_source'}&tls=true&tlsCAFile=#{input('ca_file')}&tlsCertificateKeyFile=#{input('certificate_key_file')}\" --quiet --eval \"#{get_system_users}\""

run_get_system_users = "mongosh \"mongodb://#{input('mongo_dba')}:#{input('mongo_dba_password')}@#{input('mongo_host')}:#{input('mongo_port')}/admin?authSource=#{input'mongo_auth_source'}&tls=true&tlsCAFile=#{input('ca_file')}&tlsCertificateKeyFile=#{input('certificate_key_file')}\" --quiet --eval \"#{get_system_users}\""
system_users = json({ command: run_get_system_users }).params

system_users = json({command: run_get_system_users}).params

system_users.each do |user|
user_id = user['_id']
unless input('mongo_superusers').include?(user_id)
next if input('mongo_superusers').include?(user_id)

db_name = user['db']
user_roles = user['roles'].map { |role| "#{role['role']}" }
db_roles = user_roles.map { |role| "#{db_name}.#{role}" }
db_name = user['db']
user_roles = user['roles'].map { |role| (role['role']).to_s }
user_roles.map { |role| "#{db_name}.#{role}" }

user_roles.each do |role|
run_get_role = "mongosh \"mongodb://#{input('mongo_dba')}:#{input('mongo_dba_password')}@#{input('mongo_host')}:#{input('mongo_port')}/#{db_name}?authSource=#{input'mongo_auth_source'}&tls=true&tlsCAFile=#{input('ca_file')}&tlsCertificateKeyFile=#{input('certificate_key_file')}\" --quiet --eval \"EJSON.stringify(db.getRole('#{role}', {showPrivileges: true}))\""
user_roles.each do |role|
run_get_role = "mongosh \"mongodb://#{input('mongo_dba')}:#{input('mongo_dba_password')}@#{input('mongo_host')}:#{input('mongo_port')}/#{db_name}?authSource=#{input 'mongo_auth_source'}&tls=true&tlsCAFile=#{input('ca_file')}&tlsCertificateKeyFile=#{input('certificate_key_file')}\" --quiet --eval \"EJSON.stringify(db.getRole('#{role}', {showPrivileges: true}))\""

role_output = json({command: run_get_role}).params
role_output = json({ command: run_get_role }).params

all_actions = role_output["privileges"].map { |privilege| privilege["actions"] } +
role_output["inheritedPrivileges"].map { |privilege| privilege["actions"] }
all_actions.flatten!
all_actions = role_output['privileges'].map { |privilege| privilege['actions'] } +
role_output['inheritedPrivileges'].map { |privilege| privilege['actions'] }
all_actions.flatten!

describe "Role '#{role}' of user #{user['_id']} has the proper privileges" do
subject { all_actions }
it { should_not be_in input('inappropriate_mongo_privileges') }
end
describe "Role '#{role}' of user #{user['_id']} has the proper privileges" do
subject { all_actions }
it { should_not be_in input('inappropriate_mongo_privileges') }
end
end
end

end

0 comments on commit a71fb0a

Please sign in to comment.