Skip to content

Commit

Permalink
feat: extend universe_domain support (#1633)
Browse files Browse the repository at this point in the history
* feat: extend `universe_domain` support

* style: lint

* chore: minor fix

* chore: lint

* chore: lint

* run lint

---------

Co-authored-by: Sofia Leon <sofialeon@google.com>
  • Loading branch information
danielbankhead and sofisl committed Aug 31, 2023
1 parent bf23bad commit 4ee02da
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 21 deletions.
29 changes: 22 additions & 7 deletions src/auth/baseexternalclient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,24 +62,36 @@ const WORKFORCE_AUDIENCE_PATTERN =
// eslint-disable-next-line @typescript-eslint/no-var-requires
const pkg = require('../../../package.json');

/**
* The default cloud universe
*/
export const DEFAULT_UNIVERSE = 'googleapis.com';

export interface SharedExternalAccountClientOptions {
audience: string;
token_url: string;
quota_project_id?: string;
/**
* universe domain is the default service domain for a given Cloud universe
*/
universe_domain?: string;
}

/**
* Base external account credentials json interface.
*/
export interface BaseExternalAccountClientOptions {
export interface BaseExternalAccountClientOptions
extends SharedExternalAccountClientOptions {
type: string;
audience: string;
subject_token_type: string;
service_account_impersonation_url?: string;
service_account_impersonation?: {
token_lifetime_seconds?: number;
};
token_url: string;
token_info_url?: string;
client_id?: string;
client_secret?: string;
quota_project_id?: string;
workforce_pool_user_project?: string;
universe_domain?: string;
}

/**
Expand Down Expand Up @@ -139,7 +151,7 @@ export abstract class BaseExternalAccountClient extends AuthClient {
private readonly stsCredential: sts.StsCredentials;
private readonly clientAuth?: ClientAuthentication;
private readonly workforcePoolUserProject?: string;
private universeDomain?: string;
public universeDomain = DEFAULT_UNIVERSE;
public projectId: string | null;
public projectNumber: string | null;
public readonly eagerRefreshThresholdMillis: number;
Expand Down Expand Up @@ -217,7 +229,10 @@ export abstract class BaseExternalAccountClient extends AuthClient {
this.forceRefreshOnFailure = !!additionalOptions?.forceRefreshOnFailure;
this.projectId = null;
this.projectNumber = this.getProjectNumber(this.audience);
this.universeDomain = options.universe_domain;

if (options.universe_domain) {
this.universeDomain = options.universe_domain;
}
}

/** The service account email to be impersonated, if available. */
Expand Down
30 changes: 18 additions & 12 deletions src/auth/externalAccountAuthorizedUserClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,29 +29,30 @@ import {
} from 'gaxios';
import {Credentials} from './credentials';
import * as stream from 'stream';
import {EXPIRATION_TIME_OFFSET} from './baseexternalclient';
import {
DEFAULT_UNIVERSE,
EXPIRATION_TIME_OFFSET,
SharedExternalAccountClientOptions,
} from './baseexternalclient';

/**
* The credentials JSON file type for external account authorized user clients.
*/
export const EXTERNAL_ACCOUNT_AUTHORIZED_USER_TYPE =
'external_account_authorized_user';

/**
* External Account Authorized User Credentials JSON interface.
*/
export interface ExternalAccountAuthorizedUserClientOptions {
export interface ExternalAccountAuthorizedUserClientOptions
extends SharedExternalAccountClientOptions {
type: typeof EXTERNAL_ACCOUNT_AUTHORIZED_USER_TYPE;
audience: string;
client_id: string;
client_secret: string;
refresh_token: string;
token_url: string;
token_info_url: string;
revoke_url?: string;
quota_project_id?: string;
}

/**
* The credentials JSON file type for external account authorized user clients.
*/
export const EXTERNAL_ACCOUNT_AUTHORIZED_USER_TYPE =
'external_account_authorized_user';

/**
* Internal interface for tracking the access token expiration time.
*/
Expand Down Expand Up @@ -155,6 +156,7 @@ export class ExternalAccountAuthorizedUserClient extends AuthClient {
private cachedAccessToken: CredentialsWithResponse | null;
private readonly externalAccountAuthorizedUserHandler: ExternalAccountAuthorizedUserHandler;
private refreshToken: string;
public universeDomain = DEFAULT_UNIVERSE;

/**
* Instantiates an ExternalAccountAuthorizedUserClient instances using the
Expand Down Expand Up @@ -197,6 +199,10 @@ export class ExternalAccountAuthorizedUserClient extends AuthClient {
.eagerRefreshThresholdMillis as number;
}
this.forceRefreshOnFailure = !!additionalOptions?.forceRefreshOnFailure;

if (options.universe_domain) {
this.universeDomain = options.universe_domain;
}
}

async getAccessToken(): Promise<{
Expand Down
22 changes: 21 additions & 1 deletion test/test.baseexternalclient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
EXPIRATION_TIME_OFFSET,
BaseExternalAccountClient,
BaseExternalAccountClientOptions,
DEFAULT_UNIVERSE,
} from '../src/auth/baseexternalclient';
import {
OAuthErrorResponse,
Expand Down Expand Up @@ -80,7 +81,6 @@ describe('BaseExternalAccountClient', () => {
credential_source: {
file: '/var/run/secrets/goog.id/token',
},
universe_domain: 'universe.domain.com',
};
const externalAccountOptionsWithCreds = {
type: 'external_account',
Expand Down Expand Up @@ -294,6 +294,26 @@ describe('BaseExternalAccountClient', () => {
});
});

describe('universeDomain', () => {
it('should be the default universe if not set', () => {
const client = new TestExternalAccountClient(externalAccountOptions);

assert.equal(client.universeDomain, DEFAULT_UNIVERSE);
});

it('should be set if provided', () => {
const universeDomain = 'my-universe.domain.com';
const options: BaseExternalAccountClientOptions = {
...externalAccountOptions,
universe_domain: universeDomain,
};

const client = new TestExternalAccountClient(options);

assert.equal(client.universeDomain, universeDomain);
});
});

describe('getServiceAccountEmail()', () => {
it('should return the service account email when impersonation is used', () => {
const saEmail = 'service-1234@service-name.iam.gserviceaccount.com';
Expand Down
25 changes: 24 additions & 1 deletion test/test.externalaccountauthorizeduserclient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ import {
ExternalAccountAuthorizedUserClient,
ExternalAccountAuthorizedUserClientOptions,
} from '../src/auth/externalAccountAuthorizedUserClient';
import {EXPIRATION_TIME_OFFSET} from '../src/auth/baseexternalclient';
import {
DEFAULT_UNIVERSE,
EXPIRATION_TIME_OFFSET,
} from '../src/auth/baseexternalclient';
import {GaxiosError, GaxiosResponse} from 'gaxios';
import {
getErrorFromOAuthErrorResponse,
Expand Down Expand Up @@ -149,6 +152,26 @@ describe('ExternalAccountAuthorizedUserClient', () => {
refreshOptions.eagerRefreshThresholdMillis
);
});

describe('universeDomain', () => {
it('should be the default universe if not set', () => {
const client = new ExternalAccountAuthorizedUserClient(
externalAccountAuthorizedUserCredentialOptions
);

assert.equal(client.universeDomain, DEFAULT_UNIVERSE);
});

it('should be set if provided', () => {
const universeDomain = 'my-universe.domain.com';
const client = new ExternalAccountAuthorizedUserClient({
...externalAccountAuthorizedUserCredentialOptions,
universe_domain: universeDomain,
});

assert.equal(client.universeDomain, universeDomain);
});
});
});

describe('getAccessToken()', () => {
Expand Down

0 comments on commit 4ee02da

Please sign in to comment.