Skip to content

Commit

Permalink
feat(bom): bill of materials for aws dynamodb (#5861)
Browse files Browse the repository at this point in the history
* add bom dynamo

* update dynamo db BoM

* update BoM docs

* update
  • Loading branch information
cxMiguelSilva authored Oct 10, 2022
1 parent e18e776 commit 9562b39
Show file tree
Hide file tree
Showing 17 changed files with 819 additions and 8 deletions.
12 changes: 12 additions & 0 deletions assets/queries/cloudFormation/aws_bom/dynamo/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"id": "4e67c0ae-38a0-47f4-a50c-f0c9b75826df",
"queryName": "BOM - AWS DynamoDB",
"severity": "TRACE",
"category": "Bill Of Materials",
"descriptionText": "A list of DynamoDB resources found. Amazon DynamoDB is a fully managed, serverless, key-value NoSQL database designed to run high-performance applications at any scale.",
"descriptionUrl": "https://kics.io",
"platform": "CloudFormation",
"descriptionID": "b0d40495",
"cloudProvider": "aws"
}

171 changes: 171 additions & 0 deletions assets/queries/cloudFormation/aws_bom/dynamo/query.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
package Cx

import data.generic.cloudformation as cf_lib
import data.generic.common as common_lib

CxPolicy[result] {
document := input.document
resource := document[i].Resources[name]
resource.Type == "AWS::DynamoDB::Table"

info := get_accessibility(resource)

bom_output = {
"resource_type": "AWS::DynamoDB::Table",
"resource_name": cf_lib.get_resource_name(resource, name),
"resource_accessibility": lower(info.accessibility),
"resource_encryption": get_encryption(resource),
"resource_vendor": "AWS",
"resource_category": "Storage",
}

final_bom_output := common_lib.get_bom_output(bom_output, info.policy)

result := {
"documentId": input.document[i].id,
"searchKey": sprintf("Resources.%s", [name]),
"issueType": "BillOfMaterials",
"keyExpectedValue": "",
"keyActualValue": "",
"searchLine": common_lib.build_search_line(["Resources", name], []),
"value": json.marshal(final_bom_output),
}
}

get_accessibility(resource) = info{
info:= check_vpc_endpoint(resource)
} else = info {
info := {"accessibility":"private", "policy": ""}
}

check_vpc_endpoint(resource) = info{
values := [x |
vpc_endpoint := input.document[_].Resources[_]
vpc_endpoint.Type == "AWS::EC2::VPCEndpoint"
policy_doc := vpc_endpoint.Properties.PolicyDocument
x := policy_accessibility(policy_doc, resource.Properties.TableName)]

info := get_info(values)
}

policy_accessibility(policy, table_name) = info {
st := common_lib.get_statement(policy)
statement := st[_]

common_lib.is_allow_effect(statement)
common_lib.any_principal(statement.Principal)
check_actions(statement.Action)

resources_arn := get_resource_arn(statement.Resource)
has_all_or_dynamob_arn(resources_arn, table_name)

info := {"accessibility":"public", "policy": policy}
} else = info {
common_lib.get_statement(policy)
info := {"accessibility":"private", "policy": policy}
} else = info {
info := {"accessibility":"hasPolicy", "policy": policy}
}

get_resource_arn(resources) = val {
is_array(resources)
val := resources[_]
} else = val {
val := resources
}

has_all_or_dynamob_arn(arn, table_name){
arn == "*"
} else {
startswith(arn, "arn:aws:dynamodb:")
suffix := concat( "", [":table/", table_name])
endswith(arn, suffix)
}

get_encryption(resource) = encryption{
sse := resource.Properties.SSESpecification
sse.SSEEnabled == true
encryption := "encrypted"
} else = encryption{
encryption := "unencrypted"
}

dynamo_actions := {
"dynamodb:DescribeContributorInsights",
"dynamodb:RestoreTableToPointInTime",
"dynamodb:UpdateGlobalTable",
"dynamodb:DeleteTable",
"dynamodb:UpdateTableReplicaAutoScaling",
"dynamodb:DescribeTable",
"dynamodb:PartiQLInsert",
"dynamodb:GetItem",
"dynamodb:DescribeContinuousBackups",
"dynamodb:DescribeExport",
"dynamodb:ListImports",
"dynamodb:EnableKinesisStreamingDestination",
"dynamodb:BatchGetItem",
"dynamodb:DisableKinesisStreamingDestination",
"dynamodb:UpdateTimeToLive",
"dynamodb:BatchWriteItem",
"dynamodb:PutItem",
"dynamodb:PartiQLUpdate",
"dynamodb:Scan",
"dynamodb:StartAwsBackupJob",
"dynamodb:UpdateItem",
"dynamodb:UpdateGlobalTableSettings",
"dynamodb:CreateTable",
"dynamodb:RestoreTableFromAwsBackup",
"dynamodb:GetShardIterator",
"dynamodb:DescribeReservedCapacity",
"dynamodb:ExportTableToPointInTime",
"dynamodb:DescribeBackup",
"dynamodb:UpdateTable",
"dynamodb:GetRecords",
"dynamodb:DescribeTableReplicaAutoScaling",
"dynamodb:DescribeImport",
"dynamodb:ListTables",
"dynamodb:DeleteItem",
"dynamodb:PurchaseReservedCapacityOfferings",
"dynamodb:CreateTableReplica",
"dynamodb:ListTagsOfResource",
"dynamodb:UpdateContributorInsights",
"dynamodb:CreateBackup",
"dynamodb:UpdateContinuousBackups",
"dynamodb:DescribeReservedCapacityOfferings",
"dynamodb:TagResource",
"dynamodb:PartiQLSelect",
"dynamodb:CreateGlobalTable",
"dynamodb:DescribeKinesisStreamingDestination",
"dynamodb:DescribeLimits",
"dynamodb:ImportTable",
"dynamodb:ListExports",
"dynamodb:UntagResource",
"dynamodb:ConditionCheckItem",
"dynamodb:ListBackups",
"dynamodb:Query",
"dynamodb:DescribeStream",
"dynamodb:DeleteTableReplica",
"dynamodb:DescribeTimeToLive",
"dynamodb:ListStreams",
"dynamodb:ListContributorInsights",
"dynamodb:DescribeGlobalTableSettings",
"dynamodb:ListGlobalTables",
"dynamodb:DescribeGlobalTable",
"dynamodb:RestoreTableFromBackup",
"dynamodb:DeleteBackup",
"dynamodb:PartiQLDelete",
"dynamodb:*"
}

check_actions(actions) {
common_lib.equalsOrInArray(actions, dynamo_actions[_])
} else {
common_lib.equalsOrInArray(actions, "*")
}

get_info(info_arr)= info{
val := [ x | info_arr[x].accessibility == "public" ]
info := info_arr[val[0]]
} else = info{
info := info_arr[0]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
AWSTemplateFormatVersion: '2010-09-09'
Resources:
myDistribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
Enabled: true
40 changes: 40 additions & 0 deletions assets/queries/cloudFormation/aws_bom/dynamo/test/positive1.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
AWSTemplateFormatVersion: '2010-09-09'
Resources:
DynamoDBEndpoint:
Type: "AWS::EC2::VPCEndpoint"
Properties:
RouteTableIds:
- !Ref PublicRouteTable
- !Ref Private0RouteTable
- !Ref Private1RouteTable
- !Ref Private2RouteTable
ServiceName:
!Sub "com.amazonaws.${AWS::Region}.dynamodb"
VpcId: !Ref VPC
PolicyDocument: {
"Id": "Policy",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Statement",
"Action": "dynamodb:*",
"Effect": "Allow",
"Resource": "arn:aws:dynamodb:ap-southeast-2:123412341234:table/test",
"Principal": "*"
}
]
}
DynamoDBOnDemandTable2:
Type: "AWS::DynamoDB::Table"
Properties:
TableName: test
AttributeDefinitions:
- AttributeName: pk
AttributeType: S
KeySchema:
- AttributeName: pk
KeyType: HASH
BillingMode: PAY_PER_REQUEST
SSESpecification:
SSEEnabled: false
SSEType: "KMS"
40 changes: 40 additions & 0 deletions assets/queries/cloudFormation/aws_bom/dynamo/test/positive2.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
AWSTemplateFormatVersion: '2010-09-09'
Resources:
DynamoDBEndpoint:
Type: "AWS::EC2::VPCEndpoint"
Properties:
RouteTableIds:
- !Ref PublicRouteTable
- !Ref Private0RouteTable
- !Ref Private1RouteTable
- !Ref Private2RouteTable
ServiceName:
!Sub "com.amazonaws.${AWS::Region}.dynamodb"
VpcId: !Ref VPC
PolicyDocument: {
"Id": "Policy",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Statement",
"Action": "dynamodb:*",
"Effect": "Allow",
"Resource": "*",
"Principal": "*"
}
]
}
DynamoDBOnDemandTable2:
Type: "AWS::DynamoDB::Table"
Properties:
TableName: test2
AttributeDefinitions:
- AttributeName: pk
AttributeType: S
KeySchema:
- AttributeName: pk
KeyType: HASH
BillingMode: PAY_PER_REQUEST
SSESpecification:
SSEEnabled: false
SSEType: "KMS"
40 changes: 40 additions & 0 deletions assets/queries/cloudFormation/aws_bom/dynamo/test/positive3.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
AWSTemplateFormatVersion: '2010-09-09'
Resources:
DynamoDBEndpoint:
Type: "AWS::EC2::VPCEndpoint"
Properties:
RouteTableIds:
- !Ref PublicRouteTable
- !Ref Private0RouteTable
- !Ref Private1RouteTable
- !Ref Private2RouteTable
ServiceName:
!Sub "com.amazonaws.${AWS::Region}.dynamodb"
VpcId: !Ref VPC
PolicyDocument: {
"Id": "Policy",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Statement",
"Action": "dynamodb:*",
"Effect": "Allow",
"Resource": "arn:aws:dynamodb:ap-southeast-2:123412341234:table/other",
"Principal": "*"
}
]
}
DynamoDBOnDemandTable2:
Type: "AWS::DynamoDB::Table"
Properties:
TableName: test3
AttributeDefinitions:
- AttributeName: pk
AttributeType: S
KeySchema:
- AttributeName: pk
KeyType: HASH
BillingMode: PAY_PER_REQUEST
SSESpecification:
SSEEnabled: false
SSEType: "KMS"
16 changes: 16 additions & 0 deletions assets/queries/cloudFormation/aws_bom/dynamo/test/positive4.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
AWSTemplateFormatVersion: '2010-09-09'
Resources:
DynamoDBOnDemandTable2:
Type: "AWS::DynamoDB::Table"
Properties:
TableName: test4
AttributeDefinitions:
- AttributeName: pk
AttributeType: S
KeySchema:
- AttributeName: pk
KeyType: HASH
BillingMode: PAY_PER_REQUEST
SSESpecification:
SSEEnabled: false
SSEType: "KMS"
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[
{
"queryName": "BOM - AWS DynamoDB",
"severity": "TRACE",
"line": 27,
"fileName": "positive1.yaml"
},
{
"queryName": "BOM - AWS DynamoDB",
"severity": "TRACE",
"line": 27,
"fileName": "positive2.yaml"
},
{
"queryName": "BOM - AWS DynamoDB",
"severity": "TRACE",
"line": 27,
"fileName": "positive3.yaml"
},
{
"queryName": "BOM - AWS DynamoDB",
"severity": "TRACE",
"line": 3,
"fileName": "positive4.yaml"
}
]
11 changes: 11 additions & 0 deletions assets/queries/terraform/aws_bom/dynamo/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"id": "23edf35f-7c22-4ff9-87e6-0ca74261cfbf",
"queryName": "BOM - AWS DynamoDB",
"severity": "TRACE",
"category": "Bill Of Materials",
"descriptionText": "A list of DynamoDB resources found. Amazon DynamoDB is a fully managed, serverless, key-value NoSQL database designed to run high-performance applications at any scale.",
"descriptionUrl": "https://kics.io",
"platform": "Terraform",
"descriptionID": "c9007e7c",
"cloudProvider": "aws"
}
Loading

0 comments on commit 9562b39

Please sign in to comment.