kubernetes/kops · error
error building IAM policy: %v
Error message
error building IAM policy: %v
What it means
PolicyResource.Open wraps any error from pb.BuildAWSPolicy() (the role-level IAM policy builder) as 'error building IAM policy'. This is the outer wrapper for the whole S3/VFS/KMS policy assembly chain described by errors 1350-1356; the inner cause carries the specifics.
Source
Thrown at pkg/model/iam/iam_builder.go:796
hostedZoneID := fi.ValueOf(b.DNSZone.ZoneID)
if hostedZoneID == "" {
// ZoneID is normally populated by DNSZone.Find before this runs. In dry-run modes that
// skip Find (e.g. `kops get assets`), it may still be empty; fall back to the DNS name
// so the policy renders. The resulting ARN is not a valid Route53 ARN, but the policy
// is not applied in that mode.
hostedZoneID = fi.ValueOf(b.DNSZone.DNSName)
klog.V(4).Infof("Falling back to DNS name %q for IAM policy because ZoneID is empty", hostedZoneID)
}
if hostedZoneID == "" {
// Dependency analysis failure?
return nil, fmt.Errorf("DNS ZoneID not set")
}
pb.HostedZoneID = hostedZoneID
}
policy, err := pb.BuildAWSPolicy()
if err != nil {
return nil, fmt.Errorf("error building IAM policy: %v", err)
}
if policy == nil {
return bytes.NewReader([]byte{}), nil
}
j, err := policy.AsJSON()
if err != nil {
return nil, fmt.Errorf("error building IAM policy: %v", err)
}
return bytes.NewReader([]byte(j)), nil
}
func addECRPermissions(p *Policy) {
// TODO - I think we can just have GetAuthorizationToken here, as we are not
// TODO - making any API calls except for GetAuthorizationToken.
// We provide ECR access on the nodes (naturally), but we also provide access on the master.
// We shouldn't be running lots of pods on the master, but it is perfectly reasonable to run
// a private logging pod or similar.View on GitHub (pinned to 4c8573c808)
Solutions
- Read the chained inner error (%v suffix) for the root cause; it will name the failing path or role.
- Fix the underlying state store / backupStore / DNS configuration as indicated by that cause.
- Validate the whole spec with `kops get cluster -o yaml` and `kops validate cluster` after edits.
- Rerun `kops update cluster` to regenerate the IAM policies.
Defensive patterns
Strategy: try-catch
Validate before calling
// Validate store and zone inputs before Open
if _, err := vfs.Context.BuildVfsPath(cluster.Spec.ConfigStore.Base); err != nil {
return fmt.Errorf("invalid state store: %w", err)
} Try / catch
r, err := policyResource.Open()
if err != nil {
var inner = err.Error()
switch {
case strings.Contains(inner, "cannot parse VFS path"):
// fix state store/backupStore URL
case strings.Contains(inner, "not cluster readable"):
// switch to s3:// storage
}
return fmt.Errorf("open IAM policy resource: %w", err)
} Prevention
- Always log the full wrapped error chain (use %w / errors.Unwrap)
- Validate state store, backupStore and DNS zone before updates
- Keep kOps and cluster spec versions in sync
When it happens
Trigger: Any role policy build failure during PolicyResource.Open: NodeRoleAPIServer/Master BuildAWSPolicy returning S3 permission errors, VFS parse failures, unreadable paths, or unsupported writeable path types — all bubbled through PolicyBuilder.BuildAWSPolicy.
Common situations: Invalid state store or etcd backupStore URLs (see 1353-1356); cross-cloud state stores used with AWS IAM generation; corrupted cluster spec after manual edits; kOps version mismatch with the cluster spec format.
Related errors
- failed to generate AWS IAM Policy: %v
- failed to generate AWS IAM S3 access statements: %v
- unknown writeable path, can't apply IAM policy: %q
- error getting IAMInstanceProfile: %v
- error creating IAMInstanceProfileRole: %v
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/c613767d1bfec385.
Report an issue: GitHub.