[Rapticore] Security Findings - hamza/RCOR-2712 (Part 1)#42
[Rapticore] Security Findings - hamza/RCOR-2712 (Part 1)#42rapticore-github[bot] wants to merge 95 commits into
Conversation
added policies related to tags
Co-authored-by: Azeem Irshad <azeem.irshad@rapticore.com>
Co-authored-by: Azeem Irshad <azeem.irshad@rapticore.com>
freemium_update
changed the name of the standard cfn to standardsomething
…ss-account IAM role
RCOR-2203: added reactive and one-click remediation permission in cross-account IAM role
RCOR-2240: updated reactive remediation permissions in cross-account IAM role
RCOR-2241: added IAM right-sizing permissions in cross-account IAM role
RCOR-2335: updated one click remediation permissions in cross-account IAM role
RCOR-2361: added guardrails permissions in cross-account IAM role
…iscovery, api-helper
add queue creation and azure oidc setup in stack
| - IpProtocol: tcp | ||
| FromPort: 443 | ||
| ToPort: 443 | ||
| CidrIp: 0.0.0.0/0 | ||
| Description: Allow HTTPS traffic | ||
| Tags: | ||
| - Key: Name | ||
| Value: !Sub "${ClusterName}-cluster-sg" | ||
|
|
||
| ClusterSecurityGroupIngress: | ||
| Type: AWS::EC2::SecurityGroupIngress | ||
| Properties: | ||
| GroupId: !Ref ClusterSecurityGroup | ||
| IpProtocol: "-1" | ||
| SourceSecurityGroupId: !Ref ClusterSecurityGroup | ||
| Description: Allow cluster internal communication | ||
|
|
||
| ##### | ||
| # EKS Cluster | ||
| ##### | ||
| EksCluster: | ||
| Type: AWS::EKS::Cluster | ||
| Properties: | ||
| Name: !Ref ClusterName | ||
| Version: !Ref KubernetesVersion | ||
| RoleArn: !GetAtt EksClusterRole.Arn | ||
| ResourcesVpcConfig: | ||
| SecurityGroupIds: | ||
| - !Ref ClusterSecurityGroup | ||
| SubnetIds: !Ref SubnetIds | ||
| EndpointPublicAccess: !Ref EndpointPublicAccess | ||
| EndpointPrivateAccess: !Ref EndpointPrivateAccess | ||
| Logging: | ||
| ClusterLogging: | ||
| EnabledTypes: | ||
| - Type: api | ||
| - Type: audit | ||
| - Type: authenticator | ||
| - Type: controllerManager | ||
| - Type: scheduler | ||
| Tags: | ||
| - Key: Name | ||
| Value: !Ref ClusterName | ||
|
|
||
| ##### | ||
| # EKS Add-ons | ||
| ##### | ||
| VpcCniAddon: | ||
| Type: AWS::EKS::Addon | ||
| DependsOn: EksCluster | ||
| Properties: | ||
| AddonName: vpc-cni | ||
| ClusterName: !Ref ClusterName | ||
| ResolveConflicts: OVERWRITE | ||
| ConfigurationValues: '{"env":{"ENABLE_PREFIX_DELEGATION":"true","WARM_PREFIX_TARGET":"1","MINIMUM_IP_TARGET":"50","WARM_IP_TARGET":"10"}}' | ||
|
|
||
| CoreDnsAddon: | ||
| Type: AWS::EKS::Addon | ||
| DependsOn: EksCluster | ||
| Properties: | ||
| AddonName: coredns | ||
| ClusterName: !Ref ClusterName | ||
| ResolveConflicts: OVERWRITE |
There was a problem hiding this comment.
🔒 Security Finding: EKS Secrets Encryption Disabled
Severity: High
Lines: 192-214
Actions
- Mark as Ignored - Resolve this finding manually (Finding ID:
RCOR-0114)
Description
The EKS Cluster does not have Secrets Encryption enabled. This exposes sensitive data to unauthorized access if the cluster is compromised. Secrets encryption is crucial for protecting sensitive data from unauthorized access.
Remediation Summary
Fix Required
- Add the
EncryptionConfigproperty to the EKS Cluster resource (lines 192-214) to enable secrets encryption - Specify the
Resourcesarray withsecretsas the resource type to encrypt - Reference a KMS key ARN (either create a new KMS key or use an existing one) for the encryption provider
Code Pattern
Add this block after the Logging section and before Tags:
EncryptionConfig:
- Resources:
- secrets
Provider:
KeyArn: !GetAtt EksKmsKey.Arn
Ensure an AWS::KMS::Key resource is defined in the template (or reference an existing KMS key ARN) to serve as the encryption provider.
Verification
Deploy the updated CloudFormation template and confirm the EKS cluster's EncryptionConfig shows secrets encryption is enabled via AWS Console or AWS CLI (aws eks describe-cluster --name <cluster-name> --query cluster.encryptionConfig).
Priority
high - Estimated effort: 10-15 minutes
Suggested Fix
Click "Commit suggestion" to apply this fix:
| - IpProtocol: tcp | |
| FromPort: 443 | |
| ToPort: 443 | |
| CidrIp: 0.0.0.0/0 | |
| Description: Allow HTTPS traffic | |
| Tags: | |
| - Key: Name | |
| Value: !Sub "${ClusterName}-cluster-sg" | |
| ClusterSecurityGroupIngress: | |
| Type: AWS::EC2::SecurityGroupIngress | |
| Properties: | |
| GroupId: !Ref ClusterSecurityGroup | |
| IpProtocol: "-1" | |
| SourceSecurityGroupId: !Ref ClusterSecurityGroup | |
| Description: Allow cluster internal communication | |
| ##### | |
| # EKS Cluster | |
| ##### | |
| EksCluster: | |
| Type: AWS::EKS::Cluster | |
| Properties: | |
| Name: !Ref ClusterName | |
| Version: !Ref KubernetesVersion | |
| RoleArn: !GetAtt EksClusterRole.Arn | |
| ResourcesVpcConfig: | |
| SecurityGroupIds: | |
| - !Ref ClusterSecurityGroup | |
| SubnetIds: !Ref SubnetIds | |
| EndpointPublicAccess: !Ref EndpointPublicAccess | |
| EndpointPrivateAccess: !Ref EndpointPrivateAccess | |
| Logging: | |
| ClusterLogging: | |
| EnabledTypes: | |
| - Type: api | |
| - Type: audit | |
| - Type: authenticator | |
| - Type: controllerManager | |
| - Type: scheduler | |
| Tags: | |
| - Key: Name | |
| Value: !Ref ClusterName | |
| ##### | |
| # EKS Add-ons | |
| ##### | |
| VpcCniAddon: | |
| Type: AWS::EKS::Addon | |
| DependsOn: EksCluster | |
| Properties: | |
| AddonName: vpc-cni | |
| ClusterName: !Ref ClusterName | |
| ResolveConflicts: OVERWRITE | |
| ConfigurationValues: '{"env":{"ENABLE_PREFIX_DELEGATION":"true","WARM_PREFIX_TARGET":"1","MINIMUM_IP_TARGET":"50","WARM_IP_TARGET":"10"}}' | |
| CoreDnsAddon: | |
| Type: AWS::EKS::Addon | |
| DependsOn: EksCluster | |
| Properties: | |
| AddonName: coredns | |
| ClusterName: !Ref ClusterName | |
| ResolveConflicts: OVERWRITE | |
| ```yaml | |
| - IpProtocol: tcp | |
| FromPort: 443 | |
| ToPort: 443 | |
| CidrIp: 0.0.0.0/0 | |
| Description: Allow HTTPS traffic | |
| Tags: | |
| - Key: Name | |
| Value: !Sub "${ClusterName}-cluster-sg" | |
| ClusterSecurityGroupIngress: | |
| Type: AWS::EC2::SecurityGroupIngress | |
| Properties: | |
| GroupId: !Ref ClusterSecurityGroup | |
| IpProtocol: "-1" | |
| SourceSecurityGroupId: !Ref ClusterSecurityGroup | |
| Description: Allow cluster internal communication | |
| ##### | |
| # EKS Cluster | |
| ##### | |
| EksCluster: | |
| Type: AWS::EKS::Cluster | |
| Properties: | |
| Name: !Ref ClusterName | |
| Version: !Ref KubernetesVersion | |
| RoleArn: !GetAtt EksClusterRole.Arn | |
| ResourcesVpcConfig: | |
| SecurityGroupIds: | |
| - !Ref ClusterSecurityGroup | |
| SubnetIds: !Ref SubnetIds | |
| EndpointPublicAccess: !Ref EndpointPublicAccess | |
| EndpointPrivateAccess: !Ref EndpointPrivateAccess | |
| Logging: | |
| ClusterLogging: | |
| EnabledTypes: | |
| - Type: api | |
| - Type: audit | |
| - Type: authenticator | |
| - Type: controllerManager | |
| - Type: scheduler | |
| EncryptionConfig: | |
| - Resources: | |
| - secrets | |
| Provider: | |
| KeyArn: !GetAtt EksSecretsEncryptionKey.Arn | |
| Tags: | |
| - Key: Name | |
| Value: !Ref ClusterName | |
| ##### | |
| # EKS Add-ons | |
| ##### | |
| VpcCniAddon: | |
| Type: AWS::EKS::Addon | |
| DependsOn: EksCluster | |
| Properties: | |
| AddonName: vpc-cni | |
| ClusterName: !Ref ClusterName | |
| ResolveConflicts: OVERWRITE | |
| ConfigurationValues: '{"env":{"ENABLE_PREFIX_DELEGATION":"true","WARM_PREFIX_TARGET":"1","MINIMUM_IP_TARGET":"50","WARM_IP_TARGET":"10"}}' | |
| CoreDnsAddon: | |
| Type: AWS::EKS::Addon | |
| DependsOn: EksCluster | |
| Properties: | |
| AddonName: coredns | |
| ClusterName: !Ref ClusterName | |
| ResolveConflicts: OVERWRITE |
---
🤖 Generated by Rapticore
|
|
||
| ClusterEndpoint: | ||
| Type: String | ||
| Description: EKS cluster API server endpoint (from EksClusterStack) | ||
|
|
||
| ClusterCertificateAuthority: | ||
| Type: String | ||
| Description: EKS cluster certificate authority data, base64 encoded (from EksClusterStack) | ||
|
|
||
| ClusterServiceCidr: | ||
| Type: String | ||
| Default: "10.100.0.0/16" | ||
| Description: Kubernetes service IPv4 CIDR (from EksClusterStack) | ||
|
|
||
| Resources: | ||
| ##### | ||
| # Launch Template — sets maxPods=110 via nodeadm for AL2023 | ||
| # Required because prefix delegation increases available IPs but | ||
| # the kubelet default max-pods calculation ignores it. | ||
| ##### | ||
| NodeLaunchTemplate: | ||
| Type: AWS::EC2::LaunchTemplate | ||
| Properties: | ||
| LaunchTemplateData: | ||
| BlockDeviceMappings: | ||
| - DeviceName: /dev/xvda | ||
| Ebs: | ||
| VolumeSize: !Ref DiskSize | ||
| VolumeType: gp3 | ||
| Encrypted: true | ||
| UserData: | ||
| Fn::Base64: !Sub | | ||
| MIME-Version: 1.0 | ||
| Content-Type: multipart/mixed; boundary="BOUNDARY" | ||
|
|
||
| --BOUNDARY | ||
| Content-Type: application/node.eks.aws | ||
|
|
||
| --- | ||
| apiVersion: node.eks.aws/v1alpha1 | ||
| kind: NodeConfig | ||
| spec: | ||
| cluster: | ||
| name: ${ClusterName} | ||
| apiServerEndpoint: ${ClusterEndpoint} | ||
| certificateAuthority: ${ClusterCertificateAuthority} | ||
| cidr: ${ClusterServiceCidr} | ||
| kubelet: | ||
| config: | ||
| maxPods: 110 | ||
|
|
||
| --BOUNDARY-- | ||
|
|
||
| ##### | ||
| # EKS Node Group | ||
| ##### | ||
| EksNodeGroup: | ||
| Type: AWS::EKS::Nodegroup | ||
| Properties: | ||
| ClusterName: !Ref ClusterName | ||
| NodeRole: !Ref NodeRoleArn | ||
| Subnets: !Ref SubnetIds | ||
| ScalingConfig: | ||
| DesiredSize: !Ref DesiredSize | ||
| MinSize: !Ref MinSize | ||
| MaxSize: !Ref MaxSize | ||
| InstanceTypes: !Ref InstanceTypes | ||
| CapacityType: !Ref CapacityType | ||
| AmiType: !Ref AmiType | ||
| LaunchTemplate: | ||
| Id: !Ref NodeLaunchTemplate | ||
| Version: !GetAtt NodeLaunchTemplate.LatestVersionNumber |
There was a problem hiding this comment.
🔒 Security Finding: Instance Metadata Service V1 Enabled
Severity: High
Lines: 90-121
Actions
- Mark as Ignored - Resolve this finding manually (Finding ID:
RCOR-0075)
Description
Instance Metadata Service Version 1 is enabled, which is a security risk. This can allow unauthorized access to instance metadata, leading to potential data exposure and unauthorized actions.
Remediation Summary
Fix Required
• Add MetadataOptions to the LaunchTemplateData section (after line 99, before or after UserData) to disable IMDSv1 and enforce IMDSv2
• Set HttpTokens to 'required' to mandate token-based metadata requests (IMDSv2)
• Set HttpPutResponseHopLimit to '1' to prevent metadata propagation across network hops
Code Pattern
Add this block to LaunchTemplateData:
MetadataOptions:
HttpTokens: required
HttpPutResponseHopLimit: 1
Verification
Deploy the CloudFormation template and verify via AWS Console that the Launch Template's MetadataOptions shows HttpTokens='required', indicating IMDSv2 is enforced and IMDSv1 is disabled.
Priority
high - Estimated effort: 5 minutes
Suggested Fix
Click "Commit suggestion" to apply this fix:
| ClusterEndpoint: | |
| Type: String | |
| Description: EKS cluster API server endpoint (from EksClusterStack) | |
| ClusterCertificateAuthority: | |
| Type: String | |
| Description: EKS cluster certificate authority data, base64 encoded (from EksClusterStack) | |
| ClusterServiceCidr: | |
| Type: String | |
| Default: "10.100.0.0/16" | |
| Description: Kubernetes service IPv4 CIDR (from EksClusterStack) | |
| Resources: | |
| ##### | |
| # Launch Template — sets maxPods=110 via nodeadm for AL2023 | |
| # Required because prefix delegation increases available IPs but | |
| # the kubelet default max-pods calculation ignores it. | |
| ##### | |
| NodeLaunchTemplate: | |
| Type: AWS::EC2::LaunchTemplate | |
| Properties: | |
| LaunchTemplateData: | |
| BlockDeviceMappings: | |
| - DeviceName: /dev/xvda | |
| Ebs: | |
| VolumeSize: !Ref DiskSize | |
| VolumeType: gp3 | |
| Encrypted: true | |
| UserData: | |
| Fn::Base64: !Sub | | |
| MIME-Version: 1.0 | |
| Content-Type: multipart/mixed; boundary="BOUNDARY" | |
| --BOUNDARY | |
| Content-Type: application/node.eks.aws | |
| --- | |
| apiVersion: node.eks.aws/v1alpha1 | |
| kind: NodeConfig | |
| spec: | |
| cluster: | |
| name: ${ClusterName} | |
| apiServerEndpoint: ${ClusterEndpoint} | |
| certificateAuthority: ${ClusterCertificateAuthority} | |
| cidr: ${ClusterServiceCidr} | |
| kubelet: | |
| config: | |
| maxPods: 110 | |
| --BOUNDARY-- | |
| ##### | |
| # EKS Node Group | |
| ##### | |
| EksNodeGroup: | |
| Type: AWS::EKS::Nodegroup | |
| Properties: | |
| ClusterName: !Ref ClusterName | |
| NodeRole: !Ref NodeRoleArn | |
| Subnets: !Ref SubnetIds | |
| ScalingConfig: | |
| DesiredSize: !Ref DesiredSize | |
| MinSize: !Ref MinSize | |
| MaxSize: !Ref MaxSize | |
| InstanceTypes: !Ref InstanceTypes | |
| CapacityType: !Ref CapacityType | |
| AmiType: !Ref AmiType | |
| LaunchTemplate: | |
| Id: !Ref NodeLaunchTemplate | |
| Version: !GetAtt NodeLaunchTemplate.LatestVersionNumber | |
| ```yaml | |
| ClusterEndpoint: | |
| Type: String | |
| Description: EKS cluster API server endpoint (from EksClusterStack) | |
| ClusterCertificateAuthority: | |
| Type: String | |
| Description: EKS cluster certificate authority data, base64 encoded (from EksClusterStack) | |
| ClusterServiceCidr: | |
| Type: String | |
| Default: "10.100.0.0/16" | |
| Description: Kubernetes service IPv4 CIDR (from EksClusterStack) | |
| Resources: | |
| ##### | |
| # Launch Template — sets maxPods=110 via nodeadm for AL2023 | |
| # Required because prefix delegation increases available IPs but | |
| # the kubelet default max-pods calculation ignores it. | |
| ##### | |
| NodeLaunchTemplate: | |
| Type: AWS::EC2::LaunchTemplate | |
| Properties: | |
| LaunchTemplateData: | |
| MetadataOptions: | |
| HttpEndpoint: enabled | |
| HttpTokens: required | |
| HttpPutResponseHopLimit: 1 | |
| BlockDeviceMappings: | |
| - DeviceName: /dev/xvda | |
| Ebs: | |
| VolumeSize: !Ref DiskSize | |
| VolumeType: gp3 | |
| Encrypted: true | |
| UserData: | |
| Fn::Base64: !Sub | | |
| MIME-Version: 1.0 | |
| Content-Type: multipart/mixed; boundary="BOUNDARY" | |
| --BOUNDARY | |
| Content-Type: application/node.eks.aws | |
| --- | |
| apiVersion: node.eks.aws/v1alpha1 | |
| kind: NodeConfig | |
| spec: | |
| cluster: | |
| name: ${ClusterName} | |
| apiServerEndpoint: ${ClusterEndpoint} | |
| certificateAuthority: ${ClusterCertificateAuthority} | |
| cidr: ${ClusterServiceCidr} | |
| kubelet: | |
| config: | |
| maxPods: 110 | |
| --BOUNDARY-- | |
| ##### | |
| # EKS Node Group | |
| ##### | |
| EksNodeGroup: | |
| Type: AWS::EKS::Nodegroup | |
| Properties: | |
| ClusterName: !Ref ClusterName | |
| NodeRole: !Ref NodeRoleArn | |
| Subnets: !Ref SubnetIds | |
| ScalingConfig: | |
| DesiredSize: !Ref DesiredSize | |
| MinSize: !Ref MinSize | |
| MaxSize: !Ref MaxSize | |
| InstanceTypes: !Ref InstanceTypes | |
| CapacityType: !Ref CapacityType | |
| AmiType: !Ref AmiType | |
| LaunchTemplate: | |
| Id: !Ref NodeLaunchTemplate | |
| Version: !GetAtt NodeLaunchTemplate.LatestVersionNumber |
---
🤖 Generated by Rapticore
| Action: | ||
| - sts:AssumeRole | ||
| - sts:TagSession | ||
| Resource: "arn:aws:iam::*:role/rapticore-cross-account-*" | ||
| # IAM and EC2 Read-Only (needed by discovery for role enumeration) | ||
| - Effect: Allow | ||
| Action: | ||
| - iam:ListRole* | ||
| - iam:GetRole* | ||
| - ec2:DescribeRegions | ||
| Resource: "*" | ||
| # Cognito Identity (needed for Azure workload identity) | ||
| - Effect: Allow | ||
| Action: | ||
| - cognito-identity:GetOpenIdTokenForDeveloperIdentity | ||
| Resource: !Sub "arn:aws:cognito-identity:${AWS::Region}:${AWS::AccountId}:identitypool/*" | ||
|
|
||
| ##### | ||
| # AWS Load Balancer Controller IAM Role (IRSA) | ||
| ##### | ||
| AwsLoadBalancerControllerRole: | ||
| Type: AWS::IAM::Role | ||
| DependsOn: OidcProvider | ||
| Properties: | ||
| RoleName: !Sub "${ClusterName}-aws-load-balancer-controller-role" | ||
| AssumeRolePolicyDocument: | ||
| Fn::Sub: | ||
| - | | ||
| { | ||
| "Version": "2012-10-17", | ||
| "Statement": [{ | ||
| "Effect": "Allow", | ||
| "Principal": { | ||
| "Federated": "arn:aws:iam::${AWS::AccountId}:oidc-provider/${OidcUrl}" | ||
| }, | ||
| "Action": "sts:AssumeRoleWithWebIdentity", | ||
| "Condition": { | ||
| "StringEquals": { | ||
| "${OidcUrl}:aud": "sts.amazonaws.com", | ||
| "${OidcUrl}:sub": "system:serviceaccount:kube-system:aws-load-balancer-controller" | ||
| } | ||
| } | ||
| }] | ||
| } | ||
| - OidcUrl: !Select [1, !Split ["https://", !GetAtt EksCluster.OpenIdConnectIssuerUrl]] | ||
| Policies: | ||
| - PolicyName: AWSLoadBalancerControllerPolicy | ||
| PolicyDocument: | ||
| Version: "2012-10-17" | ||
| Statement: | ||
| - Effect: Allow | ||
| Action: | ||
| - iam:CreateServiceLinkedRole | ||
| Resource: "*" | ||
| Condition: | ||
| StringEquals: | ||
| iam:AWSServiceName: elasticloadbalancing.amazonaws.com | ||
| - Effect: Allow | ||
| Action: | ||
| - ec2:DescribeAccountAttributes | ||
| - ec2:DescribeAddresses | ||
| - ec2:DescribeAvailabilityZones | ||
| - ec2:DescribeInternetGateways | ||
| - ec2:DescribeVpcs | ||
| - ec2:DescribeVpcPeeringConnections | ||
| - ec2:DescribeSubnets | ||
| - ec2:DescribeSecurityGroups | ||
| - ec2:DescribeInstances | ||
| - ec2:DescribeNetworkInterfaces | ||
| - ec2:DescribeTags | ||
| - ec2:DescribeRouteTables | ||
| - ec2:GetCoipPoolUsage | ||
| - ec2:DescribeCoipPools | ||
| - elasticloadbalancing:DescribeLoadBalancers | ||
| - elasticloadbalancing:DescribeLoadBalancerAttributes | ||
| - elasticloadbalancing:DescribeListeners | ||
| - elasticloadbalancing:DescribeListenerAttributes | ||
| - elasticloadbalancing:DescribeListenerCertificates | ||
| - elasticloadbalancing:DescribeSSLPolicies | ||
| - elasticloadbalancing:DescribeRules | ||
| - elasticloadbalancing:DescribeTargetGroups | ||
| - elasticloadbalancing:DescribeTargetGroupAttributes | ||
| - elasticloadbalancing:DescribeTargetHealth | ||
| - elasticloadbalancing:DescribeTags | ||
| Resource: "*" | ||
| - Effect: Allow | ||
| Action: | ||
| - cognito-idp:DescribeUserPoolClient | ||
| - acm:ListCertificates | ||
| - acm:DescribeCertificate | ||
| - iam:ListServerCertificates | ||
| - iam:GetServerCertificate | ||
| - waf-regional:GetWebACL | ||
| - waf-regional:GetWebACLForResource | ||
| - waf-regional:AssociateWebACL | ||
| - waf-regional:DisassociateWebACL | ||
| - wafv2:GetWebACL | ||
| - wafv2:GetWebACLForResource | ||
| - wafv2:AssociateWebACL | ||
| - wafv2:DisassociateWebACL | ||
| - shield:GetSubscriptionState | ||
| - shield:DescribeProtection | ||
| - shield:CreateProtection | ||
| - shield:DeleteProtection | ||
| Resource: "*" | ||
| - Effect: Allow | ||
| Action: | ||
| - ec2:AuthorizeSecurityGroupIngress | ||
| - ec2:RevokeSecurityGroupIngress | ||
| Resource: "*" | ||
| - Effect: Allow | ||
| Action: | ||
| - ec2:CreateSecurityGroup | ||
| Resource: "*" | ||
| - Effect: Allow | ||
| Action: | ||
| - ec2:CreateTags | ||
| Resource: "arn:aws:ec2:*:*:security-group/*" | ||
| Condition: | ||
| StringEquals: | ||
| ec2:CreateAction: CreateSecurityGroup | ||
| "Null": | ||
| aws:RequestTag/elbv2.k8s.aws/cluster: "false" | ||
| - Effect: Allow | ||
| Action: | ||
| - ec2:CreateTags | ||
| - ec2:DeleteTags | ||
| Resource: "arn:aws:ec2:*:*:security-group/*" | ||
| Condition: | ||
| "Null": | ||
| aws:RequestTag/elbv2.k8s.aws/cluster: "true" | ||
| aws:ResourceTag/elbv2.k8s.aws/cluster: "false" | ||
| - Effect: Allow | ||
| Action: | ||
| - ec2:AuthorizeSecurityGroupIngress | ||
| - ec2:RevokeSecurityGroupIngress | ||
| - ec2:DeleteSecurityGroup | ||
| Resource: "*" | ||
| Condition: | ||
| "Null": | ||
| aws:ResourceTag/elbv2.k8s.aws/cluster: "false" | ||
| - Effect: Allow | ||
| Action: | ||
| - elasticloadbalancing:CreateLoadBalancer | ||
| - elasticloadbalancing:CreateTargetGroup | ||
| Resource: "*" | ||
| Condition: | ||
| "Null": | ||
| aws:RequestTag/elbv2.k8s.aws/cluster: "false" | ||
| - Effect: Allow | ||
| Action: | ||
| - elasticloadbalancing:CreateListener | ||
| - elasticloadbalancing:DeleteListener | ||
| - elasticloadbalancing:CreateRule | ||
| - elasticloadbalancing:DeleteRule | ||
| Resource: "*" | ||
| - Effect: Allow | ||
| Action: | ||
| - elasticloadbalancing:AddTags | ||
| - elasticloadbalancing:RemoveTags | ||
| Resource: | ||
| - "arn:aws:elasticloadbalancing:*:*:targetgroup/*/*" | ||
| - "arn:aws:elasticloadbalancing:*:*:loadbalancer/net/*/*" | ||
| - "arn:aws:elasticloadbalancing:*:*:loadbalancer/app/*/*" | ||
| Condition: | ||
| "Null": | ||
| aws:RequestTag/elbv2.k8s.aws/cluster: "true" | ||
| aws:ResourceTag/elbv2.k8s.aws/cluster: "false" | ||
| - Effect: Allow | ||
| Action: | ||
| - elasticloadbalancing:AddTags | ||
| - elasticloadbalancing:RemoveTags | ||
| Resource: | ||
| - "arn:aws:elasticloadbalancing:*:*:listener/net/*/*/*" | ||
| - "arn:aws:elasticloadbalancing:*:*:listener/app/*/*/*" | ||
| - "arn:aws:elasticloadbalancing:*:*:listener-rule/net/*/*/*" | ||
| - "arn:aws:elasticloadbalancing:*:*:listener-rule/app/*/*/*" | ||
| - Effect: Allow | ||
| Action: | ||
| - elasticloadbalancing:ModifyLoadBalancerAttributes | ||
| - elasticloadbalancing:SetIpAddressType | ||
| - elasticloadbalancing:SetSecurityGroups | ||
| - elasticloadbalancing:SetSubnets | ||
| - elasticloadbalancing:DeleteLoadBalancer | ||
| - elasticloadbalancing:ModifyTargetGroup | ||
| - elasticloadbalancing:ModifyTargetGroupAttributes | ||
| - elasticloadbalancing:DeleteTargetGroup | ||
| Resource: "*" | ||
| Condition: | ||
| "Null": | ||
| aws:ResourceTag/elbv2.k8s.aws/cluster: "false" | ||
| - Effect: Allow | ||
| Action: | ||
| - elasticloadbalancing:AddTags | ||
| Resource: | ||
| - "arn:aws:elasticloadbalancing:*:*:targetgroup/*/*" | ||
| - "arn:aws:elasticloadbalancing:*:*:loadbalancer/net/*/*" | ||
| - "arn:aws:elasticloadbalancing:*:*:loadbalancer/app/*/*" | ||
| Condition: | ||
| StringEquals: |
There was a problem hiding this comment.
🔒 Security Finding: IAM Policy Allows Unsafe Write Access
Severity: High
Lines: 396-593
Actions
- Mark as Ignored - Resolve this finding manually (Finding ID:
RCOR-0019)
Description
The IAM policy allows write access without necessary constraints, which can lead to unauthorized modifications. This can compromise the security and integrity of the associated resources. The impact includes potential data leaks or unauthorized changes to critical infrastructure.
Remediation Summary
Fix Required
• Remove or constrain overly permissive write actions: Several statements allow write operations (CreateSecurityGroup, AuthorizeSecurityGroupIngress, CreateLoadBalancer, ModifyListener, etc.) with Resource: "*" or insufficient conditions. These must be scoped to specific ARNs or have resource-level constraints.
• Add resource ARN constraints to write statements: Lines with write actions lacking proper conditions should specify exact ARN patterns. For example, ec2:AuthorizeSecurityGroupIngress and ec2:RevokeSecurityGroupIngress (lines 76-80) have Resource: "*" with only a Condition tag check—add ARN restrictions like arn:aws:ec2:*:*:security-group/*.
• Scope listener/rule modifications: The statement at the end (elasticloadbalancing:SetWebAcl, ModifyListener, AddListenerCertificates, RemoveListenerCertificates, ModifyRule) has Resource: "*" with no conditions. Add ARN-based resource restrictions or introduce conditions that limit modifications to cluster-tagged resources.
Code Pattern
For write actions without proper scoping, apply this pattern:
- Effect: Allow
Action:
- ec2:AuthorizeSecurityGroupIngress
- ec2:RevokeSecurityGroupIngress
Resource: "arn:aws:ec2:*:*:security-group/*"
Condition:
"Null":
aws:ResourceTag/elbv2.k8s.aws/cluster: "false"For ELB operations, restrict to tagged resources:
- Effect: Allow
Action:
- elasticloadbalancing:ModifyListener
- elasticloadbalancing:SetWebAcl
Resource:
- "arn:aws:elasticloadbalancing:*:*:listener/*"
- "arn:aws:elasticloadbalancing:*:*:loadbalancer/*"
Condition:
"Null":
aws:ResourceTag/elbv2.k8s.aws/cluster: "false"Verification
Validate that all write-capable actions (Create*, Modify*, Delete*, Authorize*, Set*) either have specific ARN patterns in Resource field or have Condition blocks referencing resource tags/request tags to prevent unrestricted modifications.
Priority
high - Estimated effort: 20 minutes
Suggested Fix
Click "Commit suggestion" to apply this fix:
| Action: | |
| - sts:AssumeRole | |
| - sts:TagSession | |
| Resource: "arn:aws:iam::*:role/rapticore-cross-account-*" | |
| # IAM and EC2 Read-Only (needed by discovery for role enumeration) | |
| - Effect: Allow | |
| Action: | |
| - iam:ListRole* | |
| - iam:GetRole* | |
| - ec2:DescribeRegions | |
| Resource: "*" | |
| # Cognito Identity (needed for Azure workload identity) | |
| - Effect: Allow | |
| Action: | |
| - cognito-identity:GetOpenIdTokenForDeveloperIdentity | |
| Resource: !Sub "arn:aws:cognito-identity:${AWS::Region}:${AWS::AccountId}:identitypool/*" | |
| ##### | |
| # AWS Load Balancer Controller IAM Role (IRSA) | |
| ##### | |
| AwsLoadBalancerControllerRole: | |
| Type: AWS::IAM::Role | |
| DependsOn: OidcProvider | |
| Properties: | |
| RoleName: !Sub "${ClusterName}-aws-load-balancer-controller-role" | |
| AssumeRolePolicyDocument: | |
| Fn::Sub: | |
| - | | |
| { | |
| "Version": "2012-10-17", | |
| "Statement": [{ | |
| "Effect": "Allow", | |
| "Principal": { | |
| "Federated": "arn:aws:iam::${AWS::AccountId}:oidc-provider/${OidcUrl}" | |
| }, | |
| "Action": "sts:AssumeRoleWithWebIdentity", | |
| "Condition": { | |
| "StringEquals": { | |
| "${OidcUrl}:aud": "sts.amazonaws.com", | |
| "${OidcUrl}:sub": "system:serviceaccount:kube-system:aws-load-balancer-controller" | |
| } | |
| } | |
| }] | |
| } | |
| - OidcUrl: !Select [1, !Split ["https://", !GetAtt EksCluster.OpenIdConnectIssuerUrl]] | |
| Policies: | |
| - PolicyName: AWSLoadBalancerControllerPolicy | |
| PolicyDocument: | |
| Version: "2012-10-17" | |
| Statement: | |
| - Effect: Allow | |
| Action: | |
| - iam:CreateServiceLinkedRole | |
| Resource: "*" | |
| Condition: | |
| StringEquals: | |
| iam:AWSServiceName: elasticloadbalancing.amazonaws.com | |
| - Effect: Allow | |
| Action: | |
| - ec2:DescribeAccountAttributes | |
| - ec2:DescribeAddresses | |
| - ec2:DescribeAvailabilityZones | |
| - ec2:DescribeInternetGateways | |
| - ec2:DescribeVpcs | |
| - ec2:DescribeVpcPeeringConnections | |
| - ec2:DescribeSubnets | |
| - ec2:DescribeSecurityGroups | |
| - ec2:DescribeInstances | |
| - ec2:DescribeNetworkInterfaces | |
| - ec2:DescribeTags | |
| - ec2:DescribeRouteTables | |
| - ec2:GetCoipPoolUsage | |
| - ec2:DescribeCoipPools | |
| - elasticloadbalancing:DescribeLoadBalancers | |
| - elasticloadbalancing:DescribeLoadBalancerAttributes | |
| - elasticloadbalancing:DescribeListeners | |
| - elasticloadbalancing:DescribeListenerAttributes | |
| - elasticloadbalancing:DescribeListenerCertificates | |
| - elasticloadbalancing:DescribeSSLPolicies | |
| - elasticloadbalancing:DescribeRules | |
| - elasticloadbalancing:DescribeTargetGroups | |
| - elasticloadbalancing:DescribeTargetGroupAttributes | |
| - elasticloadbalancing:DescribeTargetHealth | |
| - elasticloadbalancing:DescribeTags | |
| Resource: "*" | |
| - Effect: Allow | |
| Action: | |
| - cognito-idp:DescribeUserPoolClient | |
| - acm:ListCertificates | |
| - acm:DescribeCertificate | |
| - iam:ListServerCertificates | |
| - iam:GetServerCertificate | |
| - waf-regional:GetWebACL | |
| - waf-regional:GetWebACLForResource | |
| - waf-regional:AssociateWebACL | |
| - waf-regional:DisassociateWebACL | |
| - wafv2:GetWebACL | |
| - wafv2:GetWebACLForResource | |
| - wafv2:AssociateWebACL | |
| - wafv2:DisassociateWebACL | |
| - shield:GetSubscriptionState | |
| - shield:DescribeProtection | |
| - shield:CreateProtection | |
| - shield:DeleteProtection | |
| Resource: "*" | |
| - Effect: Allow | |
| Action: | |
| - ec2:AuthorizeSecurityGroupIngress | |
| - ec2:RevokeSecurityGroupIngress | |
| Resource: "*" | |
| - Effect: Allow | |
| Action: | |
| - ec2:CreateSecurityGroup | |
| Resource: "*" | |
| - Effect: Allow | |
| Action: | |
| - ec2:CreateTags | |
| Resource: "arn:aws:ec2:*:*:security-group/*" | |
| Condition: | |
| StringEquals: | |
| ec2:CreateAction: CreateSecurityGroup | |
| "Null": | |
| aws:RequestTag/elbv2.k8s.aws/cluster: "false" | |
| - Effect: Allow | |
| Action: | |
| - ec2:CreateTags | |
| - ec2:DeleteTags | |
| Resource: "arn:aws:ec2:*:*:security-group/*" | |
| Condition: | |
| "Null": | |
| aws:RequestTag/elbv2.k8s.aws/cluster: "true" | |
| aws:ResourceTag/elbv2.k8s.aws/cluster: "false" | |
| - Effect: Allow | |
| Action: | |
| - ec2:AuthorizeSecurityGroupIngress | |
| - ec2:RevokeSecurityGroupIngress | |
| - ec2:DeleteSecurityGroup | |
| Resource: "*" | |
| Condition: | |
| "Null": | |
| aws:ResourceTag/elbv2.k8s.aws/cluster: "false" | |
| - Effect: Allow | |
| Action: | |
| - elasticloadbalancing:CreateLoadBalancer | |
| - elasticloadbalancing:CreateTargetGroup | |
| Resource: "*" | |
| Condition: | |
| "Null": | |
| aws:RequestTag/elbv2.k8s.aws/cluster: "false" | |
| - Effect: Allow | |
| Action: | |
| - elasticloadbalancing:CreateListener | |
| - elasticloadbalancing:DeleteListener | |
| - elasticloadbalancing:CreateRule | |
| - elasticloadbalancing:DeleteRule | |
| Resource: "*" | |
| - Effect: Allow | |
| Action: | |
| - elasticloadbalancing:AddTags | |
| - elasticloadbalancing:RemoveTags | |
| Resource: | |
| - "arn:aws:elasticloadbalancing:*:*:targetgroup/*/*" | |
| - "arn:aws:elasticloadbalancing:*:*:loadbalancer/net/*/*" | |
| - "arn:aws:elasticloadbalancing:*:*:loadbalancer/app/*/*" | |
| Condition: | |
| "Null": | |
| aws:RequestTag/elbv2.k8s.aws/cluster: "true" | |
| aws:ResourceTag/elbv2.k8s.aws/cluster: "false" | |
| - Effect: Allow | |
| Action: | |
| - elasticloadbalancing:AddTags | |
| - elasticloadbalancing:RemoveTags | |
| Resource: | |
| - "arn:aws:elasticloadbalancing:*:*:listener/net/*/*/*" | |
| - "arn:aws:elasticloadbalancing:*:*:listener/app/*/*/*" | |
| - "arn:aws:elasticloadbalancing:*:*:listener-rule/net/*/*/*" | |
| - "arn:aws:elasticloadbalancing:*:*:listener-rule/app/*/*/*" | |
| - Effect: Allow | |
| Action: | |
| - elasticloadbalancing:ModifyLoadBalancerAttributes | |
| - elasticloadbalancing:SetIpAddressType | |
| - elasticloadbalancing:SetSecurityGroups | |
| - elasticloadbalancing:SetSubnets | |
| - elasticloadbalancing:DeleteLoadBalancer | |
| - elasticloadbalancing:ModifyTargetGroup | |
| - elasticloadbalancing:ModifyTargetGroupAttributes | |
| - elasticloadbalancing:DeleteTargetGroup | |
| Resource: "*" | |
| Condition: | |
| "Null": | |
| aws:ResourceTag/elbv2.k8s.aws/cluster: "false" | |
| - Effect: Allow | |
| Action: | |
| - elasticloadbalancing:AddTags | |
| Resource: | |
| - "arn:aws:elasticloadbalancing:*:*:targetgroup/*/*" | |
| - "arn:aws:elasticloadbalancing:*:*:loadbalancer/net/*/*" | |
| - "arn:aws:elasticloadbalancing:*:*:loadbalancer/app/*/*" | |
| Condition: | |
| StringEquals: | |
| ```yaml | |
| Action: | |
| - sts:AssumeRole | |
| - sts:TagSession | |
| Resource: "arn:aws:iam::*:role/rapticore-cross-account-*" | |
| # IAM and EC2 Read-Only (needed by discovery for role enumeration) | |
| - Effect: Allow | |
| Action: | |
| - iam:ListRole* | |
| - iam:GetRole* | |
| - ec2:DescribeRegions | |
| Resource: "*" | |
| # Cognito Identity (needed for Azure workload identity) | |
| - Effect: Allow | |
| Action: | |
| - cognito-identity:GetOpenIdTokenForDeveloperIdentity | |
| Resource: !Sub "arn:aws:cognito-identity:${AWS::Region}:${AWS::AccountId}:identitypool/*" | |
| ##### | |
| # AWS Load Balancer Controller IAM Role (IRSA) | |
| ##### | |
| AwsLoadBalancerControllerRole: | |
| Type: AWS::IAM::Role | |
| DependsOn: OidcProvider | |
| Properties: | |
| RoleName: !Sub "${ClusterName}-aws-load-balancer-controller-role" | |
| AssumeRolePolicyDocument: | |
| Fn::Sub: | |
| - | | |
| { | |
| "Version": "2012-10-17", | |
| "Statement": [{ | |
| "Effect": "Allow", | |
| "Principal": { | |
| "Federated": "arn:aws:iam::${AWS::AccountId}:oidc-provider/${OidcUrl}" | |
| }, | |
| "Action": "sts:AssumeRoleWithWebIdentity", | |
| "Condition": { | |
| "StringEquals": { | |
| "${OidcUrl}:aud": "sts.amazonaws.com", | |
| "${OidcUrl}:sub": "system:serviceaccount:kube-system:aws-load-balancer-controller" | |
| } | |
| } | |
| }] | |
| } | |
| - OidcUrl: !Select [1, !Split ["https://", !GetAtt EksCluster.OpenIdConnectIssuerUrl]] | |
| Policies: | |
| - PolicyName: AWSLoadBalancerControllerPolicy | |
| PolicyDocument: | |
| Version: "2012-10-17" | |
| Statement: | |
| - Effect: Allow | |
| Action: | |
| - iam:CreateServiceLinkedRole | |
| Resource: "*" | |
| Condition: | |
| StringEquals: | |
| iam:AWSServiceName: elasticloadbalancing.amazonaws.com | |
| - Effect: Allow | |
| Action: | |
| - ec2:DescribeAccountAttributes | |
| - ec2:DescribeAddresses | |
| - ec2:DescribeAvailabilityZones | |
| - ec2:DescribeInternetGateways | |
| - ec2:DescribeVpcs | |
| - ec2:DescribeVpcPeeringConnections | |
| - ec2:DescribeSubnets | |
| - ec2:DescribeSecurityGroups | |
| - ec2:DescribeInstances | |
| - ec2:DescribeNetworkInterfaces | |
| - ec2:DescribeTags | |
| - ec2:DescribeRouteTables | |
| - ec2:GetCoipPoolUsage | |
| - ec2:DescribeCoipPools | |
| - elasticloadbalancing:DescribeLoadBalancers | |
| - elasticloadbalancing:DescribeLoadBalancerAttributes | |
| - elasticloadbalancing:DescribeListeners | |
| - elasticloadbalancing:DescribeListenerAttributes | |
| - elasticloadbalancing:DescribeListenerCertificates | |
| - elasticloadbalancing:DescribeSSLPolicies | |
| - elasticloadbalancing:DescribeRules | |
| - elasticloadbalancing:DescribeTargetGroups | |
| - elasticloadbalancing:DescribeTargetGroupAttributes | |
| - elasticloadbalancing:DescribeTargetHealth | |
| - elasticloadbalancing:DescribeTags | |
| Resource: "*" | |
| - Effect: Allow | |
| Action: | |
| - cognito-idp:DescribeUserPoolClient | |
| - acm:ListCertificates | |
| - acm:DescribeCertificate | |
| - iam:ListServerCertificates | |
| - iam:GetServerCertificate | |
| - waf-regional:GetWebACL | |
| - waf-regional:GetWebACLForResource | |
| - wafv2:GetWebACL | |
| - wafv2:GetWebACLForResource | |
| - shield:GetSubscriptionState | |
| - shield:DescribeProtection | |
| Resource: "*" | |
| - Effect: Allow | |
| Action: | |
| - ec2:AuthorizeSecurityGroupIngress | |
| - ec2:RevokeSecurityGroupIngress | |
| Resource: "arn:aws:ec2:*:*:security-group/*" | |
| Condition: | |
| "Null": | |
| aws:ResourceTag/elbv2.k8s.aws/cluster: "false" | |
| - Effect: Allow | |
| Action: | |
| - ec2:CreateSecurityGroup | |
| Resource: "arn:aws:ec2:*:*:security-group/*" | |
| Condition: | |
| StringEquals: | |
| ec2:Vpc: !Sub "arn:aws:ec2:*:${AWS::AccountId}:vpc/*" | |
| - Effect: Allow | |
| Action: | |
| - ec2:CreateTags | |
| Resource: "arn:aws:ec2:*:*:security-group/*" | |
| Condition: | |
| StringEquals: | |
| ec2:CreateAction: CreateSecurityGroup | |
| "Null": | |
| aws:RequestTag/elbv2.k8s.aws/cluster: "false" | |
| - Effect: Allow | |
| Action: | |
| - ec2:CreateTags | |
| - ec2:DeleteTags | |
| Resource: "arn:aws:ec2:*:*:security-group/*" | |
| Condition: | |
| "Null": | |
| aws:RequestTag/elbv2.k8s.aws/cluster: "true" | |
| aws:ResourceTag/elbv2.k8s.aws/cluster: "false" | |
| - Effect: Allow | |
| Action: | |
| - ec2:DeleteSecurityGroup | |
| Resource: "arn:aws:ec2:*:*:security-group/*" | |
| Condition: | |
| "Null": | |
| aws:ResourceTag/elbv2.k8s.aws/cluster: "false" | |
| - Effect: Allow | |
| Action: | |
| - elasticloadbalancing:CreateLoadBalancer | |
| - elasticloadbalancing:CreateTargetGroup | |
| Resource: "*" | |
| Condition: | |
| "Null": | |
| aws:RequestTag/elbv2.k8s.aws/cluster: "false" | |
| - Effect: Allow | |
| Action: | |
| - elasticloadbalancing:CreateListener | |
| - elasticloadbalancing:DeleteListener | |
| - elasticloadbalancing:CreateRule | |
| - elasticloadbalancing:DeleteRule | |
| Resource: "arn:aws:elasticloadbalancing:*:*:listener*/app/*/*" | |
| Condition: | |
| "Null": | |
| aws:ResourceTag/elbv2.k8s.aws/cluster: "false" | |
| - Effect: Allow | |
| Action: | |
| - elasticloadbalancing:AddTags | |
| - elasticloadbalancing:RemoveTags | |
| Resource: | |
| - "arn:aws:elasticloadbalancing:*:*:targetgroup/*/*" | |
| - "arn:aws:elasticloadbalancing:*:*:loadbalancer/net/*/*" | |
| - "arn:aws:elasticloadbalancing:*:*:loadbalancer/app/*/*" | |
| Condition: | |
| "Null": | |
| aws:RequestTag/elbv2.k8s.aws/cluster: "true" | |
| aws:ResourceTag/elbv2.k8s.aws/cluster: "false" | |
| - Effect: Allow | |
| Action: | |
| - elasticloadbalancing:AddTags | |
| - elasticloadbalancing:RemoveTags | |
| Resource: | |
| - "arn:aws:elasticloadbalancing:*:*:listener/net/*/*/*" | |
| - "arn:aws:elasticloadbalancing:*:*:listener/app/*/*/*" | |
| - "arn:aws:elasticloadbalancing:*:*:listener-rule/net/*/*/*" | |
| - "arn:aws:elasticloadbalancing:*:*:listener-rule/app/*/*/*" | |
| Condition: | |
| "Null": | |
| aws:ResourceTag/elbv2.k8s.aws/cluster: "false" | |
| - Effect: Allow | |
| Action: | |
| - elasticloadbalancing:ModifyLoadBalancerAttributes | |
| - elasticloadbalancing:SetIpAddressType | |
| - elasticloadbalancing:SetSecurityGroups | |
| - elasticloadbalancing:SetSubnets | |
| - elasticloadbalancing:DeleteLoadBalancer | |
| - elasticloadbalancing:ModifyTargetGroup | |
| - elasticloadbalancing:ModifyTargetGroupAttributes | |
| - elasticloadbalancing:DeleteTargetGroup | |
| Resource: "*" | |
| Condition: | |
| "Null": | |
| aws:ResourceTag/elbv2.k8s.aws/cluster: "false" | |
| - Effect: Allow | |
| Action: | |
| - elasticloadbalancing:AddTags | |
| Resource: |
🤖 Generated by Rapticore
Rapticore Security Findings (Part 1)
This is a draft PR containing automated security fix recommendations from Rapticore.
How to use this PR:
🤖 Generated by Rapticore