/ utils / aws.ts
aws.ts
 1  import { logForDebugging } from './debug.js'
 2  
 3  /** AWS short-term credentials format. */
 4  export type AwsCredentials = {
 5    AccessKeyId: string
 6    SecretAccessKey: string
 7    SessionToken: string
 8    Expiration?: string
 9  }
10  
11  /** Output from `aws sts get-session-token` or `aws sts assume-role`. */
12  export type AwsStsOutput = {
13    Credentials: AwsCredentials
14  }
15  
16  type AwsError = {
17    name: string
18  }
19  
20  export function isAwsCredentialsProviderError(err: unknown) {
21    return (err as AwsError | undefined)?.name === 'CredentialsProviderError'
22  }
23  
24  /** Typeguard to validate AWS STS assume-role output */
25  export function isValidAwsStsOutput(obj: unknown): obj is AwsStsOutput {
26    if (!obj || typeof obj !== 'object') {
27      return false
28    }
29  
30    const output = obj as Record<string, unknown>
31  
32    // Check if Credentials exists and has required fields
33    if (!output.Credentials || typeof output.Credentials !== 'object') {
34      return false
35    }
36  
37    const credentials = output.Credentials as Record<string, unknown>
38  
39    return (
40      typeof credentials.AccessKeyId === 'string' &&
41      typeof credentials.SecretAccessKey === 'string' &&
42      typeof credentials.SessionToken === 'string' &&
43      credentials.AccessKeyId.length > 0 &&
44      credentials.SecretAccessKey.length > 0 &&
45      credentials.SessionToken.length > 0
46    )
47  }
48  
49  /** Throws if STS caller identity cannot be retrieved. */
50  export async function checkStsCallerIdentity(): Promise<void> {
51    const { STSClient, GetCallerIdentityCommand } = await import(
52      '@aws-sdk/client-sts'
53    )
54    await new STSClient().send(new GetCallerIdentityCommand({}))
55  }
56  
57  /**
58   * Clear AWS credential provider cache by forcing a refresh
59   * This ensures that any changes to ~/.aws/credentials are picked up immediately
60   */
61  export async function clearAwsIniCache(): Promise<void> {
62    try {
63      logForDebugging('Clearing AWS credential provider cache')
64      const { fromIni } = await import('@aws-sdk/credential-providers')
65      const iniProvider = fromIni({ ignoreCache: true })
66      await iniProvider() // This updates the global file cache
67      logForDebugging('AWS credential provider cache refreshed')
68    } catch (_error) {
69      // Ignore errors - we're just clearing the cache
70      logForDebugging(
71        'Failed to clear AWS credential cache (this is expected if no credentials are configured)',
72      )
73    }
74  }