kubernetes/kops · error

error describing SecurityGroup rules %q: %v

Error message

error describing SecurityGroup rules %q: %v

What it means

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.

Source

Thrown at pkg/resources/aws/securitygroup.go:71

		if len(response.SecurityGroups) == 0 {
			return nil
		}
		if len(response.SecurityGroups) != 1 {
			return fmt.Errorf("found multiple SecurityGroups with ID %q", id)
		}

		ruleReqest := &ec2.DescribeSecurityGroupRulesInput{
			Filters: []ec2types.Filter{
				{Name: aws.String("group-id"), Values: []string{id}},
			},
		}
		ruleResp, err := c.EC2().DescribeSecurityGroupRules(ctx, ruleReqest)
		if err != nil {
			if awsup.AWSErrorCode(err) == "InvalidGroup.NotFound" {
				klog.V(2).Infof("Got InvalidGroup.NotFound error describing rules for SecurityGroup %q; will treat as already-deleted", id)
				return nil
			}
			return fmt.Errorf("error describing SecurityGroup rules %q: %v", id, err)
		}

		ingressRuleIDs := make([]string, 0)
		for _, rule := range ruleResp.SecurityGroupRules {
			if !aws.ToBool(rule.IsEgress) {
				ingressRuleIDs = append(ingressRuleIDs, aws.ToString(rule.SecurityGroupRuleId))
			}
		}

		if len(ingressRuleIDs) != 0 {
			revoke := &ec2.RevokeSecurityGroupIngressInput{
				GroupId:              aws.String(id),
				SecurityGroupRuleIds: ingressRuleIDs,
			}
			_, err = c.EC2().RevokeSecurityGroupIngress(ctx, revoke)
			if err != nil {
				return fmt.Errorf("cannot revoke ingress for ID %q with rule IDs %v: %v", id, ingressRuleIDs, err)
			}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Add ec2:DescribeSecurityGroupRules to the IAM policy (distinct from ec2:DescribeSecurityGroups).
  2. Retry on throttling with backoff.
  3. Verify the SG still exists / region matches; if already deleted the InvalidGroup.NotFound path handles it.
  4. Upgrade to a recent AWS SDK v2 release if the error is an unrecognized API shape.

Example fix

// before
return fmt.Errorf("error describing SecurityGroup rules %q: %v", id, err)
// after
return fmt.Errorf("error describing SecurityGroup rules %q: %w (check ec2:DescribeSecurityGroupRules IAM permission)", id, err)
Defensive patterns

Strategy: validation

Validate before calling

// preflight IAM check via IAM policy simulator or dry attempt
_, err := ec2Client.DescribeSecurityGroupRules(ctx, &ec2.DescribeSecurityGroupRulesInput{
    Filters: []ec2types.Filter{{Name: aws.String("group-id"), Values: []string{"sg-00000000000000000"}}},
})
// AccessDenied => ec2:DescribeSecurityGroupRules missing

Type guard

func isAccessDenied(err error) bool {
    return err != nil && strings.Contains(err.Error(), "UnauthorizedOperation") || err != nil && strings.Contains(err.Error(), "AccessDenied")
}

Try / catch

ruleResp, err := ec2Client.DescribeSecurityGroupRules(ctx, req)
if err != nil {
    if awsup.AWSErrorCode(err) == "InvalidGroup.NotFound" { return nil }
    if isAccessDenied(err) {
        return fmt.Errorf("missing ec2:DescribeSecurityGroupRules IAM permission: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/75268c0e6d94b3a4. Report an issue: GitHub.