{"record":{"id":"75268c0e6d94b3a4","repo":"kubernetes/kops","slug":"error-describing-securitygroup-rules-q-v","errorCode":null,"errorMessage":"error describing SecurityGroup rules %q: %v","messagePattern":"error describing SecurityGroup rules %q: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/resources/aws/securitygroup.go","lineNumber":71,"sourceCode":"\t\tif len(response.SecurityGroups) == 0 {\n\t\t\treturn nil\n\t\t}\n\t\tif len(response.SecurityGroups) != 1 {\n\t\t\treturn fmt.Errorf(\"found multiple SecurityGroups with ID %q\", id)\n\t\t}\n\n\t\truleReqest := &ec2.DescribeSecurityGroupRulesInput{\n\t\t\tFilters: []ec2types.Filter{\n\t\t\t\t{Name: aws.String(\"group-id\"), Values: []string{id}},\n\t\t\t},\n\t\t}\n\t\truleResp, err := c.EC2().DescribeSecurityGroupRules(ctx, ruleReqest)\n\t\tif err != nil {\n\t\t\tif awsup.AWSErrorCode(err) == \"InvalidGroup.NotFound\" {\n\t\t\t\tklog.V(2).Infof(\"Got InvalidGroup.NotFound error describing rules for SecurityGroup %q; will treat as already-deleted\", id)\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\treturn fmt.Errorf(\"error describing SecurityGroup rules %q: %v\", id, err)\n\t\t}\n\n\t\tingressRuleIDs := make([]string, 0)\n\t\tfor _, rule := range ruleResp.SecurityGroupRules {\n\t\t\tif !aws.ToBool(rule.IsEgress) {\n\t\t\t\tingressRuleIDs = append(ingressRuleIDs, aws.ToString(rule.SecurityGroupRuleId))\n\t\t\t}\n\t\t}\n\n\t\tif len(ingressRuleIDs) != 0 {\n\t\t\trevoke := &ec2.RevokeSecurityGroupIngressInput{\n\t\t\t\tGroupId:              aws.String(id),\n\t\t\t\tSecurityGroupRuleIds: ingressRuleIDs,\n\t\t\t}\n\t\t\t_, err = c.EC2().RevokeSecurityGroupIngress(ctx, revoke)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"cannot revoke ingress for ID %q with rule IDs %v: %v\", id, ingressRuleIDs, err)\n\t\t\t}","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/resources/aws/securitygroup.go#L53-L89","documentation":"In DeleteSecurityGroup (pkg/resources/aws/securitygroup.go:71), the code calls EC2 DescribeSecurityGroupRules filtered by group-id to enumerate ingress rules before revoking them. This error wraps any failure other than InvalidGroup.NotFound (treated as already-deleted). It means rule enumeration failed so the SG cannot be safely emptied prior to deletion.","triggerScenarios":"ec2.DescribeSecurityGroupRules returning UnauthorizedOperation (missing ec2:DescribeSecurityGroupRules — a separate permission from DescribeSecurityGroups), InvalidGroup.NotFound shapes not matched, throttling, pagination-heavy responses timing out, or network errors.","commonSituations":"IAM policies written before the DescribeSecurityGroupRules API existed (rules API added 2021) lacking the new permission; SCC policies granting only legacy SG permissions; deleting SGs with hundreds of rules triggering throttling.","solutions":["Add ec2:DescribeSecurityGroupRules to the IAM policy (distinct from ec2:DescribeSecurityGroups).","Retry on throttling with backoff.","Verify the SG still exists / region matches; if already deleted the InvalidGroup.NotFound path handles it.","Upgrade to a recent AWS SDK v2 release if the error is an unrecognized API shape."],"exampleFix":"// before\nreturn fmt.Errorf(\"error describing SecurityGroup rules %q: %v\", id, err)\n// after\nreturn fmt.Errorf(\"error describing SecurityGroup rules %q: %w (check ec2:DescribeSecurityGroupRules IAM permission)\", id, err)","handlingStrategy":"validation","validationCode":"// preflight IAM check via IAM policy simulator or dry attempt\n_, err := ec2Client.DescribeSecurityGroupRules(ctx, &ec2.DescribeSecurityGroupRulesInput{\n    Filters: []ec2types.Filter{{Name: aws.String(\"group-id\"), Values: []string{\"sg-00000000000000000\"}}},\n})\n// AccessDenied => ec2:DescribeSecurityGroupRules missing","typeGuard":"func isAccessDenied(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"UnauthorizedOperation\") || err != nil && strings.Contains(err.Error(), \"AccessDenied\")\n}","tryCatchPattern":"ruleResp, err := ec2Client.DescribeSecurityGroupRules(ctx, req)\nif err != nil {\n    if awsup.AWSErrorCode(err) == \"InvalidGroup.NotFound\" { return nil }\n    if isAccessDenied(err) {\n        return fmt.Errorf(\"missing ec2:DescribeSecurityGroupRules IAM permission: %w\", err)\n    }\n    return err\n}","preventionTips":["Add ec2:DescribeSecurityGroupRules to IAM policies (post-2021 API, often missed).","Run the IAM policy simulator for delete-cluster automation roles.","Keep AWS SDK v2 updated so rule-API shapes are recognized.","Handle InvalidGroup.NotFound as success for idempotent cleanup."],"tags":["aws","ec2","security-group","iam"],"backgroundTag":"missing-iam-permission","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}