Skip to content

Commit 8bf11e1

Browse files
authored
Adding support for new resource types in check-no-public-access api. (#39)
* Adding support for new resource types in check-no-public-access api. * Adding support for new resource types in check-no-public-access api. * Adding support for new resource types in check-no-public-access api. * Adding support for new resource types in check-no-public-access api. * Update the GHH action to publish to PyPi version * Adding support for new resource types in check-no-public-access api. * Adding support for new resource types in check-no-public-access api.
1 parent ca9aebd commit 8bf11e1

File tree

13 files changed

+542
-17
lines changed

13 files changed

+542
-17
lines changed

.github/workflows/release-to-pypi.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121
run: |
2222
python3 -m build
2323
- name: Publish to PyPI
24-
uses: pypa/gh-action-pypi-publish@v1.8.14
24+
uses: pypa/gh-action-pypi-publish@@v1.12.4
2525
with:
2626
user: __token__
2727
password: ${{ secrets.PYPI_API_TOKEN }}

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,11 @@ Resource-based policies that can be checked with `check-no-public-access` are li
148148
- AWS::SecretsManager::Secret
149149
- AWS::SNS::Topic
150150
- AWS::SQS::Queue
151+
- AWS::S3Tables::TableBucket
152+
- AWS::S3Tables::Table
153+
- AWS::Backup::BackupVault
154+
- AWS::CodeArtifact::Domain
155+
- AWS::ApiGateway::RestApi
151156
- Role trust policies (AWS::IAM::AssumeRolePolicyDocument)
152157

153158

iam_check/config/default.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ arnServiceMap:
5353
aws_transfer_access: server_id?fakeServerId
5454
aws_transfer_user: user_name?fakeUserName
5555
aws_vpc_endpoint: fakeName
56+
aws_s3tables_table_bucket_policy: table_bucket_arn?fakeTableBucketARN
57+
aws_s3tables_table_policy: table_bucket_arn?fakeTableBucketARN
58+
aws_kinesis_resource_policy: resource_arn?fakeResourceArn
59+
aws_dynamodb_resource_policy: resource_arn?fakeResourceArn
60+
aws_lambda_permission: function_name?fakeFunctionName
5661
# iamChecks:
5762
# - AccessAnalyzer
5863

@@ -116,6 +121,12 @@ iamPolicyAttributes:
116121
aws_transfer_access: policy
117122
aws_transfer_user: policy
118123
aws_vpc_endpoint: policy
124+
aws_s3tables_table_bucket_policy: resource_policy
125+
aws_s3tables_table_policy: resource_policy
126+
aws_kinesis_resource_policy: policy
127+
aws_dynamodb_resource_policy: policy
128+
aws_lambda_permission: policy
129+
119130

120131
validatePolicyResourceType:
121132
aws_s3_bucket: AWS::S3::Bucket

iam_check/lib/iamcheck_AccessAnalyzer.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,24 @@
3434
"aws_sqs_queue": "AWS::SQS::Queue",
3535
"aws_sqs_queue_policy": "AWS::SQS::Queue",
3636
"assume_role_policy": "AWS::IAM::AssumeRolePolicyDocument",
37+
"aws_s3tables_table_bucket": "AWS::S3Tables::TableBucket",
38+
"aws_s3tables_table_bucket_policy": "AWS::S3Tables::TableBucket",
39+
"aws_api_gateway_rest_api": "AWS::ApiGateway::RestApi",
40+
"aws_api_gateway_rest_api_policy": "AWS::ApiGateway::RestApi",
41+
"aws_codeartifact_domain": "AWS::CodeArtifact::Domain",
42+
"aws_codeartifact_domain_permissions_policy": "AWS::CodeArtifact::Domain",
43+
"aws_backup_vault": "AWS::Backup::BackupVault",
44+
"aws_backup_vault_policy": "AWS::Backup::BackupVault",
45+
"aws_cloudtrail_event_data_store": "AWS::CloudTrail::EventDataStore",
46+
"aws_s3tables_table": "AWS::S3Tables::Table",
47+
"aws_s3tables_table_policy": "AWS::S3Tables::Table",
48+
"aws_lambda_permission": "AWS::Lambda::Function",
49+
"aws_lambda_function": "AWS::Lambda::Function",
50+
"aws_dynamodb_resource_policy": "AWS::DynamoDB::Table",
51+
"aws_dynamodb_table": "AWS::DynamoDB::Table",
52+
"aws_kinesis_resource_policy": "AWS::Kinesis::Stream",
53+
"aws_kinesis_stream": "AWS::Kinesis::Stream",
54+
"aws_kinesis_stream_consumer": "AWS::Kinesis::StreamConsumer",
3755
}
3856

3957

iam_check/lib/tfPlan.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# from ..config import iamPolicyAttributes, arnServiceMap, awsAccount
2+
from collections import defaultdict
23
import iam_check.config as config
34
import enum
45
import logging
@@ -81,10 +82,66 @@ def __str__(self) -> str:
8182
obj["proposed_unknown"] = json.loads(str(self.proposed_unknown))
8283
return json.dumps(obj, indent=4)
8384

85+
def generatePolicyForLambda(self, resource, permissions_policies):
86+
action = self.getValue(f"{resource}.action")
87+
function_name = self.getValue(f"{resource}.function_name")
88+
principal = self.getValue(f"{resource}.principal")
89+
source_arn = None
90+
source_account = None
91+
principal_org_id = None
92+
try:
93+
source_arn = self.getValue(f"{resource}.source_arn")
94+
except KeyError:
95+
pass
96+
try:
97+
source_account = self.getValue(f"{resource}.source_account")
98+
except KeyError:
99+
pass
100+
try:
101+
principal_org_id = self.getValue(f"{resource}.principal_org_id")
102+
except KeyError:
103+
pass
104+
105+
policy_statement = {"Effect": "Allow", "Action": action}
106+
if "amazonaws" in principal:
107+
# this is a permission to a service
108+
policy_statement["Principal"] = {"Service": principal}
109+
else:
110+
# otherwise this is a permission to an account
111+
policy_statement["Principal"] = {"AWS": principal}
112+
113+
# just the function name
114+
policy_statement["Resource"] = f"arn::lambda:::function:{function_name}"
115+
# Ref to the supported arguments
116+
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_permission
117+
118+
if source_arn is not None:
119+
condition = policy_statement.get("Condition", {})
120+
condition["ArnLike"] = {"AWS:SourceArn": source_arn}
121+
policy_statement["Condition"] = condition
122+
123+
if source_account is not None:
124+
condition = policy_statement.get("Condition", {})
125+
condition["StringEquals"] = {"AWS:SourceAccount": source_account}
126+
policy_statement["Condition"] = condition
127+
128+
if principal_org_id is not None:
129+
condition = policy_statement.get("Condition", {})
130+
if "StringEquals" not in condition:
131+
condition["StringEquals"] = {}
132+
condition["StringEquals"]["AWS:PrincipalOrgID"] = principal_org_id
133+
policy_statement["Condition"] = condition
134+
135+
permissions_policies[f"{resource}.policy"].append(policy_statement)
136+
return permissions_policies
137+
84138
def findPolicies(self):
85139
logging.debug("generating a list of policies in plan")
86140
policies = {}
87141
resources = self.listResources()
142+
# used to collect all policy statements related to a resource. Currently, only applicable to aws_lambda_permission
143+
# where each aws_lambda_permission is mapped to a statement.
144+
permissions_policies = defaultdict(list)
88145
for r in resources:
89146
resourceType = r.split(".")[-2]
90147
if resourceType not in config.iamPolicyAttributes:
@@ -93,6 +150,11 @@ def findPolicies(self):
93150
attributes = config.iamPolicyAttributes[resourceType]
94151
if isinstance(attributes, str):
95152
attributes = [attributes]
153+
if resourceType == "aws_lambda_permission":
154+
permissions_policies = self.generatePolicyForLambda(
155+
r, permissions_policies
156+
)
157+
continue
96158
for attribute in attributes:
97159
# check if attribute is a base one or inside a block
98160
if "." not in attribute:
@@ -134,6 +196,10 @@ def findPolicies(self):
134196
policies[ref] = policy
135197
else:
136198
LOGGER.info(f"No policy found at: {ref}")
199+
for key, statements in permissions_policies.items():
200+
policy_document = {"Version": "2012-10-17", "Statement": statements}
201+
policies[key] = json.dumps(policy_document)
202+
137203
for ref in policies.keys():
138204
LOGGER.debug(f"found policy at {ref}")
139205

iam_check/test/no_access_granted/actions_findings.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33
{
44
"findingType": "SECURITY_WARNING",
55
"code": "policy-analysis-CheckAccessNotGranted",
6-
"message": "The policy document grants access to perform one or more of the listed actions or resources.",
6+
"message": "The policy document grants access to perform one or more of the listed actions.",
77
"resourceName": "fakeBucket",
88
"policyName": "aws_s3_bucket_policy.allow_access_from_another_account",
99
"details": {
1010
"result": "FAIL",
1111
"reasons": [
1212
{
13-
"description": "One or more of the listed actions or resources in the statement with index: 0.",
13+
"description": "One or more of the listed actions in the statement with index: 0.",
1414
"statementIndex": 0,
1515
"accessInput": [
1616
{
@@ -21,7 +21,7 @@
2121
]
2222
}
2323
],
24-
"message": "The policy document grants access to perform one or more of the listed actions or resources."
24+
"message": "The policy document grants access to perform one or more of the listed actions."
2525
}
2626
}
2727
],

iam_check/test/no_access_granted/resources_and_actions_findings.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33
{
44
"findingType": "SECURITY_WARNING",
55
"code": "policy-analysis-CheckAccessNotGranted",
6-
"message": "The policy document grants access to perform one or more of the listed actions or resources.",
6+
"message": "The policy document grants access to one or more listed resources to perform one or more listed actions.",
77
"resourceName": "fakeBucket",
88
"policyName": "aws_s3_bucket_policy.allow_access_from_another_account",
99
"details": {
1010
"result": "FAIL",
1111
"reasons": [
1212
{
13-
"description": "One or more of the listed actions or resources in the statement with index: 0.",
13+
"description": "One or more of the listed actions and/or resources in the statement with index: 0.",
1414
"statementIndex": 0,
1515
"accessInput": [
1616
{
@@ -24,7 +24,7 @@
2424
]
2525
}
2626
],
27-
"message": "The policy document grants access to perform one or more of the listed actions or resources."
27+
"message": "The policy document grants access to one or more listed resources to perform one or more listed actions."
2828
}
2929
}
3030
],

iam_check/test/no_access_granted/resources_findings.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33
{
44
"findingType": "SECURITY_WARNING",
55
"code": "policy-analysis-CheckAccessNotGranted",
6-
"message": "The policy document grants access to perform one or more of the listed actions or resources.",
6+
"message": "The policy document grants access to one or more of the listed resources.",
77
"resourceName": "fakeBucket",
88
"policyName": "aws_s3_bucket_policy.allow_access_from_another_account",
99
"details": {
1010
"result": "FAIL",
1111
"reasons": [
1212
{
13-
"description": "One or more of the listed actions or resources in the statement with index: 0.",
13+
"description": "One or more of the listed resources in the statement with index: 0.",
1414
"statementIndex": 0,
1515
"accessInput": [
1616
{
@@ -21,7 +21,7 @@
2121
]
2222
}
2323
],
24-
"message": "The policy document grants access to perform one or more of the listed actions or resources."
24+
"message": "The policy document grants access to one or more of the listed resources."
2525
}
2626
}
2727
],

0 commit comments

Comments
 (0)