import { GaxiosOptions } from 'gaxios' ; import * as fs from 'fs' ; import { promisify } from 'util' ; import { BaseExternalAccountClient , BaseExternalAccountClientOptions , } from './baseexternalclient' ; import { RefreshOptions } from './oauth2client' ; const readFile = promisify ( fs . readFile ?? ( ( ) => { } ) ) ; const realpath = promisify ( fs . realpath ?? ( ( ) => { } ) ) ; const lstat = promisify ( fs . lstat ?? ( ( ) => { } ) ) ; type SubjectTokenFormatType = 'json' | 'text' ; interface SubjectTokenJsonResponse { [ key ] : string ; } /**
 * Url-sourced/file-sourced credentials json interface.
 * This is used for K8s and Azure workloads.
 */ export interface IdentityPoolClientOptions extends BaseExternalAccountClientOptions { credential_source : { file ? : string ; url ? : string ; headers ? : { [ key ] : string ; } ; format ? : { type : SubjectTokenFormatType ; subject_token_field_name ? : string ; } ; } ; } /**
 * Defines the Url-sourced and file-sourced external account clients mainly
 * used for K8s and Azure workloads.
 */ export class IdentityPoolClient extends BaseExternalAccountClient { private readonly file ? : string ; private readonly url ? : string ; private readonly headers ? : { [ key ] : string ; } ; private readonly formatType : SubjectTokenFormatType ; private readonly formatSubjectTokenFieldName ? : string ; param options param additionalOptions constructor ( options , additionalOptions ? ) { super ( options , additionalOptions ) ; this . file = options . credential_source . file ; this . url = options . credential_source . url ; this . headers = options . credential_source . headers ; if ( ! this . file && ! this . url ) { throw new Error ( 'No valid Identity Pool "credential_source" provided' ) ; } this . formatType = options . credential_source . format ?. type || 'text' ; this . formatSubjectTokenFieldName = options . credential_source . format ?. subject_token_field_name ; if ( this . formatType !== 'json' && this . formatType !== 'text' ) { throw new Error ( `Invalid credential_source format "${ this . formatType }"` ) ; } if ( this . formatType === 'json' && ! this . formatSubjectTokenFieldName ) { throw new Error ( 'Missing subject_token_field_name for JSON credential_source format' ) ; } } return async retrieveSubjectToken ( ) { if ( this . file ) { return await this . getTokenFromFile ( this . file ! , this . formatType , this . formatSubjectTokenFieldName ) ; } return await this . getTokenFromUrl ( this . url ! , this . formatType , this . formatSubjectTokenFieldName , this . headers ) ; } param file param formatType param formatSubjectTokenFieldName return private async getTokenFromFile ( filePath , formatType , formatSubjectTokenFieldName ? ) { try { filePath = await realpath ( filePath ) ; if ( ! ( await lstat ( filePath ) ) . isFile ( ) ) { throw new Error ( ) ; } } catch ( err ) { err . message = `The file at ${ filePath } does not exist, or it is not a file. ${ err . message }` ; throw err ; } let subjectToken ; const rawText = await readFile ( filePath , { encoding : 'utf8' } ) ; if ( formatType === 'text' ) { subjectToken = rawText ; } else if ( formatType === 'json' && formatSubjectTokenFieldName ) { const json = JSON . parse ( rawText ) as SubjectTokenJsonResponse ; subjectToken = json [ formatSubjectTokenFieldName ] ; } if ( ! subjectToken ) { throw new Error ( 'Unable to parse the subject_token from the credential_source file' ) ; } return subjectToken ; } param url param formatType param formatSubjectTokenFieldName param headers return private async getTokenFromUrl ( url , formatType , formatSubjectTokenFieldName ? , headers ? ) { const opts = { url , method : 'GET' , headers , responseType : formatType , } ; let subjectToken ; if ( formatType === 'text' ) { const response = await this . transporter . request < string > ( opts ) ; subjectToken = response . data ; } else if ( formatType === 'json' && formatSubjectTokenFieldName ) { const response = await this . transporter . request < SubjectTokenJsonResponse > ( opts ) ; subjectToken = response . data [ formatSubjectTokenFieldName ] ; } if ( ! subjectToken ) { throw new Error ( 'Unable to parse the subject_token from the credential_source URL' ) ; } return subjectToken ; } }