ExtendedIAMConfiguration.java
package com.cloudforgeci.api.core.iam;
import com.cloudforge.core.enums.TopologyType;
import com.cloudforge.core.enums.RuntimeType;
import com.cloudforge.core.enums.SecurityProfile;
import com.cloudforgeci.api.core.SystemContext;
import com.cloudforge.core.enums.IAMProfile;
import com.cloudforgeci.api.interfaces.IAMConfiguration;
import com.cloudforgeci.api.interfaces.Rule;
import io.github.cdklabs.cdknag.NagPackSuppression;
import io.github.cdklabs.cdknag.NagSuppressions;
import software.amazon.awscdk.services.iam.ManagedPolicy;
import software.amazon.awscdk.services.iam.PolicyStatement;
import software.amazon.awscdk.services.iam.Role;
import software.amazon.awscdk.services.iam.ServicePrincipal;
import java.util.List;
import static com.cloudforgeci.api.core.rules.RuleKit.require;
/**
* Extended IAM configuration with broader permissions for development.
* Suitable for development environments only.
*
* Key features:
* - Additional debugging permissions
* - Extended monitoring capabilities
* - Development tools access
* - Administrative permissions for troubleshooting
*
* WARNING: This IAM profile is NOT recommended for PRODUCTION security profile.
* Use MINIMAL or STANDARD profiles for production deployments with compliance requirements.
*/
public final class ExtendedIAMConfiguration implements IAMConfiguration {
@Override
public IAMProfile kind() {
return IAMProfile.EXTENDED;
}
@Override
public String id() {
return "iam:EXTENDED";
}
@Override
public List<Rule> rules(SystemContext c) {
var rules = new java.util.ArrayList<Rule>();
rules.add(require("vpc", x -> x.vpc));
// Instance security group is only required for EC2 runtime
if (c.runtime == RuntimeType.EC2) {
rules.add(require("instance security group", x -> x.instanceSg));
}
rules.add(require("alb security group", x -> x.albSg));
rules.add(require("efs security group", x -> x.efsSg));
return rules;
}
@Override
public void wire(SystemContext c) {
// Create extended IAM roles based on runtime type
if (c.runtime == RuntimeType.EC2) {
createExtendedEC2Role(c);
} else if (c.runtime == RuntimeType.FARGATE) {
createExtendedFargateRoles(c);
}
}
private void createExtendedEC2Role(SystemContext c) {
// Extended EC2 instance role with development permissions
Role ec2Role = Role.Builder.create(c, "ExtendedEc2Role")
.assumedBy(new ServicePrincipal("ec2.amazonaws.com"))
.managedPolicies(List.of(
ManagedPolicy.fromAwsManagedPolicyName("AmazonSSMManagedInstanceCore"),
ManagedPolicy.fromAwsManagedPolicyName("CloudWatchAgentServerPolicy"),
ManagedPolicy.fromAwsManagedPolicyName("AmazonS3ReadOnlyAccess")
))
.build();
// Suppress IAM4 for AWS managed policies - these are AWS-recommended for EC2 operations
NagSuppressions.addResourceSuppressions(
ec2Role,
List.of(
NagPackSuppression.builder()
.id("AwsSolutions-IAM4")
.reason("AWS managed policies (AmazonSSMManagedInstanceCore, CloudWatchAgentServerPolicy, " +
"AmazonS3ReadOnlyAccess) are AWS-recommended for EC2 instances. These provide " +
"minimal permissions for SSM connectivity, CloudWatch monitoring, and S3 read access.")
.build(),
NagPackSuppression.builder()
.id("AwsSolutions-IAM5")
.reason("Extended IAM profile is designed for DEV environments with broad permissions " +
"for debugging and development. Wildcard permissions enable full CloudWatch, S3, " +
"and EFS access for development flexibility. Production uses MinimalIAMConfiguration.")
.build()
),
Boolean.TRUE
);
// Add extended CloudWatch permissions
ec2Role.addToPolicy(PolicyStatement.Builder.create()
.sid("ExtendedCloudWatchLogs")
.actions(List.of(
"logs:*"
))
.resources(List.of("*"))
.build());
// Add extended CloudWatch metrics permissions
ec2Role.addToPolicy(PolicyStatement.Builder.create()
.sid("ExtendedCloudWatchMetrics")
.actions(List.of(
"cloudwatch:*"
))
.resources(List.of("*"))
.build());
// Add EFS permissions
if (c.efs.get().isPresent()) {
ec2Role.addToPolicy(PolicyStatement.Builder.create()
.sid("ExtendedEfsAccess")
.actions(List.of(
"elasticfilesystem:*"
))
.resources(List.of("*"))
.build());
}
// Add S3 permissions for development
// Use stackName for application-aware S3 bucket patterns
String devBucketPattern = c.stackName != null && !c.stackName.isEmpty()
? c.stackName.toLowerCase() + "-dev-*"
: "*-dev-*";
String backupBucketPattern = c.stackName != null && !c.stackName.isEmpty()
? c.stackName.toLowerCase() + "-backup-*"
: "*-backup-*";
ec2Role.addToPolicy(PolicyStatement.Builder.create()
.sid("ExtendedS3Access")
.actions(List.of(
"s3:*"
))
.resources(List.of(
"arn:aws:s3:::" + devBucketPattern,
"arn:aws:s3:::" + devBucketPattern + "/*",
"arn:aws:s3:::" + backupBucketPattern,
"arn:aws:s3:::" + backupBucketPattern + "/*"
))
.build());
// Add EC2 permissions for debugging
ec2Role.addToPolicy(PolicyStatement.Builder.create()
.sid("ExtendedEc2Debug")
.actions(List.of(
"ec2:DescribeInstances",
"ec2:DescribeVolumes",
"ec2:DescribeSnapshots",
"ec2:DescribeImages",
"ec2:DescribeSecurityGroups",
"ec2:DescribeVpcs",
"ec2:DescribeSubnets"
))
.resources(List.of("*"))
.build());
// Add Systems Manager permissions for debugging
ec2Role.addToPolicy(PolicyStatement.Builder.create()
.sid("ExtendedSSMDebug")
.actions(List.of(
"ssm:DescribeInstanceInformation",
"ssm:ListCommandInvocations",
"ssm:SendCommand",
"ssm:GetCommandInvocation"
))
.resources(List.of("*"))
.build());
c.ec2InstanceRole.set(ec2Role);
}
private void createExtendedFargateRoles(SystemContext c) {
// Extended ECS Task Execution Role
Role executionRole = Role.Builder.create(c, "ExtendedTaskExecutionRole")
.assumedBy(new ServicePrincipal("ecs-tasks.amazonaws.com"))
.managedPolicies(List.of(
ManagedPolicy.fromAwsManagedPolicyName("service-role/AmazonECSTaskExecutionRolePolicy")
))
.build();
NagSuppressions.addResourceSuppressions(
executionRole,
List.of(
NagPackSuppression.builder()
.id("AwsSolutions-IAM4")
.reason("AmazonECSTaskExecutionRolePolicy is an AWS-managed policy specifically " +
"designed for ECS task execution. It provides minimal required permissions " +
"for pulling container images from ECR and writing logs to CloudWatch.")
.build()
),
Boolean.TRUE
);
// Extended ECS Task Role
Role taskRole = Role.Builder.create(c, "ExtendedTaskRole")
.assumedBy(new ServicePrincipal("ecs-tasks.amazonaws.com"))
.build();
// Add extended EFS permissions
if (c.efs.get().isPresent() && c.ap.get().isPresent()) {
taskRole.addToPolicy(PolicyStatement.Builder.create()
.sid("ExtendedEfsAccess")
.actions(List.of(
"elasticfilesystem:*"
))
.resources(List.of("*"))
.build());
}
// Add extended CloudWatch permissions
taskRole.addToPolicy(PolicyStatement.Builder.create()
.sid("ExtendedCloudWatchLogs")
.actions(List.of(
"logs:*"
))
.resources(List.of("*"))
.build());
// Add extended CloudWatch metrics permissions
taskRole.addToPolicy(PolicyStatement.Builder.create()
.sid("ExtendedCloudWatchMetrics")
.actions(List.of(
"cloudwatch:*"
))
.resources(List.of("*"))
.build());
// Add extended S3 permissions
// Use stackName for application-aware S3 bucket patterns
String devBucketPattern = c.stackName != null && !c.stackName.isEmpty()
? c.stackName.toLowerCase() + "-dev-*"
: "*-dev-*";
String backupBucketPattern = c.stackName != null && !c.stackName.isEmpty()
? c.stackName.toLowerCase() + "-backup-*"
: "*-backup-*";
taskRole.addToPolicy(PolicyStatement.Builder.create()
.sid("ExtendedS3Access")
.actions(List.of(
"s3:*"
))
.resources(List.of(
"arn:aws:s3:::" + devBucketPattern,
"arn:aws:s3:::" + devBucketPattern + "/*",
"arn:aws:s3:::" + backupBucketPattern,
"arn:aws:s3:::" + backupBucketPattern + "/*"
))
.build());
// Add ECS permissions for debugging
taskRole.addToPolicy(PolicyStatement.Builder.create()
.sid("ExtendedEcsDebug")
.actions(List.of(
"ecs:DescribeClusters",
"ecs:DescribeServices",
"ecs:DescribeTasks",
"ecs:DescribeTaskDefinition",
"ecs:ListTasks",
"ecs:ListServices"
))
.resources(List.of("*"))
.build());
c.fargateExecutionRole.set(executionRole);
c.fargateTaskRole.set(taskRole);
}
}