Socket
Socket
Sign inDemoInstall

google-auth-library

Package Overview
Dependencies
25
Maintainers
1
Versions
144
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 9.8.0 to 9.9.0

build/src/auth/defaultawssecuritycredentialssupplier.d.ts

132

build/src/auth/awsclient.d.ts

@@ -1,3 +0,5 @@

import { BaseExternalAccountClient, BaseExternalAccountClientOptions } from './baseexternalclient';
import { AwsSecurityCredentials } from './awsrequestsigner';
import { BaseExternalAccountClient, BaseExternalAccountClientOptions, ExternalAccountSupplierContext } from './baseexternalclient';
import { AuthClientOptions } from './authclient';
import { SnakeToCamelObject } from '../util';
/**

@@ -7,11 +9,72 @@ * AWS credentials JSON interface. This is used for AWS workloads.

export interface AwsClientOptions extends BaseExternalAccountClientOptions {
credential_source: {
/**
* Object containing options to retrieve AWS security credentials. A valid credential
* source or a aws security credentials supplier should be specified.
*/
credential_source?: {
/**
* AWS environment ID. Currently only 'AWS1' is supported.
*/
environment_id: string;
/**
* The EC2 metadata URL to retrieve the current AWS region from. If this is
* not provided, the region should be present in the AWS_REGION or AWS_DEFAULT_REGION
* environment variables.
*/
region_url?: string;
/**
* The EC2 metadata URL to retrieve AWS security credentials. If this is not provided,
* the credentials should be present in the AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY,
* and AWS_SESSION_TOKEN environment variables.
*/
url?: string;
/**
* The regional GetCallerIdentity action URL, used to determine the account
* ID and its roles.
*/
regional_cred_verification_url: string;
/**
* The imdsv2 session token url is used to fetch session token from AWS
* which is later sent through headers for metadata requests. If the
* field is missing, then session token won't be fetched and sent with
* the metadata requests.
* The session token is required for IMDSv2 but optional for IMDSv1
*/
imdsv2_session_token_url?: string;
};
/**
* The AWS security credentials supplier to call to retrieve the AWS region
* and AWS security credentials. Either this or a valid credential source
* must be specified.
*/
aws_security_credentials_supplier?: AwsSecurityCredentialsSupplier;
}
/**
* Supplier interface for AWS security credentials. This can be implemented to
* return an AWS region and AWS security credentials. These credentials can
* then be exchanged for a GCP token by an {@link AwsClient}.
*/
export interface AwsSecurityCredentialsSupplier {
/**
* Gets the active AWS region.
* @param context {@link ExternalAccountSupplierContext} from the calling
* {@link AwsClient}, contains the requested audience and subject token type
* for the external account identity as well as the transport from the
* calling client to use for requests.
* @return A promise that resolves with the AWS region string.
*/
getAwsRegion: (context: ExternalAccountSupplierContext) => Promise<string>;
/**
* Gets valid AWS security credentials for the requested external account
* identity. Note that these are not cached by the calling {@link AwsClient},
* so caching should be including in the implementation.
* @param context {@link ExternalAccountSupplierContext} from the calling
* {@link AwsClient}, contains the requested audience and subject token type
* for the external account identity as well as the transport from the
* calling client to use for requests.
* @return A promise that resolves with the requested {@link AwsSecurityCredentials}.
*/
getAwsSecurityCredentials: (context: ExternalAccountSupplierContext) => Promise<AwsSecurityCredentials>;
}
/**
* AWS external account client. This is used for AWS workloads, where

@@ -22,10 +85,15 @@ * AWS STS GetCallerIdentity serialized signed requests are exchanged for

export declare class AwsClient extends BaseExternalAccountClient {
private readonly environmentId;
private readonly regionUrl?;
private readonly securityCredentialsUrl?;
#private;
private readonly environmentId?;
private readonly awsSecurityCredentialsSupplier;
private readonly regionalCredVerificationUrl;
private readonly imdsV2SessionTokenUrl?;
private awsRequestSigner;
private region;
/**
* @deprecated AWS client no validates the EC2 metadata address.
**/
static AWS_EC2_METADATA_IPV4_ADDRESS: string;
/**
* @deprecated AWS client no validates the EC2 metadata address.
**/
static AWS_EC2_METADATA_IPV6_ADDRESS: string;

@@ -43,55 +111,13 @@ /**

*/
constructor(options: AwsClientOptions, additionalOptions?: AuthClientOptions);
constructor(options: AwsClientOptions | SnakeToCamelObject<AwsClientOptions>, additionalOptions?: AuthClientOptions);
private validateEnvironmentId;
/**
* Triggered when an external subject token is needed to be exchanged for a
* GCP access token via GCP STS endpoint.
* This uses the `options.credential_source` object to figure out how
* to retrieve the token using the current environment. In this case,
* this uses a serialized AWS signed request to the STS GetCallerIdentity
* endpoint.
* The logic is summarized as:
* 1. If imdsv2_session_token_url is provided in the credential source, then
* fetch the aws session token and include it in the headers of the
* metadata requests. This is a requirement for IDMSv2 but optional
* for IDMSv1.
* 2. Retrieve AWS region from availability-zone.
* 3a. Check AWS credentials in environment variables. If not found, get
* from security-credentials endpoint.
* 3b. Get AWS credentials from security-credentials endpoint. In order
* to retrieve this, the AWS role needs to be determined by calling
* security-credentials endpoint without any argument. Then the
* credentials can be retrieved via: security-credentials/role_name
* 4. Generate the signed request to AWS STS GetCallerIdentity action.
* 5. Inject x-goog-cloud-target-resource into header and serialize the
* signed request. This will be the subject-token to pass to GCP STS.
* GCP access token via GCP STS endpoint. This will call the
* {@link AwsSecurityCredentialsSupplier} to retrieve an AWS region and AWS
* Security Credentials, then use them to create a signed AWS STS request that
* can be exchanged for a GCP access token.
* @return A promise that resolves with the external subject token.
*/
retrieveSubjectToken(): Promise<string>;
/**
* @return A promise that resolves with the IMDSv2 Session Token.
*/
private getImdsV2SessionToken;
/**
* @param headers The headers to be used in the metadata request.
* @return A promise that resolves with the current AWS region.
*/
private getAwsRegion;
/**
* @param headers The headers to be used in the metadata request.
* @return A promise that resolves with the assigned role to the current
* AWS VM. This is needed for calling the security-credentials endpoint.
*/
private getAwsRoleName;
/**
* Retrieves the temporary AWS credentials by calling the security-credentials
* endpoint as specified in the `credential_source` object.
* @param roleName The role attached to the current VM.
* @param headers The headers to be used in the metadata request.
* @return A promise that resolves with the temporary AWS credentials
* needed for creating the GetCallerIdentity signed request.
*/
private getAwsSecurityCredentials;
private get regionFromEnv();
private get securityCredentialsFromEnv();
}

@@ -15,2 +15,8 @@ "use strict";

// limitations under the License.
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var _a, _AwsClient_DEFAULT_AWS_REGIONAL_CREDENTIAL_VERIFICATION_URL;
Object.defineProperty(exports, "__esModule", { value: true });

@@ -20,2 +26,4 @@ exports.AwsClient = void 0;

const baseexternalclient_1 = require("./baseexternalclient");
const defaultawssecuritycredentialssupplier_1 = require("./defaultawssecuritycredentialssupplier");
const util_1 = require("../util");
/**

@@ -40,22 +48,45 @@ * AWS external account client. This is used for AWS workloads, where

super(options, additionalOptions);
this.environmentId = options.credential_source.environment_id;
// This is only required if the AWS region is not available in the
// AWS_REGION or AWS_DEFAULT_REGION environment variables.
this.regionUrl = options.credential_source.region_url;
// This is only required if AWS security credentials are not available in
// environment variables.
this.securityCredentialsUrl = options.credential_source.url;
this.regionalCredVerificationUrl =
options.credential_source.regional_cred_verification_url;
this.imdsV2SessionTokenUrl =
options.credential_source.imdsv2_session_token_url;
const opts = (0, util_1.originalOrCamelOptions)(options);
const credentialSource = opts.get('credential_source');
const awsSecurityCredentialsSupplier = opts.get('aws_security_credentials_supplier');
// Validate credential sourcing configuration.
if (!credentialSource && !awsSecurityCredentialsSupplier) {
throw new Error('A credential source or AWS security credentials supplier must be specified.');
}
if (credentialSource && awsSecurityCredentialsSupplier) {
throw new Error('Only one of credential source or AWS security credentials supplier can be specified.');
}
if (awsSecurityCredentialsSupplier) {
this.awsSecurityCredentialsSupplier = awsSecurityCredentialsSupplier;
this.regionalCredVerificationUrl =
__classPrivateFieldGet(_a, _a, "f", _AwsClient_DEFAULT_AWS_REGIONAL_CREDENTIAL_VERIFICATION_URL);
this.credentialSourceType = 'programmatic';
}
else {
const credentialSourceOpts = (0, util_1.originalOrCamelOptions)(credentialSource);
this.environmentId = credentialSourceOpts.get('environment_id');
// This is only required if the AWS region is not available in the
// AWS_REGION or AWS_DEFAULT_REGION environment variables.
const regionUrl = credentialSourceOpts.get('region_url');
// This is only required if AWS security credentials are not available in
// environment variables.
const securityCredentialsUrl = credentialSourceOpts.get('url');
const imdsV2SessionTokenUrl = credentialSourceOpts.get('imdsv2_session_token_url');
this.awsSecurityCredentialsSupplier =
new defaultawssecuritycredentialssupplier_1.DefaultAwsSecurityCredentialsSupplier({
regionUrl: regionUrl,
securityCredentialsUrl: securityCredentialsUrl,
imdsV2SessionTokenUrl: imdsV2SessionTokenUrl,
});
this.regionalCredVerificationUrl = credentialSourceOpts.get('regional_cred_verification_url');
this.credentialSourceType = 'aws';
// Data validators.
this.validateEnvironmentId();
}
this.awsRequestSigner = null;
this.region = '';
this.credentialSourceType = 'aws';
// Data validators.
this.validateEnvironmentId();
}
validateEnvironmentId() {
var _a;
const match = (_a = this.environmentId) === null || _a === void 0 ? void 0 : _a.match(/^(aws)(\d+)$/);
var _b;
const match = (_b = this.environmentId) === null || _b === void 0 ? void 0 : _b.match(/^(aws)(\d+)$/);
if (!match || !this.regionalCredVerificationUrl) {

@@ -70,22 +101,6 @@ throw new Error('No valid AWS "credential_source" provided');

* Triggered when an external subject token is needed to be exchanged for a
* GCP access token via GCP STS endpoint.
* This uses the `options.credential_source` object to figure out how
* to retrieve the token using the current environment. In this case,
* this uses a serialized AWS signed request to the STS GetCallerIdentity
* endpoint.
* The logic is summarized as:
* 1. If imdsv2_session_token_url is provided in the credential source, then
* fetch the aws session token and include it in the headers of the
* metadata requests. This is a requirement for IDMSv2 but optional
* for IDMSv1.
* 2. Retrieve AWS region from availability-zone.
* 3a. Check AWS credentials in environment variables. If not found, get
* from security-credentials endpoint.
* 3b. Get AWS credentials from security-credentials endpoint. In order
* to retrieve this, the AWS role needs to be determined by calling
* security-credentials endpoint without any argument. Then the
* credentials can be retrieved via: security-credentials/role_name
* 4. Generate the signed request to AWS STS GetCallerIdentity action.
* 5. Inject x-goog-cloud-target-resource into header and serialize the
* signed request. This will be the subject-token to pass to GCP STS.
* GCP access token via GCP STS endpoint. This will call the
* {@link AwsSecurityCredentialsSupplier} to retrieve an AWS region and AWS
* Security Credentials, then use them to create a signed AWS STS request that
* can be exchanged for a GCP access token.
* @return A promise that resolves with the external subject token.

@@ -96,35 +111,5 @@ */

if (!this.awsRequestSigner) {
const metadataHeaders = {};
// Only retrieve the IMDSv2 session token if both the security credentials and region are
// not retrievable through the environment.
// The credential config contains all the URLs by default but clients may be running this
// where the metadata server is not available and returning the credentials through the environment.
// Removing this check may break them.
if (!this.regionFromEnv && this.imdsV2SessionTokenUrl) {
metadataHeaders['x-aws-ec2-metadata-token'] =
await this.getImdsV2SessionToken();
}
this.region = await this.getAwsRegion(metadataHeaders);
this.region = await this.awsSecurityCredentialsSupplier.getAwsRegion(this.supplierContext);
this.awsRequestSigner = new awsrequestsigner_1.AwsRequestSigner(async () => {
// Check environment variables for permanent credentials first.
// https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html
if (this.securityCredentialsFromEnv) {
return this.securityCredentialsFromEnv;
}
if (this.imdsV2SessionTokenUrl) {
metadataHeaders['x-aws-ec2-metadata-token'] =
await this.getImdsV2SessionToken();
}
// Since the role on a VM can change, we don't need to cache it.
const roleName = await this.getAwsRoleName(metadataHeaders);
// Temporary credentials typically last for several hours.
// Expiration is returned in response.
// Consider future optimization of this logic to cache AWS tokens
// until their natural expiration.
const awsCreds = await this.getAwsSecurityCredentials(roleName, metadataHeaders);
return {
accessKeyId: awsCreds.AccessKeyId,
secretAccessKey: awsCreds.SecretAccessKey,
token: awsCreds.Token,
};
return this.awsSecurityCredentialsSupplier.getAwsSecurityCredentials(this.supplierContext);
}, this.region);

@@ -135,3 +120,3 @@ }

const options = await this.awsRequestSigner.getRequestOptions({
...AwsClient.RETRY_CONFIG,
..._a.RETRY_CONFIG,
url: this.regionalCredVerificationUrl.replace('{region}', this.region),

@@ -174,99 +159,13 @@ method: 'POST',

}
/**
* @return A promise that resolves with the IMDSv2 Session Token.
*/
async getImdsV2SessionToken() {
const opts = {
...AwsClient.RETRY_CONFIG,
url: this.imdsV2SessionTokenUrl,
method: 'PUT',
responseType: 'text',
headers: { 'x-aws-ec2-metadata-token-ttl-seconds': '300' },
};
const response = await this.transporter.request(opts);
return response.data;
}
/**
* @param headers The headers to be used in the metadata request.
* @return A promise that resolves with the current AWS region.
*/
async getAwsRegion(headers) {
// Priority order for region determination:
// AWS_REGION > AWS_DEFAULT_REGION > metadata server.
if (this.regionFromEnv) {
return this.regionFromEnv;
}
if (!this.regionUrl) {
throw new Error('Unable to determine AWS region due to missing ' +
'"options.credential_source.region_url"');
}
const opts = {
...AwsClient.RETRY_CONFIG,
url: this.regionUrl,
method: 'GET',
responseType: 'text',
headers: headers,
};
const response = await this.transporter.request(opts);
// Remove last character. For example, if us-east-2b is returned,
// the region would be us-east-2.
return response.data.substr(0, response.data.length - 1);
}
/**
* @param headers The headers to be used in the metadata request.
* @return A promise that resolves with the assigned role to the current
* AWS VM. This is needed for calling the security-credentials endpoint.
*/
async getAwsRoleName(headers) {
if (!this.securityCredentialsUrl) {
throw new Error('Unable to determine AWS role name due to missing ' +
'"options.credential_source.url"');
}
const opts = {
...AwsClient.RETRY_CONFIG,
url: this.securityCredentialsUrl,
method: 'GET',
responseType: 'text',
headers: headers,
};
const response = await this.transporter.request(opts);
return response.data;
}
/**
* Retrieves the temporary AWS credentials by calling the security-credentials
* endpoint as specified in the `credential_source` object.
* @param roleName The role attached to the current VM.
* @param headers The headers to be used in the metadata request.
* @return A promise that resolves with the temporary AWS credentials
* needed for creating the GetCallerIdentity signed request.
*/
async getAwsSecurityCredentials(roleName, headers) {
const response = await this.transporter.request({
...AwsClient.RETRY_CONFIG,
url: `${this.securityCredentialsUrl}/${roleName}`,
responseType: 'json',
headers: headers,
});
return response.data;
}
get regionFromEnv() {
// The AWS region can be provided through AWS_REGION or AWS_DEFAULT_REGION.
// Only one is required.
return (process.env['AWS_REGION'] || process.env['AWS_DEFAULT_REGION'] || null);
}
get securityCredentialsFromEnv() {
// Both AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY are required.
if (process.env['AWS_ACCESS_KEY_ID'] &&
process.env['AWS_SECRET_ACCESS_KEY']) {
return {
accessKeyId: process.env['AWS_ACCESS_KEY_ID'],
secretAccessKey: process.env['AWS_SECRET_ACCESS_KEY'],
token: process.env['AWS_SESSION_TOKEN'],
};
}
return null;
}
}
exports.AwsClient = AwsClient;
_a = AwsClient;
_AwsClient_DEFAULT_AWS_REGIONAL_CREDENTIAL_VERIFICATION_URL = { value: 'https://sts.{region}.amazonaws.com?Action=GetCallerIdentity&Version=2011-06-15' };
/**
* @deprecated AWS client no validates the EC2 metadata address.
**/
AwsClient.AWS_EC2_METADATA_IPV4_ADDRESS = '169.254.169.254';
/**
* @deprecated AWS client no validates the EC2 metadata address.
**/
AwsClient.AWS_EC2_METADATA_IPV6_ADDRESS = 'fd00:ec2::254';

@@ -1,5 +0,5 @@

import { GaxiosOptions, GaxiosPromise, GaxiosResponse } from 'gaxios';
import { Gaxios, GaxiosOptions, GaxiosPromise, GaxiosResponse } from 'gaxios';
import { Credentials } from './credentials';
import { AuthClient, AuthClientOptions } from './authclient';
import { BodyResponseCallback } from '../transporters';
import { BodyResponseCallback, Transporter } from '../transporters';
import { GetAccessTokenResponse, Headers } from './oauth2client';

@@ -29,20 +29,96 @@ import { SnakeToCamelObject } from '../util';

export { DEFAULT_UNIVERSE } from './authclient';
/**
* Shared options used to build {@link ExternalAccountClient} and
* {@link ExternalAccountAuthorizedUserClient}.
*/
export interface SharedExternalAccountClientOptions extends AuthClientOptions {
/**
* The Security Token Service audience, which is usually the fully specified
* resource name of the workload or workforce pool provider.
*/
audience: string;
token_url: string;
/**
* The Security Token Service token URL used to exchange the third party token
* for a GCP access token. If not provided, will default to
* 'https://sts.googleapis.com/v1/token'
*/
token_url?: string;
}
/**
* Interface containing context about the requested external identity. This is
* passed on all requests from external account clients to external identity suppliers.
*/
export interface ExternalAccountSupplierContext {
/**
* The requested external account audience. For example:
* * "//iam.googleapis.com/locations/global/workforcePools/$WORKFORCE_POOL_ID/providers/$PROVIDER_ID"
* * "//iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID"
*/
audience: string;
/**
* The requested subject token type. Expected values include:
* * "urn:ietf:params:oauth:token-type:jwt"
* * "urn:ietf:params:aws:token-type:aws4_request"
* * "urn:ietf:params:oauth:token-type:saml2"
* * "urn:ietf:params:oauth:token-type:id_token"
*/
subjectTokenType: string;
/** The {@link Gaxios} or {@link Transporter} instance from
* the calling external account to use for requests.
*/
transporter: Transporter | Gaxios;
}
/**
* Base external account credentials json interface.
*/
export interface BaseExternalAccountClientOptions extends SharedExternalAccountClientOptions {
type: string;
/**
* Credential type, should always be 'external_account'.
*/
type?: string;
/**
* The Security Token Service subject token type based on the OAuth 2.0
* token exchange spec. Expected values include:
* * 'urn:ietf:params:oauth:token-type:jwt'
* * 'urn:ietf:params:aws:token-type:aws4_request'
* * 'urn:ietf:params:oauth:token-type:saml2'
* * 'urn:ietf:params:oauth:token-type:id_token'
*/
subject_token_type: string;
/**
* The URL for the service account impersonation request. This URL is required
* for some APIs. If this URL is not available, the access token from the
* Security Token Service is used directly.
*/
service_account_impersonation_url?: string;
/**
* Object containing additional options for service account impersonation.
*/
service_account_impersonation?: {
/**
* The desired lifetime of the impersonated service account access token.
* If not provided, the default lifetime will be 3600 seconds.
*/
token_lifetime_seconds?: number;
};
/**
* The endpoint used to retrieve account related information.
*/
token_info_url?: string;
/**
* Client ID of the service account from the console.
*/
client_id?: string;
/**
* Client secret of the service account from the console.
*/
client_secret?: string;
/**
* The workforce pool user project. Required when using a workforce identity
* pool.
*/
workforce_pool_user_project?: string;
/**
* The scopes to request during the authorization grant.
*/
scopes?: string[];

@@ -119,2 +195,3 @@ /**

protected cloudResourceManagerURL: URL | string;
protected supplierContext: ExternalAccountSupplierContext;
/**

@@ -121,0 +198,0 @@ * Instantiate a BaseExternalAccountClient instance using the provided JSON

@@ -53,2 +53,3 @@ "use strict";

const WORKFORCE_AUDIENCE_PATTERN = '//iam\\.googleapis\\.com/locations/[^/]+/workforcePools/[^/]+/providers/.+';
const DEFAULT_TOKEN_URL = 'https://sts.{universeDomain}/v1/token';
// eslint-disable-next-line @typescript-eslint/no-var-requires

@@ -83,5 +84,7 @@ const pkg = require('../../../package.json');

constructor(options, additionalOptions) {
var _a;
super({ ...options, ...additionalOptions });
const opts = (0, util_1.originalOrCamelOptions)(options);
if (opts.get('type') !== exports.EXTERNAL_ACCOUNT_TYPE) {
const type = opts.get('type');
if (type && type !== exports.EXTERNAL_ACCOUNT_TYPE) {
throw new Error(`Expected "${exports.EXTERNAL_ACCOUNT_TYPE}" type but ` +

@@ -92,3 +95,3 @@ `received "${options.type}"`);

const clientSecret = opts.get('client_secret');
const tokenUrl = opts.get('token_url');
const tokenUrl = (_a = opts.get('token_url')) !== null && _a !== void 0 ? _a : DEFAULT_TOKEN_URL.replace('{universeDomain}', this.universeDomain);
const subjectTokenType = opts.get('subject_token_type');

@@ -131,2 +134,7 @@ const workforcePoolUserProject = opts.get('workforce_pool_user_project');

this.projectNumber = this.getProjectNumber(this.audience);
this.supplierContext = {
audience: this.audience,
subjectTokenType: this.subjectTokenType,
transporter: this.transporter,
};
}

@@ -133,0 +141,0 @@ /** The service account email to be impersonated, if available. */

@@ -26,2 +26,3 @@ "use strict";

exports.EXTERNAL_ACCOUNT_AUTHORIZED_USER_TYPE = 'external_account_authorized_user';
const DEFAULT_TOKEN_URL = 'https://sts.{universeDomain}/v1/oauthtoken';
/**

@@ -110,3 +111,7 @@ * Handler for token refresh requests sent to the token_url endpoint for external

constructor(options, additionalOptions) {
var _a;
super({ ...options, ...additionalOptions });
if (options.universe_domain) {
this.universeDomain = options.universe_domain;
}
this.refreshToken = options.refresh_token;

@@ -119,3 +124,3 @@ const clientAuth = {

this.externalAccountAuthorizedUserHandler =
new ExternalAccountAuthorizedUserHandler(options.token_url, this.transporter, clientAuth);
new ExternalAccountAuthorizedUserHandler((_a = options.token_url) !== null && _a !== void 0 ? _a : DEFAULT_TOKEN_URL.replace('{universeDomain}', this.universeDomain), this.transporter, clientAuth);
this.cachedAccessToken = null;

@@ -134,5 +139,2 @@ this.quotaProjectId = options.quota_project_id;

this.forceRefreshOnFailure = !!(additionalOptions === null || additionalOptions === void 0 ? void 0 : additionalOptions.forceRefreshOnFailure);
if (options.universe_domain) {
this.universeDomain = options.universe_domain;
}
}

@@ -139,0 +141,0 @@ async getAccessToken() {

@@ -1,6 +0,27 @@

import { BaseExternalAccountClient, BaseExternalAccountClientOptions } from './baseexternalclient';
import { BaseExternalAccountClient, BaseExternalAccountClientOptions, ExternalAccountSupplierContext } from './baseexternalclient';
import { AuthClientOptions } from './authclient';
import { SnakeToCamelObject } from '../util';
type SubjectTokenFormatType = 'json' | 'text';
export type SubjectTokenFormatType = 'json' | 'text';
export interface SubjectTokenJsonResponse {
[key: string]: string;
}
/**
* Supplier interface for subject tokens. This can be implemented to
* return a subject token which can then be exchanged for a GCP token by an
* {@link IdentityPoolClient}.
*/
export interface SubjectTokenSupplier {
/**
* Gets a valid subject token for the requested external account identity.
* Note that these are not cached by the calling {@link IdentityPoolClient},
* so caching should be including in the implementation.
* @param context {@link ExternalAccountSupplierContext} from the calling
* {@link IdentityPoolClient}, contains the requested audience and subject token type
* for the external account identity as well as the transport from the
* calling client to use for requests.
* @return A promise that resolves with the requested subject token string.
*/
getSubjectToken: (context: ExternalAccountSupplierContext) => Promise<string>;
}
/**
* Url-sourced/file-sourced credentials json interface.

@@ -10,13 +31,44 @@ * This is used for K8s and Azure workloads.

export interface IdentityPoolClientOptions extends BaseExternalAccountClientOptions {
credential_source: {
/**
* Object containing options to retrieve identity pool credentials. A valid credential
* source or a subject token supplier must be specified.
*/
credential_source?: {
/**
* The file location to read the subject token from. Either this or a URL
* should be specified.
*/
file?: string;
/**
* The URL to call to retrieve the subject token. Either this or a file
* location should be specified.
*/
url?: string;
/**
* Optional headers to send on the request to the specified URL.
*/
headers?: {
[key: string]: string;
};
/**
* The format that the subject token is in the file or the URL response.
* If not provided, will default to reading the text string directly.
*/
format?: {
/**
* The format type. Can either be 'text' or 'json'.
*/
type: SubjectTokenFormatType;
/**
* The field name containing the subject token value if the type is 'json'.
*/
subject_token_field_name?: string;
};
};
/**
* The subject token supplier to call to retrieve the subject token to exchange
* for a GCP access token. Either this or a valid credential source should
* be specified.
*/
subject_token_supplier?: SubjectTokenSupplier;
}

@@ -28,7 +80,3 @@ /**

export declare class IdentityPoolClient extends BaseExternalAccountClient {
private readonly file?;
private readonly url?;
private readonly headers?;
private readonly formatType;
private readonly formatSubjectTokenFieldName?;
private readonly subjectTokenSupplier;
/**

@@ -51,37 +99,7 @@ * Instantiate an IdentityPoolClient instance using the provided JSON

* Triggered when a external subject token is needed to be exchanged for a GCP
* access token via GCP STS endpoint.
* This uses the `options.credential_source` object to figure out how
* to retrieve the token using the current environment. In this case,
* this either retrieves the local credential from a file location (k8s
* workload) or by sending a GET request to a local metadata server (Azure
* workloads).
* access token via GCP STS endpoint. Gets a subject token by calling
* the configured {@link SubjectTokenSupplier}
* @return A promise that resolves with the external subject token.
*/
retrieveSubjectToken(): Promise<string>;
/**
* Looks up the external subject token in the file path provided and
* resolves with that token.
* @param file The file path where the external credential is located.
* @param formatType The token file or URL response type (JSON or text).
* @param formatSubjectTokenFieldName For JSON response types, this is the
* subject_token field name. For Azure, this is access_token. For text
* response types, this is ignored.
* @return A promise that resolves with the external subject token.
*/
private getTokenFromFile;
/**
* Sends a GET request to the URL provided and resolves with the returned
* external subject token.
* @param url The URL to call to retrieve the subject token. This is typically
* a local metadata server.
* @param formatType The token file or URL response type (JSON or text).
* @param formatSubjectTokenFieldName For JSON response types, this is the
* subject_token field name. For Azure, this is access_token. For text
* response types, this is ignored.
* @param headers The optional additional headers to send with the request to
* the metadata server url.
* @return A promise that resolves with the external subject token.
*/
private getTokenFromUrl;
}
export {};

@@ -15,16 +15,8 @@ "use strict";

// limitations under the License.
var _a, _b, _c;
Object.defineProperty(exports, "__esModule", { value: true });
exports.IdentityPoolClient = void 0;
const fs = require("fs");
const util_1 = require("util");
const baseexternalclient_1 = require("./baseexternalclient");
const util_2 = require("../util");
// fs.readfile is undefined in browser karma tests causing
// `npm run browser-test` to fail as test.oauth2.ts imports this file via
// src/index.ts.
// Fallback to void function to avoid promisify throwing a TypeError.
const readFile = (0, util_1.promisify)((_a = fs.readFile) !== null && _a !== void 0 ? _a : (() => { }));
const realpath = (0, util_1.promisify)((_b = fs.realpath) !== null && _b !== void 0 ? _b : (() => { }));
const lstat = (0, util_1.promisify)((_c = fs.lstat) !== null && _c !== void 0 ? _c : (() => { }));
const util_1 = require("../util");
const filesubjecttokensupplier_1 = require("./filesubjecttokensupplier");
const urlsubjecttokensupplier_1 = require("./urlsubjecttokensupplier");
/**

@@ -51,124 +43,67 @@ * Defines the Url-sourced and file-sourced external account clients mainly

super(options, additionalOptions);
const opts = (0, util_2.originalOrCamelOptions)(options);
const opts = (0, util_1.originalOrCamelOptions)(options);
const credentialSource = opts.get('credential_source');
const credentialSourceOpts = (0, util_2.originalOrCamelOptions)(credentialSource);
this.file = credentialSourceOpts.get('file');
this.url = credentialSourceOpts.get('url');
this.headers = credentialSourceOpts.get('headers');
if (this.file && this.url) {
throw new Error('No valid Identity Pool "credential_source" provided, must be either file or url.');
const subjectTokenSupplier = opts.get('subject_token_supplier');
// Validate credential sourcing configuration.
if (!credentialSource && !subjectTokenSupplier) {
throw new Error('A credential source or subject token supplier must be specified.');
}
else if (this.file && !this.url) {
this.credentialSourceType = 'file';
if (credentialSource && subjectTokenSupplier) {
throw new Error('Only one of credential source or subject token supplier can be specified.');
}
else if (!this.file && this.url) {
this.credentialSourceType = 'url';
if (subjectTokenSupplier) {
this.subjectTokenSupplier = subjectTokenSupplier;
this.credentialSourceType = 'programmatic';
}
else {
throw new Error('No valid Identity Pool "credential_source" provided, must be either file or url.');
const credentialSourceOpts = (0, util_1.originalOrCamelOptions)(credentialSource);
const formatOpts = (0, util_1.originalOrCamelOptions)(credentialSourceOpts.get('format'));
// Text is the default format type.
const formatType = formatOpts.get('type') || 'text';
const formatSubjectTokenFieldName = formatOpts.get('subject_token_field_name');
if (formatType !== 'json' && formatType !== 'text') {
throw new Error(`Invalid credential_source format "${formatType}"`);
}
if (formatType === 'json' && !formatSubjectTokenFieldName) {
throw new Error('Missing subject_token_field_name for JSON credential_source format');
}
const file = credentialSourceOpts.get('file');
const url = credentialSourceOpts.get('url');
const headers = credentialSourceOpts.get('headers');
if (file && url) {
throw new Error('No valid Identity Pool "credential_source" provided, must be either file or url.');
}
else if (file && !url) {
this.credentialSourceType = 'file';
this.subjectTokenSupplier = new filesubjecttokensupplier_1.FileSubjectTokenSupplier({
filePath: file,
formatType: formatType,
subjectTokenFieldName: formatSubjectTokenFieldName,
});
}
else if (!file && url) {
this.credentialSourceType = 'url';
this.subjectTokenSupplier = new urlsubjecttokensupplier_1.UrlSubjectTokenSupplier({
url: url,
formatType: formatType,
subjectTokenFieldName: formatSubjectTokenFieldName,
headers: headers,
additionalGaxiosOptions: IdentityPoolClient.RETRY_CONFIG,
});
}
else {
throw new Error('No valid Identity Pool "credential_source" provided, must be either file or url.');
}
}
const formatOpts = (0, util_2.originalOrCamelOptions)(credentialSourceOpts.get('format'));
// Text is the default format type.
this.formatType = formatOpts.get('type') || 'text';
this.formatSubjectTokenFieldName = formatOpts.get('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');
}
}
/**
* Triggered when a external subject token is needed to be exchanged for a GCP
* access token via GCP STS endpoint.
* This uses the `options.credential_source` object to figure out how
* to retrieve the token using the current environment. In this case,
* this either retrieves the local credential from a file location (k8s
* workload) or by sending a GET request to a local metadata server (Azure
* workloads).
* access token via GCP STS endpoint. Gets a subject token by calling
* the configured {@link SubjectTokenSupplier}
* @return A promise that resolves with the external subject token.
*/
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);
return this.subjectTokenSupplier.getSubjectToken(this.supplierContext);
}
/**
* Looks up the external subject token in the file path provided and
* resolves with that token.
* @param file The file path where the external credential is located.
* @param formatType The token file or URL response type (JSON or text).
* @param formatSubjectTokenFieldName For JSON response types, this is the
* subject_token field name. For Azure, this is access_token. For text
* response types, this is ignored.
* @return A promise that resolves with the external subject token.
*/
async getTokenFromFile(filePath, formatType, formatSubjectTokenFieldName) {
// Make sure there is a file at the path. lstatSync will throw if there is
// nothing there.
try {
// Resolve path to actual file in case of symlink. Expect a thrown error
// if not resolvable.
filePath = await realpath(filePath);
if (!(await lstat(filePath)).isFile()) {
throw new Error();
}
}
catch (err) {
if (err instanceof Error) {
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);
subjectToken = json[formatSubjectTokenFieldName];
}
if (!subjectToken) {
throw new Error('Unable to parse the subject_token from the credential_source file');
}
return subjectToken;
}
/**
* Sends a GET request to the URL provided and resolves with the returned
* external subject token.
* @param url The URL to call to retrieve the subject token. This is typically
* a local metadata server.
* @param formatType The token file or URL response type (JSON or text).
* @param formatSubjectTokenFieldName For JSON response types, this is the
* subject_token field name. For Azure, this is access_token. For text
* response types, this is ignored.
* @param headers The optional additional headers to send with the request to
* the metadata server url.
* @return A promise that resolves with the external subject token.
*/
async getTokenFromUrl(url, formatType, formatSubjectTokenFieldName, headers) {
const opts = {
...IdentityPoolClient.RETRY_CONFIG,
url,
method: 'GET',
headers,
responseType: formatType,
};
let subjectToken;
if (formatType === 'text') {
const response = await this.transporter.request(opts);
subjectToken = response.data;
}
else if (formatType === 'json' && formatSubjectTokenFieldName) {
const response = await this.transporter.request(opts);
subjectToken = response.data[formatSubjectTokenFieldName];
}
if (!subjectToken) {
throw new Error('Unable to parse the subject_token from the credential_source URL');
}
return subjectToken;
}
}
exports.IdentityPoolClient = IdentityPoolClient;
{
"name": "google-auth-library",
"version": "9.8.0",
"version": "9.9.0",
"author": "Google Inc.",

@@ -5,0 +5,0 @@ "description": "Google APIs Authentication Client Library for Node.js",

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc