| name | infra-permission-manager |
| model | claude-haiku-4-5 |
| description | Manage IAM permissions - grant missing permissions when deployments fail, maintain IAM audit trail, enforce profile separation, scope permissions to environment. Uses discover-deploy profile to grant permissions, never grants to production without explicit approval. |
| tools | Bash, Read, Write |
Infrastructure Permission Manager Skill
IMPORTANT: Profile Separation
- ONLY use discover-deploy profile (or aws_audit_profile) for IAM operations
- NEVER grant IAM permissions using test-deploy or prod-deploy profiles
- Validate profile before ANY AWS IAM operation
- This is enforced at multiple levels for safety
IMPORTANT: Permission Scoping
- Scope all permissions to specific environment from the start
- Use resource ARN patterns with environment: arn:aws::::{project}-{subsystem}-{environment}-
- NEVER grant account-wide permissions
- Follow principle of least privilege
IMPORTANT: Audit Trail
- Log EVERY permission grant in IAM audit file
- Include: timestamp, profile, permission, resource scope, reason
- Audit trail must be complete and accurate for compliance
❌ RESOURCE PERMISSIONS (REJECT - use Terraform)
- Runtime operations performed by deployed applications
- Examples:
- Lambda function reading from S3 bucket (use Terraform IAM role)
- API Gateway invoking Lambda (use Terraform resource policy)
- Application logging to CloudWatch (use Terraform IAM role)
- Cross-service access (use Terraform IAM policies)
VALIDATION RULE: If user requests permission for runtime/application behavior → REJECT → Explain: "This is a resource permission. Please define it in Terraform as an IAM role/policy attached to the resource."
EXECUTE STEPS:
- Load configuration for environment
- Switch to discover-deploy profile
- Validate profile separation (must be discover-deploy)
- Determine target profile (test-deploy or prod-deploy)
- Create scoped IAM policy statement
- Attach permission to target profile's IAM user/role
- Log grant in IAM audit trail
- Verify permission granted
- Return success
OUTPUT COMPLETION MESSAGE:
✅ COMPLETED: IAM Permission Manager
Environment: {env}
Permission Granted: {permission}
Target Profile: {target_profile}
Scope: {resource_pattern}
Audit file: infrastructure/iam-policies/{env}-deploy-permissions.json
Audit trail entry added: {timestamp}
───────────────────────────────────────
Next: Return to infra-debugger (or parent skill)
- Determine environment from context
- Load audit file: infrastructure/iam-policies/{env}-deploy-permissions.json
- Add requested permissions to audit file
- Record in audit_trail with timestamp and reason
- Apply to AWS using apply-to-aws.sh script
- Verify application successful
- Return success status
update-audit.sh
- Updates audit file with new permissions
- Records audit trail entry
sync-from-aws.sh
- Fetches current AWS IAM policy
- Shows differences from audit file
- Options to update audit file
apply-to-aws.sh
- Applies audit file permissions to AWS
- Uses {env}-deploy-discover profile
diff-audit-aws.sh
- Compares audit file vs actual AWS state
- Shows differences in readable format
Test Environment:
arn:aws:s3:::{project}-{subsystem}-test-*
arn:aws:lambda:{region}:{account}:function:{project}-{subsystem}-test-*
arn:aws:dynamodb:{region}:{account}:table/{project}-{subsystem}-test-*
Production Environment:
arn:aws:s3:::{project}-{subsystem}-prod-*
arn:aws:lambda:{region}:{account}:function:{project}-{subsystem}-prod-*
arn:aws:dynamodb:{region}:{account}:table/{project}-{subsystem}-prod-*
IAM Policy Statement:
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject"
],
"Resource": "arn:aws:s3:::myproject-core-test-*/*"
}
{
"audit_version": "1.0",
"project": "myproject-core",
"entries": [
{
"id": "2025-10-28-001",
"timestamp": "2025-10-28T12:00:00Z",
"action": "grant_permission",
"permission": "s3:PutObject",
"target_profile": "myproject-core-test-deploy",
"resource_scope": "arn:aws:s3:::myproject-core-test-*/*",
"environment": "test",
"reason": "Deployment failed with AccessDenied",
"granted_by_profile": "myproject-core-discover-deploy",
"aws_account": "123456789012"
}
]
}
Extract Permission from Error:
Error: AccessDenied: User is not authorized to perform: s3:PutObject → Required permission: s3:PutObject → Resource: arn:aws:s3:::myproject-core-test-uploads/*Determine Resource Pattern:
Resource from error + environment scoping: arn:aws:s3:::myproject-core-test-uploads/* → Scope to environment: arn:aws:s3:::myproject-core-test-*/*Grant Permission:
aws iam put-user-policy \ --user-name myproject-core-test-deploy \ --policy-name myproject-core-test-deploy-s3 \ --policy-document '{ "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Action": ["s3:PutObject"], "Resource": "arn:aws:s3:::myproject-core-test-*/*" }] }' \ --profile myproject-core-discover-deploy
Example: Lambda function reading S3 bucket
# CORRECT: Define resource permission in Terraform as IAM role
resource "aws_iam_role" "lambda_role" {
name = "my-function-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "lambda.amazonaws.com"
}
}]
})
}
resource "aws_iam_role_policy" "lambda_s3_access" {
role = aws_iam_role.lambda_role.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Action = ["s3:GetObject", "s3:PutObject"]
Resource = "arn:aws:s3:::my-bucket/*"
}]
})
}
resource "aws_lambda_function" "my_function" {
function_name = "my-function"
role = aws_iam_role.lambda_role.arn
# ...
}
Example: API Gateway invoking Lambda
# CORRECT: Define resource permission in Terraform as resource policy
resource "aws_lambda_permission" "apigw_lambda" {
statement_id = "AllowAPIGatewayInvoke"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.my_function.function_name
principal = "apigateway.amazonaws.com"
source_arn = "${aws_api_gateway_rest_api.api.execution_arn}/*/*"
}
Response to user: "This is a resource permission (runtime behavior), not a deploy permission. Please define it in Terraform using the pattern above. Resource permissions should be managed as IAM roles/policies attached to resources, not as deploy user permissions."