Skip to content

Commit

Permalink
Feature/253 remaining password property rules (#345)
Browse files Browse the repository at this point in the history
* #253 adding SecretToken rule for CodePipeline Webhook AuthenticationConfiguration

* #253 adding AuthToken rule for ElastiCache ReplicationGroup

* #253 adding EventSourceToken rule for Lambda Permission

* #253 adding AdminPassword rule for ManagedBlockChain Member MemberFabricationConfiguration

* #253 adding MasterUserPassword rule for DocDB DBCluster

* Update CodePipelineWebhookAuthenticationConfigurationSecretTokenRule.rb

* #253 adding check to ensure the optional property exists in template before running secure check against value

Co-authored-by: Eric Kascic <eric.kascic@stelligent.com>
  • Loading branch information
Peter Helewski and Eric Kascic committed Jan 16, 2020
1 parent 76801cc commit c1868bd
Show file tree
Hide file tree
Showing 50 changed files with 910 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# frozen_string_literal: true

require 'cfn-nag/violation'
require_relative 'password_base_rule'

class CodePipelineWebhookAuthenticationConfigurationSecretTokenRule < PasswordBaseRule
def rule_text
'CodePipeline Webhook AuthenticationConfiguration SecretToken must not be ' \
'a plaintext string or a Ref to a NoEcho Parameter with a Default value.'
end

def rule_type
Violation::FAILING_VIOLATION
end

def rule_id
'F69'
end

def resource_type
'AWS::CodePipeline::Webhook'
end

def password_property
:authenticationConfiguration
end

def sub_property_name
'SecretToken'
end
end
27 changes: 27 additions & 0 deletions lib/cfn-nag/custom_rules/DocDBDBClusterMasterUserPasswordRule.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# frozen_string_literal: true

require 'cfn-nag/violation'
require_relative 'password_base_rule'

class DocDBDBClusterMasterUserPasswordRule < PasswordBaseRule
def rule_text
'DocDB DB Cluster master user password must not be a plaintext string ' \
'or a Ref to a NoEcho Parameter with a Default value.'
end

def rule_type
Violation::FAILING_VIOLATION
end

def rule_id
'F70'
end

def resource_type
'AWS::DocDB::DBCluster'
end

def password_property
:masterUserPassword
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# frozen_string_literal: true

require 'cfn-nag/violation'
require_relative 'password_base_rule'

class ElastiCacheReplicationGroupAuthTokenRule < PasswordBaseRule
def rule_text
'ElastiCache ReplicationGroup AuthToken must not be a plaintext string ' \
'or a Ref to a NoEcho Parameter with a Default value.'
end

def rule_type
Violation::FAILING_VIOLATION
end

def rule_id
'F44'
end

def resource_type
'AWS::ElastiCache::ReplicationGroup'
end

def password_property
:authToken
end
end
27 changes: 27 additions & 0 deletions lib/cfn-nag/custom_rules/LambdaPermissionEventSourceTokenRule.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# frozen_string_literal: true

require 'cfn-nag/violation'
require_relative 'password_base_rule'

class LambdaPermissionEventSourceTokenRule < PasswordBaseRule
def rule_text
'Lambda Permission EventSourceToken must not be a plaintext string ' \
'or a Ref to a NoEcho Parameter with a Default value.'
end

def rule_type
Violation::FAILING_VIOLATION
end

def rule_id
'F45'
end

def resource_type
'AWS::Lambda::Permission'
end

def password_property
:eventSourceToken
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# frozen_string_literal: true

require 'cfn-nag/violation'
require 'cfn-nag/util/enforce_reference_parameter'
require 'cfn-nag/util/enforce_string_or_dynamic_reference'
require_relative 'base'

class ManagedBlockchainMemberMemberFabricConfigurationAdminPasswordRule < BaseRule
def rule_text
'ManagedBlockchain Member MemberFabricConfiguration AdminPasswordRule must ' \
'not be a plaintext string or a Ref to a NoEcho Parameter with a Default value.'
end

def rule_type
Violation::FAILING_VIOLATION
end

def rule_id
'F71'
end

def audit_impl(cfn_model)
managed_blockchain_members = cfn_model.resources_by_type('AWS::ManagedBlockchain::Member')
violating_managed_blockchains = managed_blockchain_members.select do |member|
if password_property_does_not_exist(member)
false
else
pw = member.memberConfiguration['MemberFrameworkConfiguration']['MemberFabricConfiguration']['AdminPassword']
insecure_parameter?(cfn_model, pw) ||
insecure_string_or_dynamic_reference?(cfn_model, pw)
end
end

violating_managed_blockchains.map(&:logical_resource_id)
end

private

# Checks to see if these properties are present as they are optional
# properties for the 'AWS::ManagedBlockchain::Member' resource:
# 'MemberFrameworkConfiguration'
# 'MemberFabricConfiguration'
# 'AdminPassword'
def password_property_does_not_exist(member)
if member.memberConfiguration['MemberFrameworkConfiguration'].nil?
true
elsif member.memberConfiguration['MemberFrameworkConfiguration']['MemberFabricConfiguration'].nil?
true
elsif member.memberConfiguration['MemberFrameworkConfiguration']['MemberFabricConfiguration']['AdminPassword'].nil?
true
else
false
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
require 'spec_helper'
require 'password_rule_spec_helper'
require 'cfn-model'

resource_type = 'AWS::CodePipeline::Webhook'
password_property = 'AuthenticationConfiguration'
sub_property_name = 'SecretToken'
test_template_type = 'yaml'

require "cfn-nag/custom_rules/#{rule_name(resource_type, password_property, sub_property_name)}"

describe Object.const_get(rule_name(resource_type, password_property, sub_property_name)), :rule do
# Creates dynamic set of contexts based on the password_rule_test_sets hash
password_rule_test_sets.each do |test_description, desired_test_result|
context "#{resource_type} #{password_property} #{sub_property_name} #{test_description}" do
it context_return_value(desired_test_result) do
run_test(resource_type, password_property, sub_property_name,
test_template_type, test_description, desired_test_result)
end
end
end
end
22 changes: 22 additions & 0 deletions spec/custom_rules/DocDBDBClusterMasterUserPasswordRule_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
require 'spec_helper'
require 'password_rule_spec_helper'
require 'cfn-model'

resource_type = 'AWS::DocDB::DBCluster'
password_property = 'MasterUserPassword'
sub_property_name = nil
test_template_type = 'yaml'

require "cfn-nag/custom_rules/#{rule_name(resource_type, password_property, sub_property_name)}"

describe Object.const_get(rule_name(resource_type, password_property, sub_property_name)), :rule do
# Creates dynamic set of contexts based on the password_rule_test_sets hash
password_rule_test_sets.each do |test_description, desired_test_result|
context "#{resource_type} #{password_property} #{test_description}" do
it context_return_value(desired_test_result) do
run_test(resource_type, password_property, sub_property_name,
test_template_type, test_description, desired_test_result)
end
end
end
end
22 changes: 22 additions & 0 deletions spec/custom_rules/ElastiCacheReplicationGroupAuthTokenRule_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
require 'spec_helper'
require 'password_rule_spec_helper'
require 'cfn-model'

resource_type = 'AWS::ElastiCache::ReplicationGroup'
password_property = 'AuthToken'
sub_property_name = nil
test_template_type = 'yaml'

require "cfn-nag/custom_rules/#{rule_name(resource_type, password_property, sub_property_name)}"

describe Object.const_get(rule_name(resource_type, password_property, sub_property_name)), :rule do
# Creates dynamic set of contexts based on the password_rule_test_sets hash
password_rule_test_sets.each do |test_description, desired_test_result|
context "#{resource_type} #{password_property} #{test_description}" do
it context_return_value(desired_test_result) do
run_test(resource_type, password_property, sub_property_name,
test_template_type, test_description, desired_test_result)
end
end
end
end
22 changes: 22 additions & 0 deletions spec/custom_rules/LambdaPermissionEventSourceTokenRule_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
require 'spec_helper'
require 'password_rule_spec_helper'
require 'cfn-model'

resource_type = 'AWS::Lambda::Permission'
password_property = 'EventSourceToken'
sub_property_name = nil
test_template_type = 'yaml'

require "cfn-nag/custom_rules/#{rule_name(resource_type, password_property, sub_property_name)}"

describe Object.const_get(rule_name(resource_type, password_property, sub_property_name)), :rule do
# Creates dynamic set of contexts based on the password_rule_test_sets hash
password_rule_test_sets.each do |test_description, desired_test_result|
context "#{resource_type} #{password_property} #{test_description}" do
it context_return_value(desired_test_result) do
run_test(resource_type, password_property, sub_property_name,
test_template_type, test_description, desired_test_result)
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
require 'spec_helper'
require 'cfn-model'
require 'cfn-nag/custom_rules/ManagedBlockchainMemberMemberFabricConfigurationAdminPasswordRule'

describe ManagedBlockchainMemberMemberFabricConfigurationAdminPasswordRule, :rule do
context 'ManagedBlockchain Member MemberFabricConfiguration AdminPassword not set' do
it 'returns empty list' do
cfn_model = CfnParser.new.parse read_test_template(
'yaml/managedblockchain_member/' \
'managedblockchain_member_member_fabric_configuration_admin_password_not_set.yaml'
)

actual_logical_resource_ids =
ManagedBlockchainMemberMemberFabricConfigurationAdminPasswordRule.new.audit_impl cfn_model
expected_logical_resource_ids = %w[]

expect(actual_logical_resource_ids).to eq expected_logical_resource_ids
end
end

context 'ManagedBlockchain Member MemberFabricConfiguration AdminPassword parameter with NoEcho' do
it 'returns empty list' do
cfn_model = CfnParser.new.parse read_test_template(
'yaml/managedblockchain_member/' \
'managedblockchain_member_member_fabric_configuration_admin_password_parameter_with_noecho.yaml'
)

actual_logical_resource_ids =
ManagedBlockchainMemberMemberFabricConfigurationAdminPasswordRule.new.audit_impl cfn_model
expected_logical_resource_ids = %w[]

expect(actual_logical_resource_ids).to eq expected_logical_resource_ids
end
end

context 'ManagedBlockchain Member MemberFabricConfiguration AdminPassword parameter with NoEcho and Default value' do
it 'returns offending logical resource id' do
cfn_model = CfnParser.new.parse read_test_template(
'yaml/managedblockchain_member/' \
'managedblockchain_member_member_fabric_configuration_admin_password_parameter_with_noecho_and_default_value.yaml'
)

actual_logical_resource_ids =
ManagedBlockchainMemberMemberFabricConfigurationAdminPasswordRule.new.audit_impl cfn_model
expected_logical_resource_ids = %w[ManagedBlockchainMember]

expect(actual_logical_resource_ids).to eq expected_logical_resource_ids
end
end

context 'ManagedBlockchain Member MemberFabricConfiguration AdminPassword parameter as a literal in plaintext' do
it 'returns offending logical resource id' do
cfn_model = CfnParser.new.parse read_test_template(
'yaml/managedblockchain_member/' \
'managedblockchain_member_member_fabric_configuration_admin_password_parameter_as_a_literal_in_plaintext.yaml'
)

actual_logical_resource_ids =
ManagedBlockchainMemberMemberFabricConfigurationAdminPasswordRule.new.audit_impl cfn_model
expected_logical_resource_ids = %w[ManagedBlockchainMember]

expect(actual_logical_resource_ids).to eq expected_logical_resource_ids
end
end

context 'ManagedBlockchain Member MemberFabricConfiguration AdminPassword as a literal in plaintext' do
it 'returns offending logical resource id' do
cfn_model = CfnParser.new.parse read_test_template(
'yaml/managedblockchain_member/' \
'managedblockchain_member_member_fabric_configuration_admin_password_as_a_literal_in_plaintext.yaml'
)

actual_logical_resource_ids =
ManagedBlockchainMemberMemberFabricConfigurationAdminPasswordRule.new.audit_impl cfn_model
expected_logical_resource_ids = %w[ManagedBlockchainMember]

expect(actual_logical_resource_ids).to eq expected_logical_resource_ids
end
end

context 'ManagedBlockchain Member MemberFabricConfiguration AdminPassword from Secrets Manager' do
it 'returns empty list' do
cfn_model = CfnParser.new.parse read_test_template(
'yaml/managedblockchain_member/' \
'managedblockchain_member_member_fabric_configuration_admin_password_from_secrets_manager.yaml'
)

actual_logical_resource_ids =
ManagedBlockchainMemberMemberFabricConfigurationAdminPasswordRule.new.audit_impl cfn_model
expected_logical_resource_ids = %w[]

expect(actual_logical_resource_ids).to eq expected_logical_resource_ids
end
end

context 'ManagedBlockchain Member MemberFabricConfiguration AdminPassword from Secure Systems Manager' do
it 'returns empty list' do
cfn_model = CfnParser.new.parse read_test_template(
'yaml/managedblockchain_member/' \
'managedblockchain_member_member_fabric_configuration_admin_password_from_secure_systems_manager.yaml'
)

actual_logical_resource_ids =
ManagedBlockchainMemberMemberFabricConfigurationAdminPasswordRule.new.audit_impl cfn_model
expected_logical_resource_ids = %w[]

expect(actual_logical_resource_ids).to eq expected_logical_resource_ids
end
end

context 'ManagedBlockchain Member MemberFabricConfiguration AdminPassword from Systems Manager' do
it 'returns offending logical resource id' do
cfn_model = CfnParser.new.parse read_test_template(
'yaml/managedblockchain_member/' \
'managedblockchain_member_member_fabric_configuration_admin_password_from_systems_manager.yaml'
)

actual_logical_resource_ids =
ManagedBlockchainMemberMemberFabricConfigurationAdminPasswordRule.new.audit_impl cfn_model
expected_logical_resource_ids = %w[ManagedBlockchainMember]

expect(actual_logical_resource_ids).to eq expected_logical_resource_ids
end
end
end
Loading

0 comments on commit c1868bd

Please sign in to comment.