Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Backend/proxy/kiro.go
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,15 @@ func CallKiroAPI(account *config.Account, payload *KiroPayload, callback *KiroSt
accountEmail = account.Email
}
logger.Warnf("[ProfileArn] Failed to resolve profile ARN for %s: %v", accountEmail, err)
// Builder-ID/OIDC accounts: ListAvailableProfiles can return
// AccessDeniedException when the token lacks control-plane scopes.
// Inject the kiro-cli fallback ARN (baked into the binary at
// crates/fig_api_client/src/profile_resolver.rs) so the data-plane
// request succeeds. AWS accepts this ARN for Builder-ID accounts.
if fallbackArn := fallbackProfileArn(account); fallbackArn != "" {
payload.ProfileArn = fallbackArn
logger.Infof("[ProfileArn] Injected fallback ARN for %s", accountEmail)
}
}
}

Expand Down
41 changes: 41 additions & 0 deletions Backend/proxy/kiro_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,47 @@ func ListAvailableModels(account *config.Account) ([]ModelInfo, error) {
return result.Models, nil
}


// fallbackProfileArn returns the kiro-cli hardcoded fallback profile ARN for a
// Builder-ID/OIDC account. This ARN is baked into the kiro binary (see
// crates/fig_api_client/src/profile_resolver.rs) and is accepted by the
// CodeWhisperer control- and data-plane. It is used when ListAvailableProfiles
// fails with AccessDeniedException (token lacks control-plane scopes).
//
// Format: arn:aws:codewhisperer:{region}:638616132270:profile/AAAACCCCXXXX
func fallbackProfileArn(account *config.Account) string {
if account == nil {
return ""
}
region := strings.TrimSpace(account.Region)
if region == "" {
region = "us-east-1"
}
// Validate region format to avoid URL injection
if !isValidRegion(region) {
return ""
}
return "arn:aws:codewhisperer:" + region + ":638616132270:profile/AAAACCCCXXXX"
}

// isValidRegion checks that a region string matches the expected AWS region
// pattern (e.g. us-east-1, eu-central-1).
func isValidRegion(region string) bool {
if region == "" {
return false
}
parts := strings.Split(region, "-")
if len(parts) < 3 {
return false
}
for _, p := range parts {
if len(p) == 0 {
return false
}
}
return true
}

func ResolveProfileArn(account *config.Account) (string, error) {
if account == nil {
return "", fmt.Errorf("account is nil")
Expand Down