Skip to content

Commit eea3229

Browse files
author
Taniya Mathur
committed
add comprehensive service role permissions validation script
1 parent 03dbb20 commit eea3229

File tree

2 files changed

+108
-0
lines changed

2 files changed

+108
-0
lines changed

.gitlab-ci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ deployment_validation:
112112

113113
script:
114114
# Check if service role has sufficient permissions for main stack deployment
115+
- python3 scripts/validate_service_role_permissions.py
115116
- |
116117
python3 -c "
117118
import yaml
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Validate CloudFormation service role has sufficient permissions for IDP deployment
4+
"""
5+
6+
import yaml
7+
import sys
8+
import os
9+
10+
# Custom YAML loader that ignores CloudFormation intrinsic functions
11+
class CFNLoader(yaml.SafeLoader):
12+
pass
13+
14+
def cfn_constructor(loader, tag_suffix, node):
15+
return None # Ignore CloudFormation functions
16+
17+
# Register constructors for CloudFormation intrinsic functions
18+
CFNLoader.add_multi_constructor('!', cfn_constructor)
19+
20+
def extract_aws_services_from_template(template_path):
21+
"""Extract AWS services used in a CloudFormation template"""
22+
try:
23+
with open(template_path, 'r') as f:
24+
template = yaml.load(f, Loader=CFNLoader)
25+
26+
services = set()
27+
if template and 'Resources' in template:
28+
for resource in template['Resources'].values():
29+
if resource and 'Type' in resource:
30+
resource_type = resource['Type']
31+
if resource_type and resource_type.startswith('AWS::'):
32+
service = resource_type.split('::')[1].lower()
33+
services.add(service)
34+
return services
35+
except Exception as e:
36+
print(f'Error parsing {template_path}: {e}')
37+
return set()
38+
39+
def extract_permissions_from_role(role_template_path):
40+
"""Extract permissions from CloudFormation service role template"""
41+
try:
42+
with open(role_template_path, 'r') as f:
43+
role_template = yaml.load(f, Loader=CFNLoader)
44+
45+
permissions = set()
46+
if role_template and 'Resources' in role_template:
47+
for resource in role_template['Resources'].values():
48+
if resource and resource.get('Type') == 'AWS::IAM::Role':
49+
policies = resource.get('Properties', {}).get('Policies', [])
50+
for policy in policies:
51+
statements = policy.get('PolicyDocument', {}).get('Statement', [])
52+
for statement in statements:
53+
actions = statement.get('Action', [])
54+
if isinstance(actions, str):
55+
actions = [actions]
56+
for action in actions:
57+
if '*' in action:
58+
service = action.split(':')[0]
59+
permissions.add(f'{service}:*')
60+
else:
61+
permissions.add(action)
62+
return permissions
63+
except Exception as e:
64+
print(f'Error parsing role template: {e}')
65+
return set()
66+
67+
def main():
68+
# Templates to check
69+
templates = [
70+
'template.yaml', # Main template
71+
'patterns/pattern-1/template.yaml',
72+
'patterns/pattern-2/template.yaml',
73+
'patterns/pattern-3/template.yaml',
74+
'options/bda-lending-project/template.yaml',
75+
'options/bedrockkb/template.yaml'
76+
]
77+
78+
all_services = set()
79+
80+
# Extract services from all templates
81+
for template_path in templates:
82+
if os.path.exists(template_path):
83+
services = extract_aws_services_from_template(template_path)
84+
all_services.update(services)
85+
print(f'{template_path}: {sorted(services)}')
86+
else:
87+
print(f'⚠️ Template not found: {template_path}')
88+
89+
print(f'\nAll templates use services: {sorted(all_services)}')
90+
91+
# Extract permissions from service role
92+
role_permissions = extract_permissions_from_role('iam-roles/cloudformation-management/IDP-Cloudformation-Service-Role.yaml')
93+
print(f'Service role has {len(role_permissions)} permissions')
94+
95+
# Basic validation - check if role has broad permissions
96+
has_broad_permissions = any('*' in perm for perm in role_permissions)
97+
print(f'Service role has broad permissions: {has_broad_permissions}')
98+
99+
if has_broad_permissions:
100+
print('✅ Service role appears to have sufficient permissions for deployment')
101+
return 0
102+
else:
103+
print('⚠️ Service role may need additional permissions')
104+
return 0 # Don't fail the pipeline, just warn
105+
106+
if __name__ == '__main__':
107+
sys.exit(main())

0 commit comments

Comments
 (0)