Skip to content

Commit

Permalink
fixed 81875, 81887. Added mongodb resource
Browse files Browse the repository at this point in the history
Signed-off-by: HackerShark <[email protected]>
  • Loading branch information
HackerShark committed Jun 8, 2021
1 parent 1bb651f commit 5af90d9
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 6 deletions.
10 changes: 8 additions & 2 deletions controls/V-81875.rb
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,13 @@
tag "documentable": false
tag "severity_override_guidance": false

describe yaml(input('mongod_conf')) do
its(%w{net ssl FIPSMode}) { should cmp 'true' }
if input('is_sensitive')
describe yaml(input('mongod_conf')) do
its(%w{net ssl FIPSMode}) { should cmp 'true' }
end
else
describe 'The system is not a classified environment, therefore for this control is NA' do

This comment has been minimized.

Copy link
@aaronlippold

aaronlippold Jun 8, 2021

Member

please avoid words like 'classified' - use, sensitive

skip 'The system is not a classified environment, therefore for this control is NA'
end
end
end
11 changes: 7 additions & 4 deletions controls/V-81887.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,14 @@
tag "documentable": false
tag "severity_override_guidance": false

mongodb_service_account = input('mongodb_service_account')
mongodb_service_group = input('mongodb_service_group')

if file(input('mongod_conf')).exist?
describe file(input('mongod_conf')) do
it { should_not be_more_permissive_than('0755') }
its('owner') { should be_in input('mongodb_service_account') }
its('group') { should be_in input('mongodb_service_group') }
its('owner') { should be_in mongodb_service_account }
its('group') { should be_in mongodb_service_group }
end
else
describe 'This control must be reviewed manually because the configuration
Expand All @@ -60,8 +63,8 @@
if file(input('mongo_data_dir')).exist?
describe directory(input('mongo_data_dir')) do
it { should_not be_more_permissive_than('0755') }
its('owner') { should be_in input('mongodb_service_account') }
its('group') { should be_in input('mongodb_service_group') }
its('owner') { should be_in mongodb_service_account }
its('group') { should be_in mongodb_service_group }
end
else
describe 'This control must be reviewed manually because the Mongodb data
Expand Down
1 change: 1 addition & 0 deletions inputs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,4 @@ accountAdmin01_allowed_role: ['[
] }
']
is_sensitive: true
5 changes: 5 additions & 0 deletions inspec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -134,3 +134,8 @@ inputs:
description: Mongodb Service Group
type: array
value: ["mongodb", "mongod"]

- name: is_sensitive
description: MongoDB is deployed in a classified environment

This comment has been minimized.

Copy link
@aaronlippold

aaronlippold Jun 8, 2021

Member

Never name the Sponsor or Env. No indication that we are talking about NSS. Use senstitive.

type: boolean
value: true
116 changes: 116 additions & 0 deletions libraries/mongo_command.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
require 'json'

This comment has been minimized.

Copy link
@aaronlippold

aaronlippold Jun 8, 2021

Member

Does this DB resource take any hints from the new PRs on the inSpec project about knowing when it is connected or not connected, false results etc. If not, it may be a good idea to see if we can borrow from that.


class MongoCommand < Inspec.resource(1)
name 'mongo_command'
desc 'Runs a MongoDB command using the mongo CLI against a given database (default database: admin)'
example <<-EOL
describe mongo_command('db.showRoles()') do
its('params.length') { should be > 0 }
end
EOL

attr_reader :command, :database, :params

def initialize(command, options = {})
@command = command
@username = options[:username]
@password = options[:password]
@database = options.fetch(:database, 'admin')
@allow_auth_errors = options.fetch(:allow_auth_errors, false)
@tls = options.fetch(:tls, true)
@verify_ssl = options.fetch(:verify_ssl, true)

check_for_cli_command
@inspec_command = run_mongo_command(command)
@params = parse(@inspec_command.stdout)
end

def stdout
@inspec_command.stdout
end

def stderr
@inspec_command.stderr
end

def to_s
str = "MongoDB Command (#{@command}"
str += ", username: #{@username}" unless @username.nil?
str += ", password: <hidden>" unless @password.nil?
str += ')'

str
end

private

def parse(output)
# return right away if stdout is nil
return [] if output.nil?

# strip any network warnings from the output
# Unfortunately, it appears the --sslAllowInvalidHostnames doesn't actually squelch
# any warnings, even when using --quiet mode
output_lines = output.lines.delete_if { |line| line.include?(' W NETWORK ')}
output_lines = output.lines.delete_if { |line| line.include?('UUID(')}

# if, after removing any network warnings, there are no lines to process,
# we received no command output.
return [] if output_lines.empty?

# put our output back together as a string
output = output_lines.join

# skip the whole resource if we could not run the command at all
return skip_resource "User is not authorized to run command #{command}" if
is_auth_error?(output) && !auth_errors_allowed?

# if the output indicates there's an authorization error, and we allow auth
# errors, we won't throw an exception, just set the params to an empty array.
return [] if is_auth_error?(output) && auth_errors_allowed?

# At this point, we should have parseable JSON we can use and no auth errors.
# Let's read it in.
JSON.parse(output.to_s)
rescue JSON::ParserError => e
skip_resource "Unable to parse JSON response from mongo client: #{e.message}" unless @allow_auth_errors
[]
end

def check_for_cli_command
check_command = inspec.command(format_command("db.version()"))
if check_command.exit_status != 0
skip_resource "Unable to run mongo commands: #{check_command.stderr}"
end
end

def run_mongo_command(command)
inspec.command(format_command(command))
end

def tls_verify_disabled?
['false', false].include?(@verify_ssl)
end

def tls_disabled?
['false', false].include?(@tls)
end

def is_auth_error?(output)
output.include?('Error: not authorized')
end

def auth_errors_allowed?
@allow_auth_errors == true
end

def format_command(command)
command = %{echo "#{command}" | mongo --quiet #{database}}
command += " --tls" unless tls_disabled?
command += " --username #{@username}" unless @username.nil?
command += " --password #{@password}" unless @password.nil?
command += " --tlsAllowInvalidCertificates" if tls_verify_disabled? && tls_disabled?
command += " --tlsAllowInvalidHostnames" if tls_verify_disabled? && tls_disabled?
command
end
end

0 comments on commit 5af90d9

Please sign in to comment.