Skip to content

Commit

Permalink
Merge pull request #766 from inspec/varunsharma5/aws_emr_sec_config
Browse files Browse the repository at this point in the history
Added support for AWS::EMR::SecurityConfiguration.
  • Loading branch information
Nirbhay1997 committed Nov 19, 2021
2 parents 06544df + 6326eb7 commit b83df3a
Show file tree
Hide file tree
Showing 12 changed files with 559 additions and 0 deletions.
93 changes: 93 additions & 0 deletions docs/resources/aws_emr_security_configuration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
---
title: About the aws_emr_security_configuration Resource
platform: aws
---

# aws_emr_security_configuration

Use the `aws_emr_security_configuration` InSpec audit resource to test properties of the singular resource of AWS EMR security configuration.

## Syntax

An `aws_emr_security_configuration` resource block declares the tests for a single AWS EMR security configuration by `security_configuration_name`.

```ruby
describe aws_emr_security_configuration(security_configuration_name: 'SECURITY_CONFIGURATION_NAME') do
it { should exist }
end
```

```ruby
describe aws_emr_security_configuration('SECURITY_CONFIGURATION_NAME') do
it { should exist }
end
```

## Parameters

`security_configuration_name` _(required)_

This resource requires a single parameter, the EMR security configuration name.
This can be passed either as a string or as a `security_configuration_name: 'value'` key-value entry in a hash.

See also the [AWS documentation on AWS EMR security configuration](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-emr-securityconfiguration.html).

## Properties

|Property | Description|
| --- | --- |
|encryption_at_rest | Specifies whether at-rest encryption is enabled for the cluster.|
|encryption_in_transit | Specifies whether in-transit encryption is enabled for the cluster.|
|local_disk_encryption | Specifies whether local-disk encryption is enabled for the cluster. |

## Examples

### Test that an EMR security configuration has at-rest encryption enabled

```ruby
describe aws_emr_security_configuration('SECURITY_CONFIGURATION_NAME') do
its ('encryption_at_rest') { should eq true }
end
```

### Test that an EMR security configuration has in-transit encryption enabled

```ruby
describe aws_emr_security_configuration('SECURITY_CONFIGURATION_NAME') do
its ('encryption_in_transit') { should eq true }
end
```

### Test that an EMR security configuration has local-disk encryption enabled

```ruby
describe aws_emr_security_configuration('SECURITY_CONFIGURATION_NAME') do
its ('local_disk_encryption') { should eq true }
end
```

## Matchers

This InSpec audit resource has the following special matchers. For a full list of available matchers, please visit our [matchers page](https://www.inspec.io/docs/reference/matchers/).

### exist

Use `should` to test the entity should exist.

```ruby
describe aws_emr_security_configuration('SECURITY_CONFIGURATION_NAME') do
it { should exist }
end
```

Use `should_not` to test the entity should not exist.

```ruby
describe aws_emr_security_configuration('SECURITY_CONFIGURATION_NAME') do
it { should_not exist }
end
```

## AWS Permissions

Your [Principal](https://docs.aws.amazon.com/IAM/latest/UserGuide/intro-structure.html#intro-structure-principal) will need the `EMR:Client:DescribeSecurityConfigurationOutput` action with `Effect` set to `Allow`.
70 changes: 70 additions & 0 deletions docs/resources/aws_emr_security_configurations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
---
title: About the aws_emr_security_configurationss Resource
platform: aws
---

# aws_emr_security_configurations

Use the `aws_emr_security_configurations` resource to test the properties of collection for AWS EMR security configuration.

## Syntax

```ruby
describe aws_emr_security_configurations do
it { should exist }
end
```

### Parameters

This resource does not expect any parameters.

See also the [AWS documentation on AWS EMR security configuration](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-emr-securityconfiguration.html).

## Properties

|Property | Description|Fields |
| --- | --- |---|
|security_configuration_names |The name of the security configuration.|name|
|encryption_at_rest | Specifies whether at-rest encryption is enabled for the cluster.|security_configuration(EncryptionConfiguration(EnableAtRestEncryption))|
|encryption_in_transit | Specifies whether in-transit encryption is enabled for the cluster.|security_configuration(EncryptionConfiguration(EnableInTransitEncryption))|
|local_disk_encryption | Specifies whether local-disk encryption is enabled for the cluster. |security_configuration(EncryptionConfiguration(AtRestEncryptionConfiguration(LocalDiskEncryptionConfiguration)))|

## Examples

#### Ensure AWS EMR security configurations exists

```ruby
describe aws_emr_security_configurations do
it { should exist }
its('encryption_at_rests') { should include encryption_at_rest }
its('encryption_in_transits') { should include encryption_in_transit }
its('local_disk_encryptions') { should include local_disk_encryption }
end
```

## Matchers

For a full list of available matchers, please visit our [matchers page](https://docs.chef.io/inspec/matchers/).

### exist

Use `should` to test an entity that should exist.

```ruby
describe aws_emr_security_configurations.where(security_configuration_name: 'SECURITY_CONFIGURATION_NAME') do
it { should exist }
end
```

Use `should_not` to test an entity that should not exist.

```ruby
describe aws_emr_security_configurations.where(security_configuration_name: 'INVALID_SECURITY_CONFIGURATION_NAME') do
it { should_not exist }
end
```

## AWS Permissions

Your [Principal](https://docs.aws.amazon.com/IAM/latest/UserGuide/intro-structure.html#intro-structure-principal) will need the `EMR:Client:DescribeSecurityConfigurationOutput` action with `Effect` set to `Allow`.
5 changes: 5 additions & 0 deletions libraries/aws_backend.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
require 'aws-sdk-signer'
require 'aws-sdk-amplify'
require 'aws-sdk-simpledb'
require 'aws-sdk-emr'

# AWS Inspec Backend Classes
#
Expand Down Expand Up @@ -306,6 +307,10 @@ def network_firewall_client
def simpledb_client
aws_client(Aws::SimpleDB::Client)
end

def emr_client
aws_client(Aws::EMR::Client)
end
end

# Base class for AWS resources
Expand Down
48 changes: 48 additions & 0 deletions libraries/aws_emr_security_configuration.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# frozen_string_literal: true

require 'aws_backend'
require 'json'

class AwsEmrClusterSecurityConfiguration < AwsResourceBase
name 'aws_emr_security_configuration'
desc 'Verifies security configuration for an EMR cluster.'

example "
describe aws_emr_security_configuration('SECURITY_CONFIGURATION_NAME') do
it { should exist }
its('encryption_at_rest') { should eq true }
its('encryption_in_transit') { should eq true }
its('local_disk_encryption') { should eq true }
end
"

attr_reader :security_configuration_name, :encryption_at_rest, :encryption_in_transit, :local_disk_encryption

def initialize(opts = {})
opts = { security_configuration_name: opts } if opts.is_a?(String)
super(opts)
validate_parameters(required: %i(security_configuration_name))
catch_aws_errors do
@security_configuration_name = opts[:security_configuration_name]

resp = @aws.emr_client.describe_security_configuration({ name: @security_configuration_name })
return if resp.nil? || resp.empty?
json_security_configuration = resp.security_configuration
return if json_security_configuration.nil? || json_security_configuration.empty?
parsed_json = JSON.parse(json_security_configuration)
@encryption_at_rest = !parsed_json['EncryptionConfiguration']['EnableAtRestEncryption'].nil? && parsed_json['EncryptionConfiguration']['EnableAtRestEncryption']
@encryption_in_transit = !parsed_json['EncryptionConfiguration']['EnableInTransitEncryption'].nil? && parsed_json['EncryptionConfiguration']['EnableInTransitEncryption']
@local_disk_encryption = !parsed_json['EncryptionConfiguration']['AtRestEncryptionConfiguration'].nil? &&
!parsed_json['EncryptionConfiguration']['AtRestEncryptionConfiguration']['LocalDiskEncryptionConfiguration'].nil? &&
!parsed_json['EncryptionConfiguration']['AtRestEncryptionConfiguration']['LocalDiskEncryptionConfiguration'].empty?
end
end

def exists?
!@security_configuration_name.nil? && !@security_configuration_name.empty?
end

def to_s
"AWS EMR Cluster Security Configuration Name: #{@security_configuration_name}"
end
end
55 changes: 55 additions & 0 deletions libraries/aws_emr_security_configurations.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# frozen_string_literal: true

require 'aws_backend'
require 'json'

class AwsEmrClusterSecurityConfigurations < AwsResourceBase
name 'aws_emr_security_configurations'
desc 'Verifies collection of security configuration for an EMR cluster.'
example "
describe aws_emr_security_configurations do
it { should exist }
end
"
attr_reader :table

FilterTable.create
.register_column(:security_configuration_names, field: :security_configuration_name)
.register_column(:encryption_at_rests, field: :encryption_at_rest)
.register_column(:encryption_in_transits, field: :encryption_in_transit)
.register_column(:local_disk_encryptions, field: :local_disk_encryption)
.install_filter_methods_on_resource(self, :table)

def initialize(opts = {})
super(opts)
validate_parameters
@table = fetch_data
end

def fetch_data
security_configuration_rows = []
pagination_options = {}
resp_security_configurations = {}
catch_aws_errors do
resp_security_configurations = @aws.emr_client.list_security_configurations(pagination_options)
end

return security_configuration_rows if !resp_security_configurations || resp_security_configurations.empty?

resp_security_configurations.security_configurations.each do |s|
resp_security_configuration = @aws.emr_client.describe_security_configuration({ name: s.name })
parsed_json = JSON.parse(resp_security_configuration.security_configuration)
encryption_at_rest = !parsed_json['EncryptionConfiguration']['EnableAtRestEncryption'].nil? && parsed_json['EncryptionConfiguration']['EnableAtRestEncryption']
encryption_in_transit = !parsed_json['EncryptionConfiguration']['EnableInTransitEncryption'].nil? && parsed_json['EncryptionConfiguration']['EnableInTransitEncryption']
local_disk_encryption = !parsed_json['EncryptionConfiguration']['AtRestEncryptionConfiguration'].nil? &&
!parsed_json['EncryptionConfiguration']['AtRestEncryptionConfiguration']['LocalDiskEncryptionConfiguration'].nil? &&
!parsed_json['EncryptionConfiguration']['AtRestEncryptionConfiguration']['LocalDiskEncryptionConfiguration'].empty?

security_configuration_rows += [{ security_configuration_name: s.name,
encryption_at_rest: encryption_at_rest,
encryption_in_transit: encryption_in_transit,
local_disk_encryption: local_disk_encryption }]
end
@table = security_configuration_rows
end
end
8 changes: 8 additions & 0 deletions test/integration/build/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -1148,4 +1148,12 @@ output "app_id" {

output "branch_name" {
value = aws_amplify_app.test-app.name
}

output "aws_emr_security_configuration_name" {
value = aws_emr_security_configuration.emr_security_configuration.name
}

output "aws_emr_security_configuration_json" {
value = aws_emr_security_configuration.emr_security_configuration.configuration
}
1 change: 1 addition & 0 deletions test/integration/configuration/aws_inspec_config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ def self.region_parser(raw)
aws_elb_access_log_name: "elb-log-name-#{add_random_string}",
aws_elb_access_log_prefix: "elb-log-prefix-#{add_random_string}",
aws_elb_name: "elb-#{add_random_string}",
aws_emr_security_configuration_name: "emr-sec-config-#{add_random_string}",
aws_flow_log_bucket_name: "aws-flow-log-bucket-#{add_random_string}",
aws_iam_user_name: "iam-user-#{add_random_string}",
aws_iam_user_policy_name: "iam-user-policy-#{add_random_string}",
Expand Down
26 changes: 26 additions & 0 deletions test/integration/verify/controls/aws_emr_security_configuration.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
require 'json'

aws_emr_security_configuration_name = attribute(:aws_emr_security_configuration_name, value: '', description: 'The Name of the EMR Security Configuration.')
aws_emr_security_configuration_name.gsub!('"', '')
aws_emr_security_configuration_json = attribute(:aws_emr_security_configuration_json, value: '', description: 'The JSON formatted Security Configuration.')
aws_emr_security_configuration_json.gsub!('EOT', '')
aws_emr_security_configuration_json.gsub!('<<', '')

parsed_json = JSON.parse(aws_emr_security_configuration_json.strip)
encryption_at_rest = !parsed_json['EncryptionConfiguration']['EnableAtRestEncryption'].nil? && parsed_json['EncryptionConfiguration']['EnableAtRestEncryption']
encryption_in_transit = !parsed_json['EncryptionConfiguration']['EnableInTransitEncryption'].nil? && parsed_json['EncryptionConfiguration']['EnableInTransitEncryption']
local_disk_encryption = !parsed_json['EncryptionConfiguration']['AtRestEncryptionConfiguration'].nil? &&
!parsed_json['EncryptionConfiguration']['AtRestEncryptionConfiguration']['LocalDiskEncryptionConfiguration'].nil? &&
!parsed_json['EncryptionConfiguration']['AtRestEncryptionConfiguration']['LocalDiskEncryptionConfiguration'].empty?

control 'aws-emr-security-configuration-1.0' do
impact 1.0
title 'Test single AWS EMR Security Configuration'

describe aws_emr_security_configuration(security_configuration_name: aws_emr_security_configuration_name) do
it { should exist }
its('encryption_at_rest'){ should eq encryption_at_rest }
its('encryption_in_transit'){ should eq encryption_in_transit }
its('local_disk_encryption'){ should eq local_disk_encryption }
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
require 'json'

aws_emr_security_configuration_name = attribute(:aws_emr_security_configuration_name, value: '', description: 'The Name of the EMR Security Configuration.')
aws_emr_security_configuration_name.gsub!('"', '')
aws_emr_security_configuration_json = attribute(:aws_emr_security_configuration_json, value: '', description: 'The JSON formatted Security Configuration.')
aws_emr_security_configuration_json.gsub!('EOT', '')
aws_emr_security_configuration_json.gsub!('<<', '')
parsed_json = JSON.parse(aws_emr_security_configuration_json.strip)
encryption_at_rest = !parsed_json['EncryptionConfiguration']['EnableAtRestEncryption'].nil? && parsed_json['EncryptionConfiguration']['EnableAtRestEncryption']
encryption_in_transit = !parsed_json['EncryptionConfiguration']['EnableInTransitEncryption'].nil? && parsed_json['EncryptionConfiguration']['EnableInTransitEncryption']
local_disk_encryption = !parsed_json['EncryptionConfiguration']['AtRestEncryptionConfiguration'].nil? &&
!parsed_json['EncryptionConfiguration']['AtRestEncryptionConfiguration']['LocalDiskEncryptionConfiguration'].nil? &&
!parsed_json['EncryptionConfiguration']['AtRestEncryptionConfiguration']['LocalDiskEncryptionConfiguration'].empty?

control 'aws-emr-security-configurations-1.0' do
impact 1.0
title 'Test AWS EMR Security Configuration in bulk'

describe aws_emr_security_configurations do
it { should exist }
end

describe aws_emr_security_configurations.where(security_configuration_name: aws_emr_security_configuration_name) do
it { should exist }
its('encryption_at_rests') { should include encryption_at_rest }
its('encryption_in_transits') { should include encryption_in_transit }
its('local_disk_encryptions') { should include local_disk_encryption }
end
end
Loading

0 comments on commit b83df3a

Please sign in to comment.