Skip to content

Commit

Permalink
Merge pull request #803 from inspec/AWS_WAF_ByteMatchSet
Browse files Browse the repository at this point in the history
nirbhay/aws_waf_byte_match_set
  • Loading branch information
soumyo13 committed Dec 27, 2021
2 parents 09789e6 + 15ef60b commit 9a156f7
Show file tree
Hide file tree
Showing 8 changed files with 382 additions and 0 deletions.
90 changes: 90 additions & 0 deletions docs/resources/aws_waf_byte_match_set.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
---
title: About the aws_waf_byte_match_set resource
platform: aws
---

# aws_waf_byte_match_set

Use the `aws_waf_byte_match_set` Chef InSpec audit resource to test the properties of a single AWS (Web Application Firewall) WAF byte match set.

## Syntax

Ensure that a byte match set exists.

describe aws_waf_byte_match_set(byte_match_set_id: 'BYTE_MATCH_SET_ID') do
it { should exist }
end

## Parameters

`aws_waf_byte_match_set` _(required)_

The unique identifier for the byte match set.

For additional information, see the [AWS documentation on the `AWS::WAF::ByteMatchSet` resource type](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-waf-bytematchset.html).

## Properties

| Property | Description |
| --- | --- |
| byte_match_set_id | The unique identifier for the byte match set. |
| name | The name of the byte match set. |
| byte_match_tuples | Specifies the bytes (typically a string that corresponds with ASCII characters) that you want AWS WAF to search for in web requests, the location in requests that you want AWS WAF to search, and other settings. |
| byte_match_tuples_field_to_matches | The part of a web request that you want AWS WAF to search, such as a specified header or a query string. |
| byte_match_tuples_field_to_match_types | The part of the web request that you want AWS WAF to search for a specified string. |
| byte_match_tuples_field_to_match_data | When the value of Type is HEADER , enter the name of the header that you want AWS WAF to search, for example, User-Agent or Referer. |
| byte_match_tuples_target_strings | The value that you want AWS WAF to search for. |
| byte_match_tuples_text_transformations | Text transformations eliminate some of the unusual formatting that attackers use in web requests in an effort to bypass AWS WAF. |
| byte_match_tuples_positional_constraints | Within the portion of a web request that you want to search (for example, in the query string, if any), specify where you want AWS WAF to search. |

## Examples

### Ensure a byte match set is available.

describe aws_waf_byte_match_set(byte_match_set_id: 'BYTE_MATCH_SET_ID') do
its('byte_match_set_id') { should eq 'BYTE_MATCH_SET_ID' }
end

### Ensure a byte match set name is available.

describe aws_waf_byte_match_set(byte_match_set_id: 'BYTE_MATCH_SET_ID') do
its('name') { should eq 'BYTE_MATCH_SET_NAME' }
end

### Ensure a byte match set type is `REGULAR`.

describe aws_waf_byte_match_set(byte_match_set_id: 'BYTE_MATCH_SET_ID') do
its('byte_match_tuples_positional_constraints') { should include 'REGULAR' }
end

## Matchers

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

The controls will pass if the `get` method returns at least one result.

### exist

Use `should` to test that the entity exists.

describe aws_waf_byte_match_set(byte_match_set_id: 'BYTE_MATCH_SET_ID') do
it { should exist }
end

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

describe aws_waf_byte_match_set(byte_match_set_id: 'BYTE_MATCH_SET_ID') do
it { should_not exist }
end

### be_available

Use `should` to check if the entity is available.

describe aws_waf_byte_match_set(byte_match_set_id: 'BYTE_MATCH_SET_ID') do
it { should be_available }
end

## AWS Permissions

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

# aws_waf_byte_match_sets

Use the `aws_waf_byte_match_sets` Chef InSpec audit resource to test the properties of multiple AWS (Web Application Firewall) WAF byte match sets.

## Syntax

### Ensure that a byte match set exists.

describe aws_waf_byte_match_sets do
it { should exist }
end

## Parameters

This resource does not expect any parameters.

For additional information, see the [AWS documentation on the `AWS::WAF::ByteMatchSet` resource type](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-waf-bytematchset.html).

## Properties

| Property | Description | Fields |
| --- | --- | --- |
| byte_match_set_ids | The unique identifier for the ByteMatchSet. | byte_match_set_id |
| names | The name of the ByteMatchSet. | name |

## Examples

### Ensure a byte match set is available.

describe aws_waf_byte_match_sets do
its('byte_match_set_ids') { should include 'BYTE_MATCH_SET_ID' }
end

### Ensure a byte match set name is available.

describe aws_waf_byte_match_sets do
its('names') { should include 'BYTE_MATCH_SET_NAME' }
end

## Matchers

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

The controls will pass if the `list` method returns at least one result.

### exist

Use `should` to test that the entity exists.

describe aws_waf_byte_match_sets do
it { should exist }
end

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

describe aws_waf_byte_match_sets 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 `WAF:Client:ListByteMatchSetsResponse` action with `Effect` set to `Allow`.
64 changes: 64 additions & 0 deletions libraries/aws_waf_byte_match_set.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# frozen_string_literal: true

require 'aws_backend'

class AWSWAFByteMatchSet < AwsResourceBase
name 'aws_waf_byte_match_set'
desc 'Describes one WAF byte set.'

example "
describe aws_waf_byte_match_set(byte_match_set_id: 'BYTE_MATCH_SET_ID') do
it { should exits }
end
"

def initialize(opts = {})
opts = { byte_match_set_id: opts } if opts.is_a?(String)
super(opts)
validate_parameters(required: %i(byte_match_set_id))
raise ArgumentError, "#{@__resource_name__}: byte_match_set_id must be provided" unless opts[:byte_match_set_id] && !opts[:byte_match_set_id].empty?
@display_name = opts[:byte_match_set_id]
catch_aws_errors do
resp = @aws.waf_client.get_byte_match_set({ byte_match_set_id: opts[:byte_match_set_id] })
@resp = resp.byte_match_set.to_h
create_resource_methods(@resp)
end
end

def byte_match_set_id
return nil unless exists?
@resp[:byte_match_set_id]
end

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

def to_s
"Byte Match Set ID: #{@display_name}"
end

def byte_match_tuples_field_to_matches
byte_match_tuples.map(&:field_to_match)
end

def byte_match_tuples_field_to_match_types
(byte_match_tuples.map(&:field_to_match)).map(&:type)
end

def byte_match_tuples_field_to_match_data
(byte_match_tuples.map(&:field_to_match)).map(&:data)
end

def byte_match_tuples_target_strings
byte_match_tuples.map(&:target_string)
end

def byte_match_tuples_text_transformations
byte_match_tuples.map(&:text_transformation)
end

def byte_match_tuples_positional_constraints
byte_match_tuples.map(&:positional_constraint)
end
end
39 changes: 39 additions & 0 deletions libraries/aws_waf_byte_match_sets.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# frozen_string_literal: true

require 'aws_backend'

class AWSWAFByteMatchSets < AwsResourceBase
name 'aws_waf_byte_match_sets'
desc 'Verifies settings for all the WAF rules.'

example "
describe aws_waf_byte_match_sets do
it { should exist }
end
"

attr_reader :table

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

FilterTable.create
.register_column(:byte_match_set_ids, field: :byte_match_set_id, style: :simple)
.register_column(:names, field: :name, style: :simple)
.install_filter_methods_on_resource(self, :table)

def fetch_data
catch_aws_errors do
@resp = @aws.waf_client.list_byte_match_sets.map do |table|
table.map { |table_name| {
byte_match_set_id: table_name.byte_match_sets.map(&:byte_match_set_id),
name: table_name.byte_match_sets.map(&:name),
}
}
end.flatten
end
end
end
24 changes: 24 additions & 0 deletions test/integration/verify/controls/aws_waf_byte_match_set.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
aws_waf_byte_match_set_id = attribute(aws_waf_byte_match_set_id, value: '', description: '')
aws_waf_byte_match_set_name = attribute(aws_waf_byte_match_set_name, value: '', description: '')

title 'Ensure the byte match set have the correct properties.'

control 'aws-waf-byte-match-set-1.0' do
impact 1.0

describe aws_waf_byte_match_set(byte_match_set_id: aws_waf_byte_match_set_id) do
it { should exist }
end

describe aws_waf_byte_match_set(byte_match_set_id: aws_waf_byte_match_set_id) do
its('byte_match_set_id') { should eq aws_waf_byte_match_set_id }
its('name') { should eq aws_waf_byte_match_set_name }

its('byte_match_tuples_field_to_matches') { should_not be_empty }
its('byte_match_tuples_field_to_match_types') { should include 'HEADER' }
its('byte_match_tuples_field_to_match_data') { should include 'referer' }
its('byte_match_tuples_target_strings') { should include 'badrefer1' }
its('byte_match_tuples_text_transformations') { should include 'NONE' }
its('byte_match_tuples_positional_constraints') { should include 'CONTAINS' }
end
end
18 changes: 18 additions & 0 deletions test/integration/verify/controls/aws_waf_byte_match_sets.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
aws_waf_byte_match_set_id = attribute(aws_waf_byte_match_set_id, value: '', description: '')
aws_waf_byte_match_set_name = attribute(aws_waf_byte_match_set_name, value: '', description: '')

title 'Ensure the byte match sets have the correct properties.'

control 'aws-waf-byte-match-sets-1.0' do
impact 1.0

describe aws_waf_byte_match_sets do
it { should exist }
end

describe aws_waf_byte_match_sets do
its('byte_match_set_ids') { should include aws_waf_byte_match_set_id }
its('names') { should include aws_waf_byte_match_set_name }
end
end

45 changes: 45 additions & 0 deletions test/unit/resources/aws_waf_byte_match_set_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
require 'helper'
require 'aws_waf_byte_match_set'
require 'aws-sdk-core'

class AWSWAFByteMatchSetConstructorTest < Minitest::Test

def test_empty_params_not_ok
assert_raises(ArgumentError) { AWSWAFByteMatchSet.new(client_args: { stub_responses: true }) }
end

def test_empty_param_arg_not_ok
assert_raises(ArgumentError) { AWSWAFByteMatchSet.new('', client_args: { stub_responses: true }) }
end

def test_rejects_unrecognized_params
assert_raises(ArgumentError) { AWSWAFByteMatchSet.new(unexpected: 9) }
end
end

class AWSWAFByteMatchSetHappyPathTest < Minitest::Test

def setup
data = {}
data[:method] = :get_byte_match_set
mock_data = {}
mock_data[:byte_match_set_id] = 'test1'
mock_data[:name] = 'test1'
mock_data[:byte_match_tuples] = [{ target_string: "test1", field_to_match: { type: 'test1', data: 'test1'}, text_transformation: 'test1', positional_constraint: 'test1' }]
data[:data] = { byte_match_set: mock_data }
data[:client] = Aws::WAF::Client
@resp = AWSWAFByteMatchSet.new(byte_match_set_id: 'test1', client_args: { stub_responses: true }, stub_data: [data])
end

def test_byte_match_set_exists
assert @resp.exist?
end

def byte_match_set_id
assert_equal(@resp.byte_match_set_id, 'test1')
end

def test_byte_match_set_name
assert_equal(@resp.name, 'test1')
end
end
35 changes: 35 additions & 0 deletions test/unit/resources/aws_waf_byte_match_sets_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
require 'helper'
require 'aws_waf_byte_match_sets'
require 'aws-sdk-core'

class AWSWAFByteMatchSetsConstructorTest < Minitest::Test

def test_empty_params_ok
AWSWAFByteMatchSets.new(client_args: { stub_responses: true })
end

def test_rejects_other_args
assert_raises(ArgumentError) { AWSWAFByteMatchSets.new(test: 'dummy') }
end
end

class AWSWAFByteMatchSetsHappyPathTest < Minitest::Test

def setup
data = {}
data[:method] = :list_byte_match_sets
mock_data = {}
mock_data[:byte_match_sets] = [{ byte_match_set_id: 'byte_match_set_id', name: 'name' }]
data[:data] = mock_data
data[:client] = Aws::WAF::Client
@resp = AWSWAFByteMatchSets.new(client_args: { stub_responses: true }, stub_data: [data])
end

def test_byte_match_set_exists
assert @resp.exist?
end

def test_byte_match_set_ids
assert_equal(@resp.byte_match_set_ids, ['byte_match_set_id'])
end
end

0 comments on commit 9a156f7

Please sign in to comment.