kubernetes/kops · error

building presigned request: %w

Error message

building presigned request: %w

What it means

buildSTSRequestValidator constructs a reference presigned GetCallerIdentity URL using the AWS SDK's PresignClient, primarily to learn the expected STS hostname for later token validation. The 'building presigned request: %w' error means PresignGetCallerIdentity failed — typically because the STS client has no usable credentials to sign with, its region/endpoint configuration is invalid, or the SDK could not resolve the endpoint.

Source

Thrown at pkg/bootstrap/awsbootstrap/verifier.go:481

	if response.StatusCode != 200 {
		return nil, fmt.Errorf("received status code %d from STS: %s", response.StatusCode, string(responseBody))
	}

	callerIdentity := &GetCallerIdentityResponse{}
	err = xml.NewDecoder(bytes.NewReader(responseBody)).Decode(callerIdentity)
	if err != nil {
		return nil, fmt.Errorf("decoding STS response: %v", err)
	}

	return callerIdentity, nil
}

// buildSTSRequestValidator determines the form of a valid STS presigned URL.
func buildSTSRequestValidator(ctx context.Context, stsClient *sts.Client) (*stsRequestValidator, error) {
	// We build a presigned token ourselves, primarily to get the expected hostname for the endpoint.
	signed, err := sts.NewPresignClient(stsClient).PresignGetCallerIdentity(ctx, &sts.GetCallerIdentityInput{})
	if err != nil {
		return nil, fmt.Errorf("building presigned request: %w", err)
	}
	u, err := url.Parse(signed.URL)
	if err != nil {
		return nil, fmt.Errorf("parsing presigned url: %w", err)
	}
	return &stsRequestValidator{Host: u.Host}, nil
}

// GetInstanceCertificateNames returns the instance names and addresses that should go into
// certificates: the instance ID, the private DNS name and the IP addresses.
func GetInstanceCertificateNames(instances *ec2.DescribeInstancesOutput) (addrs []string, err error) {
	if len(instances.Reservations) != 1 {
		return nil, fmt.Errorf("too many reservations returned for the single instance-id")
	}

	if len(instances.Reservations[0].Instances) != 1 {
		return nil, fmt.Errorf("too many instances returned for the single instance-id")
	}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Export AWS_REGION (or AWS_DEFAULT_REGION) so the STS client resolves an endpoint; outside AWS use e.g. us-east-1 or your cluster's region.
  2. Provide signing credentials via env (AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY), the shared credentials file, or an attached IAM role — presigning requires some credential even though the URL is presigned.
  3. Run aws sts get-caller-identity with the same environment to confirm credentials and region resolve.
  4. Check for expired session credentials and refresh them (aws sso login, new assume-role, or updated credential file).
  5. Verify the region string is valid and supported; an invalid region breaks endpoint resolution in the SDK.

Example fix

// before: STS client built with no region, presign fails
stsClient := sts.NewFromConfig(aws.Config{})
verifier, err := NewAWSVerifier(ctx, stsClient, ...)
// after: explicit region so presigning can resolve the endpoint
cfg, err := config.LoadDefaultConfig(ctx, config.WithRegion("us-east-1"))
if err != nil { return err }
stsClient := sts.NewFromConfig(cfg)
verifier, err := NewAWSVerifier(ctx, stsClient, ...)
Defensive patterns

Strategy: validation

Validate before calling

// Validate region + credential presence before constructing the verifier
cfg, err := config.LoadDefaultConfig(ctx)
if err != nil {
    return fmt.Errorf("aws config unavailable: %w", err)
}
if cfg.Region == "" {
    return errors.New("AWS region not set: set AWS_REGION or pass config.WithRegion(...)")
}
creds, err := cfg.Credentials.Retrieve(ctx)
if err != nil || !creds.HasKeys() {
    return errors.New("AWS credentials not found: set env vars, shared credentials file, or IAM role")
}
stsClient := sts.NewFromConfig(cfg)

Type guard

func isPresignConfigError(err error) bool {
    if err == nil { return false }
    msg := err.Error()
    return strings.Contains(msg, "building presigned request") &&
        (strings.Contains(msg, "no credential") || strings.Contains(msg, "region") || strings.Contains(msg, "endpoint"))
}

Try / catch

verifier, err := NewAWSVerifier(ctx, stsClient, ...)
if err != nil {
    if isPresignConfigError(err) {
        return fmt.Errorf("verifier setup needs valid AWS region and credentials: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Called from NewAWSVerifier (verifier construction) and tests when sts.NewPresignClient(stsClient).PresignGetCallerIdentity returns an error: missing/empty AWS credentials in the signing chain, no region set on the STS client config, invalid region name, or credential-provider errors (e.g. expired static keys, unreadable credential files).

Common situations: Environment lacks AWS_REGION/AWS_DEFAULT_REGION where no region can be inferred (e.g. running kOps control plane off-cluster); shared credentials file or env vars absent/misnamed; expired AWS_SESSION_TOKEN with static keys; typo'd region causing endpoint resolution failure; test fixtures constructing a verifier without valid-looking credentials.

Related errors


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