diff --git a/core/packages/google-auth-library-nodejs/src/auth/authclient.ts b/core/packages/google-auth-library-nodejs/src/auth/authclient.ts index f18dd58e2abf..216e3390fdc4 100644 --- a/core/packages/google-auth-library-nodejs/src/auth/authclient.ts +++ b/core/packages/google-auth-library-nodejs/src/auth/authclient.ts @@ -20,6 +20,10 @@ import {OriginalAndCamel, originalOrCamelOptions} from '../util'; import {log as makeLog} from 'google-logging-utils'; import {PRODUCT_NAME, USER_AGENT} from '../shared.cjs'; +import { + RegionalAccessBoundaryData, + RegionalAccessBoundaryManager, +} from './regionalaccessboundary'; /** * An interface for enforcing `fetch`-type compliance. @@ -232,6 +236,7 @@ export abstract class AuthClient eagerRefreshThresholdMillis = DEFAULT_EAGER_REFRESH_THRESHOLD_MILLIS; forceRefreshOnFailure = false; universeDomain = DEFAULT_UNIVERSE; + protected regionalAccessBoundaryManager: RegionalAccessBoundaryManager; /** * Symbols that can be added to GaxiosOptions to specify the method name that is @@ -258,6 +263,12 @@ export abstract class AuthClient // Shared client options this.transporter = opts.transporter ?? new Gaxios(opts.transporterOptions); + this.regionalAccessBoundaryManager = new RegionalAccessBoundaryManager({ + transporter: this.transporter, + getLookupUrl: async () => this.getRegionalAccessBoundaryUrl(), + isUniverseDomainDefault: () => this.universeDomain === DEFAULT_UNIVERSE, + }); + if (options.get('useAuthRequestParameters') !== false) { this.transporter.interceptors.request.add( AuthClient.DEFAULT_REQUEST_INTERCEPTOR, @@ -361,6 +372,21 @@ export abstract class AuthClient res?: GaxiosResponse | null; }>; + /** + * Returns the regional access boundary lookup URL for the current client. + * This method is intended for internal use by the RegionalAccessBoundaryManager + * and should not be called directly by users. + * + * @return The regional access boundary URL string, or `null` if the client type + * does not support regional access boundaries. + * @throws {Error} If the URL cannot be constructed for a compatible client, + * for instance, if a required property like a service account email is missing. + * @internal + */ + public async getRegionalAccessBoundaryUrl(): Promise { + return null; + } + /** * Sets the auth credentials. */ @@ -368,6 +394,22 @@ export abstract class AuthClient this.credentials = credentials; } + /** + * Returns the current regional access boundary data. + * @internal + */ + getRegionalAccessBoundary(): RegionalAccessBoundaryData | null { + return this.regionalAccessBoundaryManager.data; + } + + /** + * Returns the current regional access boundary cooldown time in milliseconds. + * @internal + */ + getRegionalAccessBoundaryCooldownTime(): number { + return this.regionalAccessBoundaryManager.cooldownTime; + } + /** * Append additional headers, e.g., x-goog-user-project, shared across the * classes inheriting AuthClient. This method should be used by any method @@ -386,23 +428,47 @@ export abstract class AuthClient ) { headers.set('x-goog-user-project', this.quotaProjectId); } + return headers; } /** - * Adds the `x-goog-user-project` and `authorization` headers to the target Headers + * Applies regional access boundary rules to the provided headers. + * This includes adding the x-allowed-locations header and triggering + * a background refresh if needed. + * @param headers The headers to update. + * @param url Optional destination URL of the request. If missing, assumed global. + */ + protected applyRegionalAccessBoundary( + headers: Headers, + url?: string | URL, + ): void { + const rabHeader = + this.regionalAccessBoundaryManager.getRegionalAccessBoundaryHeader( + url, + headers, + ); + if (rabHeader) { + headers.set('x-allowed-locations', rabHeader); + } + } + + /** + * Adds the `x-goog-user-project`, `authorization`, and 'x-allowed-locations' + * headers to the target Headers * object, if they exist on the source. * * @param target the headers to target * @param source the headers to source from * @returns the target headers */ - protected addUserProjectAndAuthHeaders( + protected applyHeadersFromSource( target: T, source: Headers, ): T { const xGoogUserProject = source.get('x-goog-user-project'); const authorizationHeader = source.get('authorization'); + const xGoogAllowedLocs = source.get('x-allowed-locations'); if (xGoogUserProject) { target.set('x-goog-user-project', xGoogUserProject); @@ -412,6 +478,10 @@ export abstract class AuthClient target.set('authorization', authorizationHeader); } + if (xGoogAllowedLocs) { + target.set('x-allowed-locations', xGoogAllowedLocs); + } + return target; } @@ -549,6 +619,20 @@ export abstract class AuthClient }, }; } + + /** + * Returns whether the provided credentials are expired or will expire within + * eagerRefreshThresholdMillismilliseconds. + * If there is no expiry time, assumes the token is not expired or expiring. + * @param credentials The credentials to check for expiration. + * @return Whether the credentials are expired or not. + */ + protected isExpired(credentials: Credentials = this.credentials): boolean { + const now = new Date().getTime(); + return credentials.expiry_date + ? now >= credentials.expiry_date - this.eagerRefreshThresholdMillis + : false; + } } // TypeScript does not have `HeadersInit` in the standard types yet diff --git a/core/packages/google-auth-library-nodejs/src/auth/baseexternalclient.ts b/core/packages/google-auth-library-nodejs/src/auth/baseexternalclient.ts index 48111eb6345a..f569a590fc29 100644 --- a/core/packages/google-auth-library-nodejs/src/auth/baseexternalclient.ts +++ b/core/packages/google-auth-library-nodejs/src/auth/baseexternalclient.ts @@ -31,7 +31,16 @@ import { import * as sts from './stscredentials'; import {ClientAuthentication} from './oauth2common'; import {SnakeToCamelObject, originalOrCamelOptions} from '../util'; +import { + getWorkforcePoolIdFromAudience, + getWorkloadPoolIdFromAudience, +} from '../util'; import {pkg} from '../shared.cjs'; +import { + SERVICE_ACCOUNT_LOOKUP_ENDPOINT, + WORKFORCE_LOOKUP_ENDPOINT, + WORKLOAD_LOOKUP_ENDPOINT, +} from './regionalaccessboundary'; /** * The required token exchange grant_type: rfc8693#section-2.1 @@ -415,11 +424,12 @@ export abstract class BaseExternalAccountClient extends AuthClient { * The result has the form: * { authorization: 'Bearer ' } */ - async getRequestHeaders(): Promise { + async getRequestHeaders(url?: string | URL): Promise { const accessTokenResponse = await this.getAccessToken(); const headers = new Headers({ authorization: `Bearer ${accessTokenResponse.token}`, }); + this.applyRegionalAccessBoundary(headers, url); return this.addSharedMetadataHeaders(headers); } @@ -499,13 +509,14 @@ export abstract class BaseExternalAccountClient extends AuthClient { reAuthRetried = false, ): Promise> { let response: GaxiosResponse; + const requestOpts = {...opts}; try { - const requestHeaders = await this.getRequestHeaders(); - opts.headers = Gaxios.mergeHeaders(opts.headers); + const requestHeaders = await this.getRequestHeaders(opts.url); + requestOpts.headers = Gaxios.mergeHeaders(requestOpts.headers); - this.addUserProjectAndAuthHeaders(opts.headers, requestHeaders); + this.applyHeadersFromSource(requestOpts.headers, requestHeaders); - response = await this.transporter.request(opts); + response = await this.transporter.request(requestOpts); } catch (e) { const res = (e as GaxiosError).response; if (res) { @@ -684,19 +695,6 @@ export abstract class BaseExternalAccountClient extends AuthClient { }; } - /** - * Returns whether the provided credentials are expired or not. - * If there is no expiry time, assumes the token is not expired or expiring. - * @param accessToken The credentials to check for expiration. - * @return Whether the credentials are expired or not. - */ - private isExpired(accessToken: Credentials): boolean { - const now = new Date().getTime(); - return accessToken.expiry_date - ? now >= accessToken.expiry_date - this.eagerRefreshThresholdMillis - : false; - } - /** * @return The list of scopes for the requested GCP access token. */ @@ -722,4 +720,54 @@ export abstract class BaseExternalAccountClient extends AuthClient { protected getTokenUrl(): string { return this.tokenUrl; } + + /** + * Returns the regional access boundary lookup URL for the external account. + * This implementation constructs the URL based on the audience of the + * workforce or workload pool. If the client is configured for service account + * impersonation, it uses the target service account email to generate + * the lookup endpoint. + * + * @return The regional access boundary URL string. + * @internal + */ + public async getRegionalAccessBoundaryUrl(): Promise { + if (this.serviceAccountImpersonationUrl) { + // When impersonating a service account, the regional access boundary is determined + // by the security policies of the target service account. + const email = this.getServiceAccountEmail(); + if (!email) { + throw new Error( + `RegionalAccessBoundary: A service account email is required for regional access boundary lookups but could not be determined from the serviceAccountImpersonationUrl ${this.serviceAccountImpersonationUrl}.`, + ); + } + return SERVICE_ACCOUNT_LOOKUP_ENDPOINT.replace( + '{service_account_email}', + encodeURIComponent(email), + ); + } + + // Check if the audience corresponds to a workload identity pool. + const wfPoolId = getWorkforcePoolIdFromAudience(this.audience); + if (wfPoolId) { + return WORKFORCE_LOOKUP_ENDPOINT.replace( + '{pool_id}', + encodeURIComponent(wfPoolId), + ); + } + + // Check if the audience corresponds to a workforce identity pool. + const wlPoolId = getWorkloadPoolIdFromAudience(this.audience); + const projectNumber = this.getProjectNumber(this.audience); + if (wlPoolId && projectNumber) { + return WORKLOAD_LOOKUP_ENDPOINT.replace( + '{project_id}', + projectNumber, + ).replace('{pool_id}', wlPoolId); + } + + throw new RangeError( + `RegionalAccessBoundary: Invalid audience provided: "${this.audience}" does not correspond to a workforce or workload pool.`, + ); + } } diff --git a/core/packages/google-auth-library-nodejs/src/auth/certificatesubjecttokensupplier.ts b/core/packages/google-auth-library-nodejs/src/auth/certificatesubjecttokensupplier.ts index d09382c3983c..9cbe1f6d2f63 100644 --- a/core/packages/google-auth-library-nodejs/src/auth/certificatesubjecttokensupplier.ts +++ b/core/packages/google-auth-library-nodejs/src/auth/certificatesubjecttokensupplier.ts @@ -13,33 +13,14 @@ // limitations under the License. import {SubjectTokenSupplier} from './identitypoolclient'; -import {getWellKnownCertificateConfigFileLocation, isValidFile} from '../util'; import * as fs from 'fs'; -import {createPrivateKey, X509Certificate} from 'crypto'; +import {X509Certificate} from 'crypto'; import * as https from 'https'; - -export const CERTIFICATE_CONFIGURATION_ENV_VARIABLE = - 'GOOGLE_API_CERTIFICATE_CONFIG'; - -/** - * Thrown when the certificate source cannot be located or accessed. - */ -export class CertificateSourceUnavailableError extends Error { - constructor(message: string) { - super(message); - this.name = 'CertificateSourceUnavailableError'; - } -} - -/** - * Thrown for invalid configuration that is not related to file availability. - */ -export class InvalidConfigurationError extends Error { - constructor(message: string) { - super(message); - this.name = 'InvalidConfigurationError'; - } -} +import { + CertificateSourceUnavailableError, + InvalidConfigurationError, + getClientCertAndKey, +} from './mtlsutils'; /** * Defines options for creating a {@link CertificateSubjectTokenSupplier}. @@ -65,21 +46,6 @@ export interface CertificateSubjectTokenSupplierOptions { * Represents the "workload" block within the certificate configuration file. * @internal */ -interface WorkloadCertConfigJson { - cert_path: string; - key_path: string; -} - -/** - * Represents the structure of the certificate_config.json file. - * @internal - */ -interface CertificateConfigFileJson { - version: number; - cert_configs: { - workload?: WorkloadCertConfigJson; - }; -} /** * A subject token supplier that uses a client certificate for authentication. @@ -130,135 +96,14 @@ export class CertificateSubjectTokenSupplier implements SubjectTokenSupplier { public async getSubjectToken(): Promise { // The "subject token" in this context is the processed certificate chain. - this.certificateConfigPath = await this.#resolveCertificateConfigFilePath(); - - const {certPath, keyPath} = await this.#getCertAndKeyPaths(); - - ({cert: this.cert, key: this.key} = await this.#getKeyAndCert( - certPath, - keyPath, + // getClientCertAndKey handles path resolution, file reading, and validation + ({cert: this.cert, key: this.key} = await getClientCertAndKey( + this.certificateConfigPath, )); return await this.#processChainFromPaths(this.cert); } - /** - * Resolves the absolute path to the certificate configuration file - * by checking the "certificate_config_location" provided in the ADC file, - * or the "GOOGLE_API_CERTIFICATE_CONFIG" environment variable - * or in the default gcloud path. - * @param overridePath An optional path to check first. - * @returns The resolved file path. - */ - async #resolveCertificateConfigFilePath(): Promise { - // 1. Check for the override path from constructor options. - const overridePath = this.certificateConfigPath; - if (overridePath) { - if (await isValidFile(overridePath)) { - return overridePath; - } - throw new CertificateSourceUnavailableError( - `Provided certificate config path is invalid: ${overridePath}`, - ); - } - - // 2. Check the standard environment variable. - const envPath = process.env[CERTIFICATE_CONFIGURATION_ENV_VARIABLE]; - if (envPath) { - if (await isValidFile(envPath)) { - return envPath; - } - throw new CertificateSourceUnavailableError( - `Path from environment variable "${CERTIFICATE_CONFIGURATION_ENV_VARIABLE}" is invalid: ${envPath}`, - ); - } - - // 3. Check the well-known gcloud config location. - const wellKnownPath = getWellKnownCertificateConfigFileLocation(); - if (await isValidFile(wellKnownPath)) { - return wellKnownPath; - } - - // 4. If none are found, throw an error. - throw new CertificateSourceUnavailableError( - 'Could not find certificate configuration file. Searched override path, ' + - `the "${CERTIFICATE_CONFIGURATION_ENV_VARIABLE}" env var, and the gcloud path (${wellKnownPath}).`, - ); - } - - /** - * Reads and parses the certificate config JSON file to extract the certificate and key paths. - * @returns An object containing the certificate and key paths. - */ - async #getCertAndKeyPaths(): Promise<{ - certPath: string; - keyPath: string; - }> { - const configPath = this.certificateConfigPath; - let fileContents: string; - try { - fileContents = await fs.promises.readFile(configPath, 'utf8'); - } catch (err) { - throw new CertificateSourceUnavailableError( - `Failed to read certificate config file at: ${configPath}`, - ); - } - - try { - const config = JSON.parse(fileContents) as CertificateConfigFileJson; - const certPath = config?.cert_configs?.workload?.cert_path; - const keyPath = config?.cert_configs?.workload?.key_path; - - if (!certPath || !keyPath) { - throw new InvalidConfigurationError( - `Certificate config file (${configPath}) is missing required "cert_path" or "key_path" in the workload config.`, - ); - } - return {certPath, keyPath}; - } catch (e) { - if (e instanceof InvalidConfigurationError) throw e; - throw new InvalidConfigurationError( - `Failed to parse certificate config from ${configPath}: ${ - (e as Error).message - }`, - ); - } - } - - /** - * Reads and parses the cert and key files get their content and check valid format. - * @returns An object containing the cert content and key content in buffer format. - */ - async #getKeyAndCert( - certPath: string, - keyPath: string, - ): Promise<{ - cert: Buffer; - key: Buffer; - }> { - let cert, key; - try { - cert = await fs.promises.readFile(certPath); - new X509Certificate(cert); - } catch (err) { - const message = err instanceof Error ? err.message : String(err); - throw new CertificateSourceUnavailableError( - `Failed to read certificate file at ${certPath}: ${message}`, - ); - } - try { - key = await fs.promises.readFile(keyPath); - createPrivateKey(key); - } catch (err) { - const message = err instanceof Error ? err.message : String(err); - throw new CertificateSourceUnavailableError( - `Failed to read private key file at ${keyPath}: ${message}`, - ); - } - - return {cert, key}; - } - /** * Reads the leaf certificate and trust chain, combines them, * and returns a JSON array of base64-encoded certificates. diff --git a/core/packages/google-auth-library-nodejs/src/auth/computeclient.ts b/core/packages/google-auth-library-nodejs/src/auth/computeclient.ts index 36ca73d172aa..a5329e4cfa2b 100644 --- a/core/packages/google-auth-library-nodejs/src/auth/computeclient.ts +++ b/core/packages/google-auth-library-nodejs/src/auth/computeclient.ts @@ -21,6 +21,7 @@ import { OAuth2Client, OAuth2ClientOptions, } from './oauth2client'; +import {SERVICE_ACCOUNT_LOOKUP_ENDPOINT} from './regionalaccessboundary'; export interface ComputeOptions extends OAuth2ClientOptions { /** @@ -137,4 +138,45 @@ export class Compute extends OAuth2Client { } } } + + /** + * Returns the regional access boundary lookup URL for the GCE instance. + * This implementation resolves the default service account email of the GCE + * instance to construct the lookup endpoint. + * + * @return The regional access boundary URL string. + * @internal + */ + public async getRegionalAccessBoundaryUrl(): Promise { + const email = await this.resolveServiceAccountEmail(); + const regionalAccessBoundaryUrl = SERVICE_ACCOUNT_LOOKUP_ENDPOINT.replace( + '{service_account_email}', + encodeURIComponent(email), + ); + return regionalAccessBoundaryUrl; + } + + /** + * Resolves the service account email. If the email is set to 'default', + * it fetches the email from the GCE metadata server. + * @returns A promise that resolves with the service account email. + */ + private async resolveServiceAccountEmail(): Promise { + if (this.serviceAccountEmail !== 'default') { + // If a specific email is provided, return it directly. + return this.serviceAccountEmail; + } + + // Otherwise, fetch the default email from the metadata server. + try { + return await gcpMetadata.instance('service-accounts/default/email'); + } catch (e) { + throw new Error( + 'RegionalAccessBoundary: Failed to retrieve default service account email from metadata server.', + { + cause: e, + }, + ); + } + } } diff --git a/core/packages/google-auth-library-nodejs/src/auth/downscopedclient.ts b/core/packages/google-auth-library-nodejs/src/auth/downscopedclient.ts index bc0d19b16b81..cbb6a1e255b2 100644 --- a/core/packages/google-auth-library-nodejs/src/auth/downscopedclient.ts +++ b/core/packages/google-auth-library-nodejs/src/auth/downscopedclient.ts @@ -290,7 +290,7 @@ export class DownscopedClient extends AuthClient { const requestHeaders = await this.getRequestHeaders(); opts.headers = Gaxios.mergeHeaders(opts.headers); - this.addUserProjectAndAuthHeaders(opts.headers, requestHeaders); + this.applyHeadersFromSource(opts.headers, requestHeaders); response = await this.transporter.request(opts); } catch (e) { @@ -381,18 +381,4 @@ export class DownscopedClient extends AuthClient { // Return the cached access token. return this.cachedDownscopedAccessToken; } - - /** - * Returns whether the provided credentials are expired or not. - * If there is no expiry time, assumes the token is not expired or expiring. - * @param downscopedAccessToken The credentials to check for expiration. - * @return Whether the credentials are expired or not. - */ - private isExpired(downscopedAccessToken: Credentials): boolean { - const now = new Date().getTime(); - return downscopedAccessToken.expiry_date - ? now >= - downscopedAccessToken.expiry_date - this.eagerRefreshThresholdMillis - : false; - } } diff --git a/core/packages/google-auth-library-nodejs/src/auth/externalAccountAuthorizedUserClient.ts b/core/packages/google-auth-library-nodejs/src/auth/externalAccountAuthorizedUserClient.ts index 320db05546ad..59d8f42f6f43 100644 --- a/core/packages/google-auth-library-nodejs/src/auth/externalAccountAuthorizedUserClient.ts +++ b/core/packages/google-auth-library-nodejs/src/auth/externalAccountAuthorizedUserClient.ts @@ -33,6 +33,8 @@ import { EXPIRATION_TIME_OFFSET, SharedExternalAccountClientOptions, } from './baseexternalclient'; +import {WORKFORCE_LOOKUP_ENDPOINT} from './regionalaccessboundary'; +import {getWorkforcePoolIdFromAudience} from '../util'; /** * The credentials JSON file type for external account authorized user clients. @@ -159,6 +161,7 @@ export class ExternalAccountAuthorizedUserClient extends AuthClient { private cachedAccessToken: CredentialsWithResponse | null; private readonly externalAccountAuthorizedUserHandler: ExternalAccountAuthorizedUserHandler; private refreshToken: string; + private readonly audience: string; /** * Instantiates an ExternalAccountAuthorizedUserClient instances using the @@ -172,6 +175,7 @@ export class ExternalAccountAuthorizedUserClient extends AuthClient { if (options.universe_domain) { this.universeDomain = options.universe_domain; } + this.audience = options.audience; this.refreshToken = options.refresh_token; const clientAuthentication = { confidentialClientType: 'basic', @@ -218,11 +222,20 @@ export class ExternalAccountAuthorizedUserClient extends AuthClient { }; } - async getRequestHeaders(): Promise { + /** + * The main authentication interface. It takes an optional url which when + * present is the endpoint being accessed, and returns a Promise which + * resolves with authorization header fields. + * + * @param url The URI being authorized. + * @returns A promise that resolves with authorization header fields. + */ + async getRequestHeaders(url?: string | URL): Promise { const accessTokenResponse = await this.getAccessToken(); const headers = new Headers({ authorization: `Bearer ${accessTokenResponse.token}`, }); + this.applyRegionalAccessBoundary(headers, url); return this.addSharedMetadataHeaders(headers); } @@ -256,13 +269,14 @@ export class ExternalAccountAuthorizedUserClient extends AuthClient { reAuthRetried = false, ): Promise> { let response: GaxiosResponse; + const requestOpts = {...opts}; try { - const requestHeaders = await this.getRequestHeaders(); - opts.headers = Gaxios.mergeHeaders(opts.headers); + const requestHeaders = await this.getRequestHeaders(opts.url); + requestOpts.headers = Gaxios.mergeHeaders(requestOpts.headers); - this.addUserProjectAndAuthHeaders(opts.headers, requestHeaders); + this.applyHeadersFromSource(requestOpts.headers, requestHeaders); - response = await this.transporter.request(opts); + response = await this.transporter.request(requestOpts); } catch (e) { const res = (e as GaxiosError).response; if (res) { @@ -308,21 +322,34 @@ export class ExternalAccountAuthorizedUserClient extends AuthClient { if (refreshResponse.refresh_token !== undefined) { this.refreshToken = refreshResponse.refresh_token; + + // Set credentials. + this.credentials = {...this.cachedAccessToken}; + delete (this.credentials as CredentialsWithResponse).res; } return this.cachedAccessToken; } /** - * Returns whether the provided credentials are expired or not. - * If there is no expiry time, assumes the token is not expired or expiring. - * @param credentials The credentials to check for expiration. - * @return Whether the credentials are expired or not. + * Returns the regional access boundary lookup URL for the external account + * authorized user. + * This implementation constructs the lookup endpoint using the workforce + * pool ID resolved from the audience. + * + * @return The regional access boundary URL string. + * @internal */ - private isExpired(credentials: Credentials): boolean { - const now = new Date().getTime(); - return credentials.expiry_date - ? now >= credentials.expiry_date - this.eagerRefreshThresholdMillis - : false; + public async getRegionalAccessBoundaryUrl(): Promise { + const poolId = getWorkforcePoolIdFromAudience(this.audience); + if (!poolId) { + throw new Error( + `RegionalAccessBoundary: A workforce pool ID is required for regional access boundary lookups but could not be determined from the audience: ${this.audience}.`, + ); + } + return WORKFORCE_LOOKUP_ENDPOINT.replace( + '{pool_id}', + encodeURIComponent(poolId), + ); } } diff --git a/core/packages/google-auth-library-nodejs/src/auth/idtokenclient.ts b/core/packages/google-auth-library-nodejs/src/auth/idtokenclient.ts index 68303c97e36a..58ed71ae210a 100644 --- a/core/packages/google-auth-library-nodejs/src/auth/idtokenclient.ts +++ b/core/packages/google-auth-library-nodejs/src/auth/idtokenclient.ts @@ -54,7 +54,7 @@ export class IdTokenClient extends OAuth2Client { if ( !this.credentials.id_token || !this.credentials.expiry_date || - this.isTokenExpiring() + this.isExpired() ) { const idToken = await this.idTokenProvider.fetchIdToken( this.targetAudience, @@ -68,7 +68,12 @@ export class IdTokenClient extends OAuth2Client { const headers = new Headers({ authorization: 'Bearer ' + this.credentials.id_token, }); - return {headers}; + return { + headers, + // Since ID-tokens are outside RAB scope, isIDToken is used as a flag + // to avoid RAB lookup. + isIDToken: true, + }; } private getIdTokenExpiryDate(idToken: string): number | void { diff --git a/core/packages/google-auth-library-nodejs/src/auth/impersonated.ts b/core/packages/google-auth-library-nodejs/src/auth/impersonated.ts index 97742ef668b3..d146c11f31de 100644 --- a/core/packages/google-auth-library-nodejs/src/auth/impersonated.ts +++ b/core/packages/google-auth-library-nodejs/src/auth/impersonated.ts @@ -24,6 +24,7 @@ import {IdTokenProvider} from './idtokenclient'; import {GaxiosError} from 'gaxios'; import {SignBlobResponse} from './googleauth'; import {originalOrCamelOptions} from '../util'; +import {SERVICE_ACCOUNT_LOOKUP_ENDPOINT} from './regionalaccessboundary'; export interface ImpersonatedOptions extends OAuth2ClientOptions { /** @@ -202,6 +203,7 @@ export class Impersonated extends OAuth2Client implements IdTokenProvider { const tokenResponse = res.data; this.credentials.access_token = tokenResponse.accessToken; this.credentials.expiry_date = Date.parse(tokenResponse.expireTime); + return { tokens: this.credentials, res, @@ -260,4 +262,27 @@ export class Impersonated extends OAuth2Client implements IdTokenProvider { return res.data.token; } + + /** + * Returns the regional access boundary lookup URL for the impersonated + * service account. + * This implementation uses the target principal (service account email) + * to construct the lookup endpoint. + * + * @return The regional access boundary URL string. + * @internal + */ + public async getRegionalAccessBoundaryUrl(): Promise { + const targetPrincipal = this.getTargetPrincipal(); + if (!targetPrincipal) { + throw new Error( + 'RegionalAccessBoundary: A targetPrincipal is required for regional access boundary lookups but was not provided in the ImpersonatedClient options.', + ); + } + const regionalAccessBoundaryUrl = SERVICE_ACCOUNT_LOOKUP_ENDPOINT.replace( + '{service_account_email}', + encodeURIComponent(targetPrincipal), + ); + return regionalAccessBoundaryUrl; + } } diff --git a/core/packages/google-auth-library-nodejs/src/auth/jwtclient.ts b/core/packages/google-auth-library-nodejs/src/auth/jwtclient.ts index 55ce73e849e7..2f5c0bda0ec6 100644 --- a/core/packages/google-auth-library-nodejs/src/auth/jwtclient.ts +++ b/core/packages/google-auth-library-nodejs/src/auth/jwtclient.ts @@ -26,6 +26,7 @@ import { RequestMetadataResponse, } from './oauth2client'; import {DEFAULT_UNIVERSE} from './authclient'; +import {SERVICE_ACCOUNT_LOOKUP_ENDPOINT} from './regionalaccessboundary'; export interface JWTOptions extends OAuth2ClientOptions { /** @@ -147,6 +148,9 @@ export class JWT extends OAuth2Client implements IdTokenProvider { authorization: `Bearer ${tokens.id_token}`, }), ), + // Since ID-tokens are outside RAB scope, + // isIDToken is used as a flag to avoid RAB lookup. + isIDToken: true, }; } else { // no scopes have been set, but a uri has been provided. Use JWTAccess @@ -271,7 +275,7 @@ export class JWT extends OAuth2Client implements IdTokenProvider { protected async refreshTokenNoCache(): Promise { const gtoken = this.createGToken(); const token = await gtoken.getToken({ - forceRefresh: this.isTokenExpiring(), + forceRefresh: this.isExpired(), }); const tokens = { access_token: token.access_token, @@ -408,4 +412,25 @@ export class JWT extends OAuth2Client implements IdTokenProvider { } throw new Error('A key or a keyFile must be provided to getCredentials.'); } + + /** + * Returns the regional access boundary lookup URL for the service account. + * This implementation uses the configured service account email to construct + * the lookup endpoint. + * + * @return The regional access boundary URL string. + * @internal + */ + public async getRegionalAccessBoundaryUrl(): Promise { + if (!this.email) { + throw new Error( + 'RegionalAccessBoundary: An email address is required for regional access boundary lookups but was not provided in the JwtClient options.', + ); + } + const regionalAccessBoundaryUrl = SERVICE_ACCOUNT_LOOKUP_ENDPOINT.replace( + '{service_account_email}', + encodeURIComponent(this.email), + ); + return regionalAccessBoundaryUrl; + } } diff --git a/core/packages/google-auth-library-nodejs/src/auth/mtlsutils.ts b/core/packages/google-auth-library-nodejs/src/auth/mtlsutils.ts new file mode 100644 index 000000000000..bd6986e329dd --- /dev/null +++ b/core/packages/google-auth-library-nodejs/src/auth/mtlsutils.ts @@ -0,0 +1,262 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import * as fs from 'fs'; +import {createPrivateKey, X509Certificate} from 'crypto'; +import {getWellKnownCertificateConfigFileLocation, isValidFile} from '../util'; + +interface WorkloadCertConfigJson { + cert_path: string; + key_path: string; +} + +interface CertificateConfigFileJson { + version: number; + cert_configs: { + workload?: WorkloadCertConfigJson; + }; +} + +export const CERTIFICATE_CONFIGURATION_ENV_VARIABLE = + 'GOOGLE_API_CERTIFICATE_CONFIG'; + +/** + * Thrown when the certificate source cannot be located or accessed. + */ +export class CertificateSourceUnavailableError extends Error { + constructor(message: string) { + super(message); + this.name = 'CertificateSourceUnavailableError'; + } +} + +/** + * Thrown for invalid configuration that is not related to file availability. + * Re-exported for use in CertificateSubjectTokenSupplier validation. + */ +export class InvalidConfigurationError extends Error { + constructor(message: string) { + super(message); + this.name = 'InvalidConfigurationError'; + } +} + +/** + * Endpoint usage policy for mutual TLS (mTLS). + */ +export enum MtlsEndpointUsagePolicy { + ALWAYS = 'always', + NEVER = 'never', + AUTO = 'auto', +} + +/** + * Resolves the mTLS endpoint usage policy based on the `GOOGLE_API_USE_MTLS_ENDPOINT` + * environment variable. + * + * @returns The resolved MtlsEndpointUsagePolicy. + */ +export function getMtlsEndpointUsagePolicy(): MtlsEndpointUsagePolicy { + const policy = process.env.GOOGLE_API_USE_MTLS_ENDPOINT?.toLowerCase(); + if (policy === 'never') { + return MtlsEndpointUsagePolicy.NEVER; + } else if (policy === 'always') { + return MtlsEndpointUsagePolicy.ALWAYS; + } + return MtlsEndpointUsagePolicy.AUTO; +} + +/** + * Centralized helper method to determine if mutual TLS (mTLS) can be enabled. + * + * Checks for the environment policy constraints and parses the certificate configuration file. + * + * @param certConfigPathOverride Optional path to override the certificate configuration file. + * @returns A promise that resolves to `true` if mTLS can be enabled, `false` otherwise. + * @throws {Error} If a configuration file is resolved but contains malformed contents or missing files. + */ +export async function canMtlsBeEnabled( + certConfigPathOverride?: string, +): Promise { + const policy = getMtlsEndpointUsagePolicy(); + if (process.env.GOOGLE_API_USE_CLIENT_CERTIFICATE === 'false') { + if (policy === MtlsEndpointUsagePolicy.ALWAYS) { + throw new CertificateSourceUnavailableError( + 'mTLS is configured to ALWAYS, but client certificate usage was explicitly disabled via GOOGLE_API_USE_CLIENT_CERTIFICATE=false.', + ); + } + return false; + } + if (policy === MtlsEndpointUsagePolicy.NEVER) { + return false; + } + if (policy === MtlsEndpointUsagePolicy.ALWAYS) { + return true; + } + + // Check for certificate configuration file + if ( + certConfigPathOverride || + process.env[CERTIFICATE_CONFIGURATION_ENV_VARIABLE] + ) { + const configPath = + certConfigPathOverride || + process.env[CERTIFICATE_CONFIGURATION_ENV_VARIABLE]!; + if (!(await isValidFile(configPath))) { + throw new CertificateSourceUnavailableError( + `Certificate configuration file does not exist or is not a file: ${configPath}`, + ); + } + return true; + } + + const wellKnownPath = getWellKnownCertificateConfigFileLocation(); + if (await isValidFile(wellKnownPath)) { + return true; + } + + return false; +} + +/** + * Resolves the path to the certificate configuration JSON file. + * Checks the override path, standard environment variable, and well-known location. + * + * @param certConfigPathOverride Optional override path. + * @returns The resolved absolute path to the configuration file. + * @throws {CertificateSourceUnavailableError} If the configuration file cannot be found. + */ +export async function resolveCertificateConfigFilePath( + certConfigPathOverride?: string, +): Promise { + // Step 1: Check if an override path was passed directly (highest precedence) + if (certConfigPathOverride) { + if (await isValidFile(certConfigPathOverride)) { + return certConfigPathOverride; + } + throw new CertificateSourceUnavailableError( + `Provided certificate config path is invalid: ${certConfigPathOverride}`, + ); + } + + // Step 2: Check if the configuration path environment variable is defined + const envPath = process.env[CERTIFICATE_CONFIGURATION_ENV_VARIABLE]; + if (envPath) { + if (await isValidFile(envPath)) { + return envPath; + } + throw new CertificateSourceUnavailableError( + `Path from environment variable "${CERTIFICATE_CONFIGURATION_ENV_VARIABLE}" is invalid: ${envPath}`, + ); + } + + // Step 3: Check in the default well-known gcloud location (lowest precedence) + const wellKnownPath = getWellKnownCertificateConfigFileLocation(); + if (await isValidFile(wellKnownPath)) { + return wellKnownPath; + } + + // Step 4: Throw error if no configuration file could be resolved + throw new CertificateSourceUnavailableError( + 'Could not find certificate configuration file. Searched override path, ' + + `the "${CERTIFICATE_CONFIGURATION_ENV_VARIABLE}" env var, and the gcloud path (${wellKnownPath}).`, + ); +} + +/** + * Reads and parses the certificate configuration JSON file to extract the + * certificate and private key file paths from the workload configuration block. + * + * @param configPath Absolute path to the certificate config file. + * @returns The file paths to the certificate and key. + * @throws {CertificateSourceUnavailableError} If the configuration file is unreadable. + * @throws {InvalidConfigurationError} If the JSON contents are invalid or missing required paths. + */ +export async function getCertAndKeyFilePathsFromConfig( + configPath: string, +): Promise<{certPath: string; keyPath: string}> { + let fileContents: string; + try { + fileContents = await fs.promises.readFile(configPath, 'utf8'); + } catch (err) { + throw new CertificateSourceUnavailableError( + `Failed to read certificate config file at: ${configPath}`, + ); + } + + try { + const config = JSON.parse(fileContents) as CertificateConfigFileJson; + const certPath = config?.cert_configs?.workload?.cert_path; + const keyPath = config?.cert_configs?.workload?.key_path; + + if (!certPath || !keyPath) { + throw new InvalidConfigurationError( + `Certificate config file (${configPath}) is missing required "cert_path" or "key_path" in the workload config.`, + ); + } + return {certPath, keyPath}; + } catch (e) { + if ( + e instanceof InvalidConfigurationError || + e instanceof CertificateSourceUnavailableError + ) { + throw e; + } + throw new InvalidConfigurationError( + `Failed to parse certificate config from ${configPath}: ${ + (e as Error).message + }`, + ); + } +} + +/** + * Loads the actual certificate and private key bytes from disk. + * Prioritizes the configuration file. Validates the loaded files are in the correct format. + * + * @param certConfigPathOverride Optional override path. + * @returns The loaded cert and private key buffers. + * @throws {Error} If no credentials could be resolved or if validation fails. + */ +export async function getClientCertAndKey( + certConfigPathOverride?: string, +): Promise<{cert: Buffer; key: Buffer}> { + const configPath = await resolveCertificateConfigFilePath( + certConfigPathOverride, + ); + const {certPath, keyPath} = + await getCertAndKeyFilePathsFromConfig(configPath); + + let cert, key; + try { + cert = await fs.promises.readFile(certPath); + new X509Certificate(cert); + } catch (err) { + const message = err instanceof Error ? err.message : String(err); + throw new CertificateSourceUnavailableError( + `Failed to read certificate file at ${certPath}: ${message}`, + ); + } + try { + key = await fs.promises.readFile(keyPath); + createPrivateKey(key); + } catch (err) { + const message = err instanceof Error ? err.message : String(err); + throw new CertificateSourceUnavailableError( + `Failed to read private key file at ${keyPath}: ${message}`, + ); + } + + return {cert, key}; +} diff --git a/core/packages/google-auth-library-nodejs/src/auth/oauth2client.ts b/core/packages/google-auth-library-nodejs/src/auth/oauth2client.ts index 138e66c462b5..4bf698df95e9 100644 --- a/core/packages/google-auth-library-nodejs/src/auth/oauth2client.ts +++ b/core/packages/google-auth-library-nodejs/src/auth/oauth2client.ts @@ -378,6 +378,11 @@ export interface RefreshAccessTokenResponse { export interface RequestMetadataResponse { headers: Headers; res?: GaxiosResponse | null; + /** + * Whether the returned headers contain an ID token (OIDC) instead of an + * access token. ID tokens are out of scope for Regional Access Boundaries. + */ + isIDToken?: boolean; } export interface RequestMetadataCallback { @@ -901,8 +906,7 @@ export class OAuth2Client extends AuthClient { } private async getAccessTokenAsync(): Promise { - const shouldRefresh = - !this.credentials.access_token || this.isTokenExpiring(); + const shouldRefresh = !this.credentials.access_token || this.isExpired(); if (shouldRefresh) { if (!this.credentials.refresh_token) { if (this.refreshHandler) { @@ -938,7 +942,10 @@ export class OAuth2Client extends AuthClient { * { authorization: 'Bearer ' } */ async getRequestHeaders(url?: string | URL): Promise { - const headers = (await this.getRequestMetadataAsync(url)).headers; + const {headers, isIDToken} = await this.getRequestMetadataAsync(url); + if (!isIDToken) { + this.applyRegionalAccessBoundary(headers, url); + } return headers; } @@ -1118,17 +1125,23 @@ export class OAuth2Client extends AuthClient { opts: GaxiosOptions, reAuthRetried = false, ): Promise> { + const requestOpts = {...opts}; try { - const r = await this.getRequestMetadataAsync(); - opts.headers = Gaxios.mergeHeaders(opts.headers); + const {headers, isIDToken} = await this.getRequestMetadataAsync(); + requestOpts.headers = Gaxios.mergeHeaders(requestOpts.headers); - this.addUserProjectAndAuthHeaders(opts.headers, r.headers); + this.applyHeadersFromSource(requestOpts.headers, headers); if (this.apiKey) { - opts.headers.set('X-Goog-Api-Key', this.apiKey); + requestOpts.headers.set('X-Goog-Api-Key', this.apiKey); + } + + if (!isIDToken) { + // Id token flows are outside the scope of Regional Access Boundary. + this.applyRegionalAccessBoundary(requestOpts.headers, opts.url); } - return await this.transporter.request(opts); + return await this.transporter.request(requestOpts); } catch (e) { const res = (e as GaxiosError).response; if (res) { diff --git a/core/packages/google-auth-library-nodejs/src/auth/regionalaccessboundary.ts b/core/packages/google-auth-library-nodejs/src/auth/regionalaccessboundary.ts new file mode 100644 index 000000000000..57f1cc94569c --- /dev/null +++ b/core/packages/google-auth-library-nodejs/src/auth/regionalaccessboundary.ts @@ -0,0 +1,287 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import {Gaxios, GaxiosOptions} from 'gaxios'; +import {log as makeLog} from 'google-logging-utils'; +import * as https from 'https'; +import { + canMtlsBeEnabled, + getClientCertAndKey, + getMtlsEndpointUsagePolicy, + MtlsEndpointUsagePolicy, +} from './mtlsutils'; + +const log = makeLog('auth'); + +export const SERVICE_ACCOUNT_LOOKUP_ENDPOINT = + 'https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/{service_account_email}/allowedLocations'; + +export const WORKLOAD_LOOKUP_ENDPOINT = + 'https://iamcredentials.googleapis.com/v1/projects/{project_id}/locations/global/workloadIdentityPools/{pool_id}/allowedLocations'; + +export const WORKFORCE_LOOKUP_ENDPOINT = + 'https://iamcredentials.googleapis.com/v1/locations/global/workforcePools/{pool_id}/allowedLocations'; + +/** + * RAB is considered valid for 6 hours. + */ +const RAB_TTL_MILLIS = 6 * 60 * 60 * 1000; + +/** + * Grace period before hard expiry to trigger a background refresh (1 hour). + */ +const RAB_SOFT_EXPIRY_GRACE_PERIOD_MILLIS = 1 * 60 * 60 * 1000; + +/** + * Initial cooldown period for RAB lookup failures (15 minutes). + */ +const RAB_INITIAL_COOLDOWN_MILLIS = 15 * 60 * 1000; + +/** + * Maximum cooldown period for RAB lookup failures. + * Set as 6 hours. + */ +const RAB_MAX_COOLDOWN_MILLIS = 6 * 60 * 60 * 1000; + +/** + * Holds regional access boundary related information like locations + * where the credentials can be used. + */ +export interface RegionalAccessBoundaryData { + /** + * The readable text format of the allowed regional access boundary locations. + */ + locations?: string[]; + + /** + * The encoded text format of allowed regional access boundary locations. + */ + encodedLocations: string; +} + +export interface RegionalAccessBoundaryManagerOptions { + transporter: Gaxios; + getLookupUrl: () => Promise; + isUniverseDomainDefault: () => boolean; +} + +export class RegionalAccessBoundaryManager { + private regionalAccessBoundary: RegionalAccessBoundaryData | null = null; + private regionalAccessBoundaryExpiry = 0; + private regionalAccessBoundaryRefreshPromise: Promise | null = null; + private regionalAccessBoundaryCooldownTime = 0; + private regionalAccessBoundaryCooldownBackoff = RAB_INITIAL_COOLDOWN_MILLIS; + private options: RegionalAccessBoundaryManagerOptions; + + constructor(options: RegionalAccessBoundaryManagerOptions) { + this.options = options; + } + + /** + * @internal + */ + get data(): RegionalAccessBoundaryData | null { + return this.regionalAccessBoundary; + } + + /** + * @internal + */ + get cooldownTime(): number { + return this.regionalAccessBoundaryCooldownTime; + } + + /** + * Returns the encoded locations string if the RAB is active and valid. + * Also triggers a background refresh if needed. + * @param url Optional endpoint URL being accessed. If missing, assumed global. + * @param headers The headers of the current request. + */ + getRegionalAccessBoundaryHeader( + url: string | URL | undefined, + headers: Headers, + ): string | null { + if (!this.options.isUniverseDomainDefault()) { + return null; + } + + // Only attach/refresh for global endpoints + if (url && !this.isGlobalEndpoint(url)) { + return null; + } + + // Attempt to trigger refresh if we have a token. + const authHeader = headers.get('authorization'); + if (authHeader && authHeader.startsWith('Bearer ')) { + // authHeader.substring(7) as auth header is of type 'Bearer XYZ...' + this.maybeTriggerRegionalAccessBoundaryRefresh(authHeader.substring(7)); + } + + if ( + this.regionalAccessBoundary && + this.regionalAccessBoundary.encodedLocations && + Date.now() < this.regionalAccessBoundaryExpiry + ) { + return this.regionalAccessBoundary.encodedLocations; + } + return null; + } + + /** + * Checks if the given URL is a global endpoint (not regional). + * @param url The URL to check. + */ + private isGlobalEndpoint(url: string | URL): boolean { + try { + const hostname = + url instanceof URL ? url.hostname : new URL(url).hostname; + return ( + !hostname.endsWith('.rep.googleapis.com') && + !hostname.endsWith('.rep.sandbox.googleapis.com') + ); + } catch { + // If the URL is relative or malformed, assume it is global. + return true; + } + } + + /** + * Triggers an asynchronous regional access boundary refresh if needed. + * @param accessToken The access token to use for the lookup. + */ + private maybeTriggerRegionalAccessBoundaryRefresh(accessToken: string): void { + if (this.regionalAccessBoundaryRefreshPromise) { + return; + } + + const now = Date.now(); + + // Check if in cooldown + if (now < this.regionalAccessBoundaryCooldownTime) { + return; + } + + // Check if expired or never fetched (using soft expiry grace period) + const softExpiryThreshold = + this.regionalAccessBoundaryExpiry - RAB_SOFT_EXPIRY_GRACE_PERIOD_MILLIS; + if (!this.regionalAccessBoundary || now >= softExpiryThreshold) { + this.regionalAccessBoundaryRefreshPromise = + this.backgroundRefreshRegionalAccessBoundary(accessToken); + } + } + + /** + * Performs the background refresh of the regional access boundary. + * @param accessToken The access token to use for the lookup. + */ + private async backgroundRefreshRegionalAccessBoundary( + accessToken: string, + ): Promise { + try { + const data = await this.fetchRegionalAccessBoundary(accessToken); + if (data) { + this.regionalAccessBoundary = data; + this.regionalAccessBoundaryExpiry = Date.now() + RAB_TTL_MILLIS; + // Reset cooldown on success. + this.regionalAccessBoundaryCooldownTime = 0; + this.regionalAccessBoundaryCooldownBackoff = + RAB_INITIAL_COOLDOWN_MILLIS; + } + } catch (error) { + // Non-retryable or all retries failed: enter cooldown, + // initially for 15 mins which doubles after each failed cooldown 'exit' attempt. + this.regionalAccessBoundaryCooldownTime = + Date.now() + this.regionalAccessBoundaryCooldownBackoff; + this.regionalAccessBoundaryCooldownBackoff = Math.min( + this.regionalAccessBoundaryCooldownBackoff * 2, + RAB_MAX_COOLDOWN_MILLIS, + ); + log.error( + 'RegionalAccessBoundary: Lookup failed. Entering cooldown.', + error, + ); + } finally { + this.regionalAccessBoundaryRefreshPromise = null; + } + } + + /** + * Internal method to fetch RAB data. + * Retries for retryable 5xx errors from the RAB lookup endpoint. + * Throws if response from lookup is malformed. + */ + private async fetchRegionalAccessBoundary( + accessToken?: string, + ): Promise { + let regionalAccessBoundaryUrl = await this.options.getLookupUrl(); + if (!regionalAccessBoundaryUrl) { + return null; + } + + if (!accessToken) { + throw new Error( + 'RegionalAccessBoundary: Error calling lookup endpoint without valid access token', + ); + } + + const headers = new Headers({ + authorization: 'Bearer ' + accessToken, + }); + + const opts: GaxiosOptions = { + retry: true, + retryConfig: { + retry: 9, // Approximately 1 minute with default exponential backoff + retryDelay: 100, + httpMethodsToRetry: ['GET'], + statusCodesToRetry: [ + [500, 500], + [502, 504], + ], + }, + headers, + url: regionalAccessBoundaryUrl, + }; + + // If mTLS can be enabled, use mTLS agent and switch to the mTLS endpoint + try { + if (await canMtlsBeEnabled()) { + const {cert, key} = await getClientCertAndKey(); + opts.agent = new https.Agent({cert, key}); + regionalAccessBoundaryUrl = regionalAccessBoundaryUrl.replace( + 'iamcredentials.googleapis.com', + 'iamcredentials.mtls.googleapis.com', + ); + opts.url = regionalAccessBoundaryUrl; + } + } catch (e) { + log.error('RegionalAccessBoundary: Failed to initialize mTLS: ', e); + // If mTLS is configured to ALWAYS, propagate the error instead of falling back to the standard endpoint. + if (getMtlsEndpointUsagePolicy() === MtlsEndpointUsagePolicy.ALWAYS) { + throw e; + } + } + + const {data: regionalAccessBoundaryData} = + await this.options.transporter.request(opts); + + if (!regionalAccessBoundaryData.encodedLocations) { + throw new Error( + 'RegionalAccessBoundary: Malformed response from lookup endpoint.', + ); + } + + return regionalAccessBoundaryData; + } +} diff --git a/core/packages/google-auth-library-nodejs/src/util.ts b/core/packages/google-auth-library-nodejs/src/util.ts index 238ab604b109..0d9081c4c2dc 100644 --- a/core/packages/google-auth-library-nodejs/src/util.ts +++ b/core/packages/google-auth-library-nodejs/src/util.ts @@ -300,3 +300,40 @@ export function getWellKnownCertificateConfigFileLocation(): string { function _isWindows(): boolean { return os.platform().startsWith('win'); } + +/** + * Returns the workforce identity pool ID if it is determinable + * from the audience resource name. + * @param audience The audience used to determine the pool ID. + * @return The pool ID associated with the workforce identity pool, if + * this can be determined from the audience field. Otherwise, null is + * returned. + */ +export function getWorkforcePoolIdFromAudience( + audience: string, +): string | null { + // STS audience pattern: + // .../workforcePools/$WORKFORCE_POOL_ID/providers/... + return ( + audience.match(/\/workforcePools\/(?[^/]+)\/providers\//)?.groups + ?.poolId ?? null + ); +} + +/** + * Returns the workload identity pool ID if it is determinable + * from the audience resource name. + * @param audience The audience used to determine the pool ID. + * @return The pool ID associated with the workload identity pool, if + * this can be determined from the audience field. Otherwise, null is + * returned. + */ +export function getWorkloadPoolIdFromAudience(audience: string): string | null { + // STS audience pattern: + // .../workloadIdentityPools/POOL_ID/providers/... + return ( + audience.match( + /\/workloadIdentityPools\/(?[^/]+)\/providers\//, + )?.groups?.workloadPool ?? null + ); +} diff --git a/core/packages/google-auth-library-nodejs/test/test.authclient.ts b/core/packages/google-auth-library-nodejs/test/test.authclient.ts index 22b2528c6497..a288fee4cde0 100644 --- a/core/packages/google-auth-library-nodejs/test/test.authclient.ts +++ b/core/packages/google-auth-library-nodejs/test/test.authclient.ts @@ -13,7 +13,6 @@ // limitations under the License. import {strict as assert} from 'assert'; - import * as nock from 'nock'; import { Gaxios, @@ -23,10 +22,16 @@ import { GaxiosResponse, } from 'gaxios'; -import {AuthClient, PassThroughClient} from '../src'; +import {AuthClient, Compute, PassThroughClient} from '../src'; import {snakeToCamel} from '../src/util'; import {PRODUCT_NAME, USER_AGENT} from '../src/shared.cjs'; import * as logging from 'google-logging-utils'; +import {BASE_PATH, HOST_ADDRESS, HEADERS} from 'gcp-metadata'; +import sinon = require('sinon'); +import { + RegionalAccessBoundaryData, + SERVICE_ACCOUNT_LOOKUP_ENDPOINT, +} from '../src/auth/regionalaccessboundary'; // Fakes for the logger, to capture logs that would've happened. interface TestLog { @@ -54,6 +59,22 @@ class TestLogSink implements logging.DebugLogBackend { } describe('AuthClient', () => { + let sandbox: sinon.SinonSandbox; + + beforeEach(() => { + sandbox = sinon.createSandbox(); + sandbox.stub(process, 'env').value({ + ...process.env, + GOOGLE_API_USE_CLIENT_CERTIFICATE: undefined, + GOOGLE_API_CERTIFICATE_CONFIG: undefined, + }); + }); + + afterEach(() => { + sandbox.restore(); + nock.cleanAll(); + }); + it('should accept and normalize snake case options to camel case', () => { const expected = { project_id: 'my-projectId', @@ -376,5 +397,217 @@ describe('AuthClient', () => { }); }); }); + + describe('regional access boundaries', () => { + const MOCK_ACCESS_TOKEN = 'abc123'; + const SERVICE_ACCOUNT_EMAIL = 'service-account@example.com'; + const EXPECTED_RAB_DATA: RegionalAccessBoundaryData = { + locations: ['us-central1', 'europe-west1'], + encodedLocations: '0x123', + }; + + function setupTokenNock( + email: string | 'default' = 'default', + ): nock.Scope { + const tokenPath = + email === 'default' + ? `${BASE_PATH}/instance/service-accounts/default/token` + : `${BASE_PATH}/instance/service-accounts/${email}/token`; + return nock(HOST_ADDRESS) + .get(tokenPath) + .reply( + 200, + {access_token: MOCK_ACCESS_TOKEN, expires_in: 10000}, + HEADERS, + ); + } + + it('should trigger asynchronous background refresh and not block', async () => { + const compute = new Compute({ + serviceAccountEmail: SERVICE_ACCOUNT_EMAIL, + }); + // Set up nocks + const tokenScope = setupTokenNock(SERVICE_ACCOUNT_EMAIL); + // Use a promise to track when the RAB lookup is actually called + let rabLookupCalled = false; + const rabUrl = SERVICE_ACCOUNT_LOOKUP_ENDPOINT.replace( + '{service_account_email}', + encodeURIComponent(SERVICE_ACCOUNT_EMAIL), + ); + + const rabScope = nock(new URL(rabUrl).origin) + .get(new URL(rabUrl).pathname) + .reply(() => { + rabLookupCalled = true; + return [200, EXPECTED_RAB_DATA]; + }); + + // Initial call - should NOT have the header yet because refresh is async + const headers = await compute.getRequestHeaders( + 'https://pubsub.googleapis.com', + ); + + assert.strictEqual(headers.get('x-allowed-locations'), null); + + // Wait for the background task to complete (not ideal but necessary for testing side effect) + // In a real scenario we'd use a better way to wait for the internal promise + let attempts = 0; + while (!rabLookupCalled && attempts < 10) { + await new Promise(r => setTimeout(r, 50)); + attempts++; + } + + assert.strictEqual(rabLookupCalled, true); + + // Give the background processing a moment to update the class member + await new Promise(r => setTimeout(r, 50)); + assert.deepStrictEqual( + compute.getRegionalAccessBoundary(), + EXPECTED_RAB_DATA, + ); + + tokenScope.done(); + rabScope.done(); + }); + + it('should NOT trigger lookup for regional endpoints', async () => { + const compute = new Compute({ + serviceAccountEmail: SERVICE_ACCOUNT_EMAIL, + }); + + const tokenScope = setupTokenNock(SERVICE_ACCOUNT_EMAIL); + // No RAB nock setup here. If it's called, nock will throw. + + await compute.getRequestHeaders('https://us-east1.rep.googleapis.com'); + + tokenScope.done(); + // Assert no RAB lookup was attempted (implicitly verified by lack of nock error) + }); + + it('should NOT trigger lookup for non-GDU universes', async () => { + const compute = new Compute({ + serviceAccountEmail: SERVICE_ACCOUNT_EMAIL, + universe_domain: 'custom-universe.com', + }); + + const tokenScope = setupTokenNock(SERVICE_ACCOUNT_EMAIL); + + await compute.getRequestHeaders('https://pubsub.googleapis.com'); + + tokenScope.done(); + // Assert no RAB lookup was attempted + }); + + it('should NOT crash and should trigger lookup for relative URLs', async () => { + const compute = new Compute({ + serviceAccountEmail: SERVICE_ACCOUNT_EMAIL, + }); + + const tokenScope = setupTokenNock(SERVICE_ACCOUNT_EMAIL); + // If it treats the relative URL as global, it should try to call the RAB endpoint. + const rabUrl = SERVICE_ACCOUNT_LOOKUP_ENDPOINT.replace( + '{universe_domain}', + 'googleapis.com', + ).replace( + '{service_account_email}', + encodeURIComponent(SERVICE_ACCOUNT_EMAIL), + ); + + const rabScope = nock(new URL(rabUrl).origin) + .get(new URL(rabUrl).pathname) + .reply(200, EXPECTED_RAB_DATA); + + // This should NOT throw even though '/v1/resource' is relative + await compute.getRequestHeaders('/v1/resource'); + + // Wait for the background task to complete + let attempts = 0; + while (!compute.getRegionalAccessBoundary() && attempts < 10) { + await new Promise(r => setTimeout(r, 50)); + attempts++; + } + + assert.deepStrictEqual( + compute.getRegionalAccessBoundary(), + EXPECTED_RAB_DATA, + ); + + tokenScope.done(); + rabScope.done(); + }); + + it('should retry on retryable errors in background', async () => { + const compute = new Compute({ + serviceAccountEmail: SERVICE_ACCOUNT_EMAIL, + }); + + setupTokenNock(SERVICE_ACCOUNT_EMAIL); + + // Mock 503 then 200 + const rabUrl = SERVICE_ACCOUNT_LOOKUP_ENDPOINT.replace( + '{service_account_email}', + encodeURIComponent(SERVICE_ACCOUNT_EMAIL), + ); + + const rabFail = nock(new URL(rabUrl).origin) + .get(new URL(rabUrl).pathname) + .reply(503); + const rabSuccess = nock(new URL(rabUrl).origin) + .get(new URL(rabUrl).pathname) + .reply(200, EXPECTED_RAB_DATA); + + await compute.getRequestHeaders('https://pubsub.googleapis.com'); + + // Wait for retries (exponential backoff might take a moment) + let attempts = 0; + while (!compute.getRegionalAccessBoundary() && attempts < 20) { + await new Promise(r => setTimeout(r, 150)); + attempts++; + } + + assert.deepStrictEqual( + compute.getRegionalAccessBoundary(), + EXPECTED_RAB_DATA, + ); + rabFail.done(); + rabSuccess.done(); + }); + + it('should enter cooldown on non-retryable error', async () => { + const compute = new Compute({ + serviceAccountEmail: SERVICE_ACCOUNT_EMAIL, + }); + + setupTokenNock(SERVICE_ACCOUNT_EMAIL); + + const rabUrl = SERVICE_ACCOUNT_LOOKUP_ENDPOINT.replace( + '{service_account_email}', + encodeURIComponent(SERVICE_ACCOUNT_EMAIL), + ); + + const rabFail = nock(new URL(rabUrl).origin) + .get(new URL(rabUrl).pathname) + .reply(400, {error: 'Permanent failure'}); + + await compute.getRequestHeaders('https://pubsub.googleapis.com'); + + // Wait for it to fail and enter cooldown + let attempts = 0; + while ( + !compute.getRegionalAccessBoundaryCooldownTime() && + attempts < 10 + ) { + await new Promise(r => setTimeout(r, 50)); + attempts++; + } + + assert.ok(compute.getRegionalAccessBoundaryCooldownTime() > Date.now()); + + // Subsequent call should NOT trigger nock (which would fail as we only set up 1) + await compute.getRequestHeaders('https://pubsub.googleapis.com'); + + rabFail.done(); + }); + }); }); }); diff --git a/core/packages/google-auth-library-nodejs/test/test.baseexternalclient.ts b/core/packages/google-auth-library-nodejs/test/test.baseexternalclient.ts index 3020b47cd49e..2f079f57cf57 100644 --- a/core/packages/google-auth-library-nodejs/test/test.baseexternalclient.ts +++ b/core/packages/google-auth-library-nodejs/test/test.baseexternalclient.ts @@ -38,9 +38,16 @@ import { mockGenerateAccessToken, mockStsTokenExchange, getExpectedExternalAccountMetricsHeaderValue, + saEmail, } from './externalclienthelper'; import {DEFAULT_UNIVERSE} from '../src/auth/authclient'; import {TestUtils} from './utils'; +import { + RegionalAccessBoundaryData, + SERVICE_ACCOUNT_LOOKUP_ENDPOINT, + WORKFORCE_LOOKUP_ENDPOINT, + WORKLOAD_LOOKUP_ENDPOINT, +} from '../src/auth/regionalaccessboundary'; nock.disableNetConnect(); interface SampleResponse { @@ -155,11 +162,25 @@ describe('BaseExternalAccountClient', () => { '//iam.googleapis.com/projects_suffix/123456', ]; + let sandbox: sinon.SinonSandbox; + beforeEach(() => { + sandbox = sinon.createSandbox(); + sandbox.stub(process, 'env').value({ + ...process.env, + GOOGLE_API_USE_CLIENT_CERTIFICATE: undefined, + GOOGLE_API_CERTIFICATE_CONFIG: undefined, + }); + sandbox + .stub(BaseExternalAccountClient.prototype, 'getRegionalAccessBoundaryUrl') + .resolves(undefined); + }); + afterEach(() => { nock.cleanAll(); if (clock) { clock.restore(); } + sandbox.restore(); }); describe('Constructor', () => { @@ -2706,4 +2727,234 @@ describe('BaseExternalAccountClient', () => { ); }); }); + + describe('regional access boundaries', () => { + const MOCK_ACCESS_TOKEN = 'ACCESS_TOKEN'; + const MOCK_AUTH_HEADER = `Bearer ${MOCK_ACCESS_TOKEN}`; + const EXPECTED_RAB_DATA: RegionalAccessBoundaryData = { + locations: ['some-locations'], + encodedLocations: '0xdeadbeef', + }; + + beforeEach(() => { + ( + BaseExternalAccountClient.prototype + .getRegionalAccessBoundaryUrl as sinon.SinonStub + ).restore(); + }); + + afterEach(() => { + nock.cleanAll(); + }); + + it('should trigger asynchronous RAB refresh for workload identity', async () => { + const projectNumber = '12345'; + const workloadPoolId = 'my-pool'; + const workloadAudience = `//iam.googleapis.com/projects/${projectNumber}/locations/global/workloadIdentityPools/${workloadPoolId}/providers/my-provider`; + const workloadOptions = { + ...externalAccountOptions, + audience: workloadAudience, + }; + const client = new TestExternalAccountClient(workloadOptions); + + const stsScope = mockStsTokenExchange([ + { + statusCode: 200, + response: {...stsSuccessfulResponse, access_token: MOCK_ACCESS_TOKEN}, + request: { + grant_type: 'urn:ietf:params:oauth:grant-type:token-exchange', + audience: workloadAudience, + scope: 'https://www.googleapis.com/auth/cloud-platform', + requested_token_type: + 'urn:ietf:params:oauth:token-type:access_token', + subject_token: 'subject_token_0', + subject_token_type: 'urn:ietf:params:oauth:token-type:jwt', + }, + }, + ]); + + const lookupUrl = WORKLOAD_LOOKUP_ENDPOINT.replace( + '{project_id}', + projectNumber, + ).replace('{pool_id}', workloadPoolId); + + let rabLookupCalled = false; + const rabScope = nock(new URL(lookupUrl).origin) + .get(new URL(lookupUrl).pathname) + .matchHeader('authorization', MOCK_AUTH_HEADER) + .reply(() => { + rabLookupCalled = true; + return [200, EXPECTED_RAB_DATA]; + }); + + // Initial call - should NOT have the header yet + const headers = await client.getRequestHeaders(); + assert.strictEqual(headers.get('x-allowed-locations'), null); + + // Wait for background lookup + let attempts = 0; + while (!rabLookupCalled && attempts < 10) { + await new Promise(r => setTimeout(r, 50)); + attempts++; + } + assert.strictEqual(rabLookupCalled, true); + + await new Promise(r => setTimeout(r, 50)); + assert.deepStrictEqual( + client.getRegionalAccessBoundary(), + EXPECTED_RAB_DATA, + ); + + stsScope.done(); + rabScope.done(); + }); + + it('should trigger asynchronous RAB refresh for workforce identity', async () => { + const workforcePoolId = 'my-workforce-pool'; + const location = 'global'; + const workforceAudience = `//iam.googleapis.com/locations/${location}/workforcePools/${workforcePoolId}/providers/my-provider`; + const workforceOptions = { + ...externalAccountOptions, + audience: workforceAudience, + }; + const client = new TestExternalAccountClient(workforceOptions); + + const stsScope = mockStsTokenExchange([ + { + statusCode: 200, + response: {...stsSuccessfulResponse, access_token: MOCK_ACCESS_TOKEN}, + request: { + grant_type: 'urn:ietf:params:oauth:grant-type:token-exchange', + audience: workforceAudience, + scope: 'https://www.googleapis.com/auth/cloud-platform', + requested_token_type: + 'urn:ietf:params:oauth:token-type:access_token', + subject_token: 'subject_token_0', + subject_token_type: 'urn:ietf:params:oauth:token-type:jwt', + }, + }, + ]); + + const lookupUrl = WORKFORCE_LOOKUP_ENDPOINT.replace( + '{location}', + location, + ).replace('{pool_id}', workforcePoolId); + + let rabLookupCalled = false; + const rabScope = nock(new URL(lookupUrl).origin) + .get(new URL(lookupUrl).pathname) + .matchHeader('authorization', MOCK_AUTH_HEADER) + .reply(() => { + rabLookupCalled = true; + return [200, EXPECTED_RAB_DATA]; + }); + + const headers = await client.getRequestHeaders(); + assert.strictEqual(headers.get('x-allowed-locations'), null); + + let attempts = 0; + while (!rabLookupCalled && attempts < 10) { + await new Promise(r => setTimeout(r, 50)); + attempts++; + } + assert.strictEqual(rabLookupCalled, true); + + await new Promise(r => setTimeout(r, 50)); + assert.deepStrictEqual( + client.getRegionalAccessBoundary(), + EXPECTED_RAB_DATA, + ); + + stsScope.done(); + rabScope.done(); + }); + + it('should fail background lookup for an invalid audience', async () => { + const invalidAudience = 'invalid-audience-format/providers/1235'; + const invalidOptions = { + ...externalAccountOptions, + audience: invalidAudience, + }; + const client = new TestExternalAccountClient(invalidOptions); + + // Note: background refresh fails silently in terms of getRequestHeaders resolving. + // But we can manually trigger getRegionalAccessBoundaryUrl to verify it throws. + await assert.rejects( + client.getRegionalAccessBoundaryUrl(), + /RegionalAccessBoundary: Invalid audience provided/, + ); + }); + + it('should trigger asynchronous RAB refresh for impersonated service account', async () => { + const projectNumber = '12345'; + const workloadPoolId = 'my-pool'; + const workloadAudience = `//iam.googleapis.com/projects/${projectNumber}/locations/global/workloadIdentityPools/${workloadPoolId}/providers/my-provider`; + const workloadOptions = { + ...externalAccountOptionsWithSA, + audience: workloadAudience, + }; + const client = new TestExternalAccountClient(workloadOptions); + + const stsScope = mockStsTokenExchange([ + { + statusCode: 200, + response: {...stsSuccessfulResponse, access_token: MOCK_ACCESS_TOKEN}, + request: { + grant_type: 'urn:ietf:params:oauth:grant-type:token-exchange', + audience: workloadAudience, + scope: 'https://www.googleapis.com/auth/cloud-platform', + requested_token_type: + 'urn:ietf:params:oauth:token-type:access_token', + subject_token: 'subject_token_0', + subject_token_type: 'urn:ietf:params:oauth:token-type:jwt', + }, + }, + ]); + + const saSuccessResponse = { + accessToken: 'SA_ACCESS_TOKEN', + expireTime: new Date(Date.now() + 60 * 60 * 100).toISOString(), + }; + const impersonatedScope = mockGenerateAccessToken({ + statusCode: 200, + response: saSuccessResponse, + token: stsSuccessfulResponse.access_token, + scopes: ['https://www.googleapis.com/auth/cloud-platform'], + }); + + const lookupUrl = SERVICE_ACCOUNT_LOOKUP_ENDPOINT.replace( + '{service_account_email}', + encodeURIComponent(saEmail), + ); + + let rabLookupCalled = false; + const rabScope = nock(new URL(lookupUrl).origin) + .get(new URL(lookupUrl).pathname) + .matchHeader('authorization', `Bearer ${saSuccessResponse.accessToken}`) + .reply(() => { + rabLookupCalled = true; + return [200, EXPECTED_RAB_DATA]; + }); + + const headers = await client.getRequestHeaders(); + assert.strictEqual(headers.get('x-allowed-locations'), null); + + let attempts = 0; + while (!rabLookupCalled && attempts < 10) { + await new Promise(r => setTimeout(r, 50)); + attempts++; + } + assert.strictEqual(rabLookupCalled, true); + + await new Promise(r => setTimeout(r, 50)); + assert.deepStrictEqual( + client.getRegionalAccessBoundary(), + EXPECTED_RAB_DATA, + ); + + stsScope.done(); + rabScope.done(); + impersonatedScope.done(); + }); + }); }); diff --git a/core/packages/google-auth-library-nodejs/test/test.compute.ts b/core/packages/google-auth-library-nodejs/test/test.compute.ts index 981eac6c4f69..c1c1b0104940 100644 --- a/core/packages/google-auth-library-nodejs/test/test.compute.ts +++ b/core/packages/google-auth-library-nodejs/test/test.compute.ts @@ -17,7 +17,11 @@ import {describe, it, beforeEach, afterEach} from 'mocha'; import {BASE_PATH, HEADERS, HOST_ADDRESS} from 'gcp-metadata'; import * as nock from 'nock'; import * as sinon from 'sinon'; -import {Compute} from '../src'; +import {Compute, gcpMetadata} from '../src'; +import { + SERVICE_ACCOUNT_LOOKUP_ENDPOINT, + RegionalAccessBoundaryData, +} from '../src/auth/regionalaccessboundary'; nock.disableNetConnect(); @@ -43,7 +47,15 @@ describe('compute', () => { const sandbox = sinon.createSandbox(); let compute: Compute; beforeEach(() => { + sandbox.stub(process, 'env').value({ + ...process.env, + GOOGLE_API_USE_CLIENT_CERTIFICATE: undefined, + GOOGLE_API_CERTIFICATE_CONFIG: undefined, + }); compute = new Compute(); + sandbox + .stub(Compute.prototype, 'getRegionalAccessBoundaryUrl') + .resolves(undefined); }); afterEach(() => { @@ -261,4 +273,166 @@ describe('compute', () => { assert.fail('failed to throw'); }); + describe('regional access boundaries', () => { + const MOCK_ACCESS_TOKEN = 'abc123'; + const MOCK_AUTH_HEADER = `Bearer ${MOCK_ACCESS_TOKEN}`; + const EXPECTED_RAB_DATA: RegionalAccessBoundaryData = { + locations: ['sadad', 'asdad'], + encodedLocations: '000x9', + }; + + function setupTokenNock(email: string | 'default' = 'default'): nock.Scope { + const tokenPath = + email === 'default' + ? `${BASE_PATH}/instance/service-accounts/default/token` + : `${BASE_PATH}/instance/service-accounts/${email}/token`; + return nock(HOST_ADDRESS) + .get(tokenPath) + .reply( + 200, + {access_token: MOCK_ACCESS_TOKEN, expires_in: 10000}, + HEADERS, + ); + } + + function setupRegionalAccessBoundaryNock( + email: string, + regionalAccessBoundaryData: RegionalAccessBoundaryData = EXPECTED_RAB_DATA, + ): nock.Scope { + const lookupUrl = SERVICE_ACCOUNT_LOOKUP_ENDPOINT.replace( + '{service_account_email}', + encodeURIComponent(email), + ); + return nock(new URL(lookupUrl).origin) + .get(new URL(lookupUrl).pathname) + .matchHeader('authorization', MOCK_AUTH_HEADER) + .reply(200, regionalAccessBoundaryData); + } + + beforeEach(() => { + ( + Compute.prototype.getRegionalAccessBoundaryUrl as sinon.SinonStub + ).restore(); + }); + + afterEach(() => { + nock.cleanAll(); + }); + + it('should trigger asynchronous RAB refresh using email from metadata server', async () => { + const compute = new Compute(); + const fakeEmail = 'fake-default-sa@developer.gserviceaccount.com'; + const metadataStub = sandbox.stub(gcpMetadata, 'instance'); + metadataStub.callThrough(); + metadataStub + .withArgs('service-accounts/default/email') + .resolves(fakeEmail); + + const tokenScope = setupTokenNock('default'); + const rabScope = setupRegionalAccessBoundaryNock(fakeEmail); + let rabLookupCalled = false; + rabScope.on('request', () => { + rabLookupCalled = true; + }); + + const url = 'https://pubsub.googleapis.com'; + const headers = await compute.getRequestHeaders(url); + + // Initial headers should NOT have RAB + assert.strictEqual(headers.get('x-allowed-locations'), null); + + // Wait for background tasks (email resolution + RAB lookup) + let attempts = 0; + while (!rabLookupCalled && attempts < 10) { + await new Promise(r => setTimeout(r, 100)); + attempts++; + } + assert.strictEqual(rabLookupCalled, true); + + await new Promise(r => setTimeout(r, 50)); + assert.deepStrictEqual( + compute.getRegionalAccessBoundary(), + EXPECTED_RAB_DATA, + ); + + tokenScope.done(); + rabScope.done(); + }); + + it('should trigger asynchronous RAB refresh using mTLS when enabled', async () => { + const compute = new Compute(); + const fakeEmail = 'fake-default-sa@developer.gserviceaccount.com'; + const metadataStub = sandbox.stub(gcpMetadata, 'instance'); + metadataStub.callThrough(); + metadataStub + .withArgs('service-accounts/default/email') + .resolves(fakeEmail); + + process.env.GOOGLE_API_USE_CLIENT_CERTIFICATE = 'true'; + process.env.GOOGLE_API_CERTIFICATE_CONFIG = + './test/fixtures/external-account-cert/cert_config.json'; + + const tokenScope = setupTokenNock('default'); + + // The lookup url should be replaced with iamcredentials.mtls.googleapis.com + const lookupUrl = SERVICE_ACCOUNT_LOOKUP_ENDPOINT.replace( + '{service_account_email}', + encodeURIComponent(fakeEmail), + ).replace( + 'iamcredentials.googleapis.com', + 'iamcredentials.mtls.googleapis.com', + ); + + const rabScope = nock(new URL(lookupUrl).origin) + .get(new URL(lookupUrl).pathname) + .matchHeader('authorization', MOCK_AUTH_HEADER) + .reply(200, EXPECTED_RAB_DATA); + + let rabLookupCalled = false; + rabScope.on('request', () => { + rabLookupCalled = true; + }); + + const url = 'https://pubsub.googleapis.com'; + const headers = await compute.getRequestHeaders(url); + + assert.strictEqual(headers.get('x-allowed-locations'), null); + + let attempts = 0; + while (!rabLookupCalled && attempts < 10) { + await new Promise(r => setTimeout(r, 100)); + attempts++; + } + assert.strictEqual(rabLookupCalled, true); + + await new Promise(r => setTimeout(r, 50)); + assert.deepStrictEqual( + compute.getRegionalAccessBoundary(), + EXPECTED_RAB_DATA, + ); + + tokenScope.done(); + rabScope.done(); + + delete process.env.GOOGLE_API_USE_CLIENT_CERTIFICATE; + delete process.env.GOOGLE_API_CERTIFICATE_CONFIG; + }); + + it('should fail getRegionalAccessBoundaryUrl in background if metadata call fails', async () => { + const compute = new Compute(); + + const metadataStub = sandbox.stub(gcpMetadata, 'instance'); + metadataStub.callThrough(); + metadataStub + .withArgs('service-accounts/default/email') + .rejects(new Error('metadata failure')); + + // Error happens in background, so getRequestHeaders resolves fine. + // We manually call getRegionalAccessBoundaryUrl to verify the failure logic. + await assert.rejects( + compute.getRegionalAccessBoundaryUrl(), + /RegionalAccessBoundary: Failed to retrieve default service account email from metadata server./, + ); + }); + }); }); diff --git a/core/packages/google-auth-library-nodejs/test/test.externalaccountauthorizeduserclient.ts b/core/packages/google-auth-library-nodejs/test/test.externalaccountauthorizeduserclient.ts index e5aca190ebc9..713941f8d1ef 100644 --- a/core/packages/google-auth-library-nodejs/test/test.externalaccountauthorizeduserclient.ts +++ b/core/packages/google-auth-library-nodejs/test/test.externalaccountauthorizeduserclient.ts @@ -17,7 +17,7 @@ import {describe, it, afterEach, beforeEach} from 'mocha'; import * as nock from 'nock'; import * as sinon from 'sinon'; import * as qs from 'querystring'; -import {assertGaxiosResponsePresent, getAudience} from './externalclienthelper'; +import {assertGaxiosResponsePresent} from './externalclienthelper'; import { EXTERNAL_ACCOUNT_AUTHORIZED_USER_TYPE, ExternalAccountAuthorizedUserClient, @@ -31,6 +31,10 @@ import { } from '../src/auth/oauth2common'; import {DEFAULT_UNIVERSE} from '../src/auth/authclient'; import {TestUtils} from './utils'; +import { + RegionalAccessBoundaryData, + WORKFORCE_LOOKUP_ENDPOINT, +} from '../src/auth/regionalaccessboundary'; nock.disableNetConnect(); @@ -83,10 +87,11 @@ describe('ExternalAccountAuthorizedUserClient', () => { let clock: sinon.SinonFakeTimers; const referenceDate = new Date('2020-08-11T06:55:22.345Z'); - const audience = getAudience(); + const workforcePoolAudience = + '//iam.googleapis.com/locations/global/workforcePools/pool-id-123/providers/provider-id-abc'; const externalAccountAuthorizedUserCredentialOptions = { type: EXTERNAL_ACCOUNT_AUTHORIZED_USER_TYPE, - audience: audience, + audience: workforcePoolAudience, client_id: 'clientId', client_secret: 'clientSecret', refresh_token: 'refreshToken', @@ -95,7 +100,7 @@ describe('ExternalAccountAuthorizedUserClient', () => { } as ExternalAccountAuthorizedUserClientOptions; const externalAccountAuthorizedUserCredentialOptionsNoToken = { type: EXTERNAL_ACCOUNT_AUTHORIZED_USER_TYPE, - audience: audience, + audience: workforcePoolAudience, client_id: 'clientId', client_secret: 'clientSecret', refresh_token: 'refreshToken', @@ -111,6 +116,11 @@ describe('ExternalAccountAuthorizedUserClient', () => { expires_in: 3600, }; beforeEach(() => { + sinon.stub(process, 'env').value({ + ...process.env, + GOOGLE_API_USE_CLIENT_CERTIFICATE: undefined, + GOOGLE_API_CERTIFICATE_CONFIG: undefined, + }); clock = TestUtils.useFakeTimers(sinon, referenceDate); }); @@ -119,6 +129,7 @@ describe('ExternalAccountAuthorizedUserClient', () => { if (clock) { clock.restore(); } + sinon.restore(); }); describe('Constructor', () => { @@ -893,4 +904,90 @@ describe('ExternalAccountAuthorizedUserClient', () => { scopes.forEach(scope => scope.done()); }); }); + + describe('regional access boundaries', () => { + const MOCK_ACCESS_TOKEN = 'newAccessToken'; + const MOCK_AUTH_HEADER = `Bearer ${MOCK_ACCESS_TOKEN}`; + const EXPECTED_RAB_DATA: RegionalAccessBoundaryData = { + locations: ['some-locations'], + encodedLocations: '0xdeadbeef', + }; + + beforeEach(() => { + clock.restore(); + }); + + afterEach(() => { + nock.cleanAll(); + }); + + it('should trigger asynchronous RAB refresh successfully', async () => { + const workforcePoolId = 'pool-id-123'; + const client = new ExternalAccountAuthorizedUserClient( + externalAccountAuthorizedUserCredentialOptions, + ); + + const stsScope = mockStsTokenRefresh(BASE_URL, REFRESH_PATH, [ + { + statusCode: 200, + response: successfulRefreshResponse, + request: { + grant_type: 'refresh_token', + refresh_token: 'refreshToken', + }, + }, + ]); + + const lookupUrl = WORKFORCE_LOOKUP_ENDPOINT.replace( + '{pool_id}', + encodeURIComponent(workforcePoolId), + ); + + let rabLookupCalled = false; + const rabScope = nock(new URL(lookupUrl).origin) + .get(new URL(lookupUrl).pathname) + .matchHeader('authorization', MOCK_AUTH_HEADER) + .reply(() => { + rabLookupCalled = true; + return [200, EXPECTED_RAB_DATA]; + }); + + // Initial call - should NOT have the header yet + const headers = await client.getRequestHeaders(); + assert.strictEqual(headers.get('x-allowed-locations'), null); + + // Wait for background lookup + let attempts = 0; + while (!rabLookupCalled && attempts < 20) { + await new Promise(r => setTimeout(r, 100)); + attempts++; + } + assert.strictEqual(rabLookupCalled, true); + + await new Promise(r => setTimeout(r, 100)); + assert.deepStrictEqual( + client.getRegionalAccessBoundary(), + EXPECTED_RAB_DATA, + ); + + stsScope.done(); + rabScope.done(); + }); + + it('should fail background lookup for an invalid audience', async () => { + const invalidAudience = 'invalid-audience-format'; + const options = { + ...externalAccountAuthorizedUserCredentialOptions, + audience: invalidAudience, + }; + const client = new ExternalAccountAuthorizedUserClient(options); + + // Note: background refresh fails silently in terms of getRequestHeaders resolving. + // But we can manually trigger getRegionalAccessBoundaryUrl to verify it throws. + await assert.rejects( + client.getRegionalAccessBoundaryUrl(), + /RegionalAccessBoundary: A workforce pool ID is required for regional access boundary lookups but could not be determined from the audience/, + ); + }); + }); }); diff --git a/core/packages/google-auth-library-nodejs/test/test.externalclient.ts b/core/packages/google-auth-library-nodejs/test/test.externalclient.ts index d85a420b7fc3..6c64d360150f 100644 --- a/core/packages/google-auth-library-nodejs/test/test.externalclient.ts +++ b/core/packages/google-auth-library-nodejs/test/test.externalclient.ts @@ -109,45 +109,35 @@ describe('ExternalAccountClient', () => { ]; it('should return IdentityPoolClient on IdentityPoolClientOptions', () => { - const expectedClient = new IdentityPoolClient(fileSourcedOptions); - - assert.deepStrictEqual( - ExternalAccountClient.fromJSON(fileSourcedOptions), - expectedClient, - ); + const client = ExternalAccountClient.fromJSON(fileSourcedOptions); + assert.ok(client instanceof IdentityPoolClient); }); it('should return IdentityPoolClient with expected RefreshOptions', () => { - const expectedClient = new IdentityPoolClient({ + const client = ExternalAccountClient.fromJSON({ ...fileSourcedOptions, ...refreshOptions, }); - assert.deepStrictEqual( - ExternalAccountClient.fromJSON({ - ...fileSourcedOptions, - ...refreshOptions, - }), - expectedClient, - ); + assert.ok(client instanceof IdentityPoolClient); + assert.strictEqual(client!.eagerRefreshThresholdMillis, 10000); + assert.strictEqual(client!.forceRefreshOnFailure, true); }); it('should return AwsClient on AwsClientOptions', () => { - const expectedClient = new AwsClient(awsOptions); - - assert.deepStrictEqual( - ExternalAccountClient.fromJSON(awsOptions), - expectedClient, - ); + const client = ExternalAccountClient.fromJSON(awsOptions); + assert.ok(client instanceof AwsClient); }); it('should return AwsClient with expected RefreshOptions', () => { - const expectedClient = new AwsClient({...awsOptions, ...refreshOptions}); + const client = ExternalAccountClient.fromJSON({ + ...awsOptions, + ...refreshOptions, + }); - assert.deepStrictEqual( - ExternalAccountClient.fromJSON({...awsOptions, ...refreshOptions}), - expectedClient, - ); + assert.ok(client instanceof AwsClient); + assert.strictEqual(client!.eagerRefreshThresholdMillis, 10000); + assert.strictEqual(client!.forceRefreshOnFailure, true); }); it('should return an IdentityPoolClient with a workforce config', () => { @@ -167,41 +157,28 @@ describe('ExternalAccountClient', () => { for (const validWorkforceIdentityPoolClientAudience of validWorkforceIdentityPoolClientAudiences) { workforceFileSourcedOptions.audience = validWorkforceIdentityPoolClientAudience; - const expectedClient = new IdentityPoolClient( - workforceFileSourcedOptions, - ); - assert.deepStrictEqual( - ExternalAccountClient.fromJSON(workforceFileSourcedOptions), - expectedClient, + const client = ExternalAccountClient.fromJSON( + workforceFileSourcedOptions, ); + assert.ok(client instanceof IdentityPoolClient); } }); it('should return PluggableAuthClient on PluggableAuthClientOptions', () => { - const expectedClient = new PluggableAuthClient( - pluggableAuthClientOptions, - ); - - assert.deepStrictEqual( - ExternalAccountClient.fromJSON(pluggableAuthClientOptions), - expectedClient, - ); + const client = ExternalAccountClient.fromJSON(pluggableAuthClientOptions); + assert.ok(client instanceof PluggableAuthClient); }); it('should return PluggableAuthClient with expected RefreshOptions', () => { - const expectedClient = new PluggableAuthClient({ + const client = ExternalAccountClient.fromJSON({ ...pluggableAuthClientOptions, ...refreshOptions, }); - assert.deepStrictEqual( - ExternalAccountClient.fromJSON({ - ...pluggableAuthClientOptions, - ...refreshOptions, - }), - expectedClient, - ); + assert.ok(client instanceof PluggableAuthClient); + assert.strictEqual(client!.eagerRefreshThresholdMillis, 10000); + assert.strictEqual(client!.forceRefreshOnFailure, true); }); invalidWorkforceIdentityPoolClientAudiences.forEach( diff --git a/core/packages/google-auth-library-nodejs/test/test.identitypoolclient.ts b/core/packages/google-auth-library-nodejs/test/test.identitypoolclient.ts index d8b2ff3665d8..4653238bc105 100644 --- a/core/packages/google-auth-library-nodejs/test/test.identitypoolclient.ts +++ b/core/packages/google-auth-library-nodejs/test/test.identitypoolclient.ts @@ -39,7 +39,7 @@ import { CERTIFICATE_CONFIGURATION_ENV_VARIABLE, CertificateSourceUnavailableError, InvalidConfigurationError, -} from '../src/auth/certificatesubjecttokensupplier'; +} from '../src/auth/mtlsutils'; import * as sinon from 'sinon'; import * as util from '../src/util'; diff --git a/core/packages/google-auth-library-nodejs/test/test.impersonated.ts b/core/packages/google-auth-library-nodejs/test/test.impersonated.ts index e7be5ddf177b..7c7a021a39de 100644 --- a/core/packages/google-auth-library-nodejs/test/test.impersonated.ts +++ b/core/packages/google-auth-library-nodejs/test/test.impersonated.ts @@ -19,6 +19,11 @@ import * as nock from 'nock'; import {describe, it, afterEach} from 'mocha'; import {Impersonated, JWT, UserRefreshClient} from '../src'; import {CredentialRequest} from '../src/auth/credentials'; +import { + SERVICE_ACCOUNT_LOOKUP_ENDPOINT, + RegionalAccessBoundaryData, +} from '../src/auth/regionalaccessboundary'; +import sinon = require('sinon'); const PEM_PATH = './test/fixtures/private.pem'; @@ -69,8 +74,20 @@ interface ImpersonatedCredentialRequest { } describe('impersonated', () => { + beforeEach(() => { + sinon.stub(process, 'env').value({ + ...process.env, + GOOGLE_API_USE_CLIENT_CERTIFICATE: undefined, + GOOGLE_API_CERTIFICATE_CONFIG: undefined, + }); + sinon + .stub(Impersonated.prototype, 'getRegionalAccessBoundaryUrl') + .resolves(undefined); + }); + afterEach(() => { nock.cleanAll(); + sinon.restore(); }); it('should request impersonated credentials on first request', async () => { @@ -589,4 +606,107 @@ describe('impersonated', () => { assert.equal(resp.signedBlob, expectedSignedBlob); scopes.forEach(s => s.done()); }); + + describe('regional access boundaries', () => { + const TARGET_PRINCIPAL_EMAIL = 'target@project.iam.gserviceaccount.com'; + const MOCK_ACCESS_TOKEN = 'abc123'; + const MOCK_AUTH_HEADER = `Bearer ${MOCK_ACCESS_TOKEN}`; + + const EXPECTED_RAB_DATA: RegionalAccessBoundaryData = { + locations: ['sadad', 'asdad'], + encodedLocations: '000x9', + }; + + function setupRegionalAccessBoundaryNock( + email: string, + regionalAccessBoundaryData: RegionalAccessBoundaryData = EXPECTED_RAB_DATA, + ): nock.Scope { + const lookupUrl = SERVICE_ACCOUNT_LOOKUP_ENDPOINT.replace( + '{service_account_email}', + encodeURIComponent(email), + ); + return nock(new URL(lookupUrl).origin) + .get(new URL(lookupUrl).pathname) + .matchHeader('authorization', MOCK_AUTH_HEADER) + .reply(200, regionalAccessBoundaryData); + } + + beforeEach(() => { + ( + Impersonated.prototype.getRegionalAccessBoundaryUrl as sinon.SinonStub + ).restore(); + }); + + afterEach(() => { + nock.cleanAll(); + }); + + it('should trigger asynchronous RAB refresh', async () => { + const tomorrow = new Date(); + tomorrow.setDate(tomorrow.getDate() + 1); + const impersonated = new Impersonated({ + sourceClient: createSampleJWTClient(), + targetPrincipal: TARGET_PRINCIPAL_EMAIL, + lifetime: 30, + delegates: [], + targetScopes: ['https://www.googleapis.com/auth/cloud-platform'], + }); + + const tokenScope = createGTokenMock({access_token: MOCK_ACCESS_TOKEN}); + const saScope = nock('https://iamcredentials.googleapis.com') + .post( + `/v1/projects/-/serviceAccounts/${TARGET_PRINCIPAL_EMAIL}:generateAccessToken`, + ) + .reply(200, { + accessToken: MOCK_ACCESS_TOKEN, + expireTime: tomorrow.toISOString(), + }); + + let rabLookupCalled = false; + const rabScope = setupRegionalAccessBoundaryNock(TARGET_PRINCIPAL_EMAIL); + rabScope.on('request', () => { + rabLookupCalled = true; + }); + + const url = 'https://pubsub.googleapis.com'; + const headers = await impersonated.getRequestHeaders(url); + + // Initial headers should NOT have RAB + assert.strictEqual(headers.get('x-allowed-locations'), null); + + // Wait for background lookup + let attempts = 0; + while (!rabLookupCalled && attempts < 10) { + await new Promise(r => setTimeout(r, 50)); + attempts++; + } + assert.strictEqual(rabLookupCalled, true); + + await new Promise(r => setTimeout(r, 50)); + assert.deepStrictEqual( + impersonated.getRegionalAccessBoundary(), + EXPECTED_RAB_DATA, + ); + + tokenScope.done(); + saScope.done(); + rabScope.done(); + }); + + it('should fail getRegionalAccessBoundaryUrl in background if no target principal is specified', async () => { + const impersonated = new Impersonated({ + sourceClient: createSampleJWTClient(), + // targetPrincipal missing + lifetime: 30, + delegates: [], + targetScopes: ['https://www.googleapis.com/auth/cloud-platform'], + }); + + // Error happens in background. + await assert.rejects( + impersonated.getRegionalAccessBoundaryUrl(), + /RegionalAccessBoundary: A targetPrincipal is required for regional access boundary lookups but was not provided in the ImpersonatedClient options./, + ); + }); + }); }); diff --git a/core/packages/google-auth-library-nodejs/test/test.jwt.ts b/core/packages/google-auth-library-nodejs/test/test.jwt.ts index cb5ed85ba4ce..1cb05438ebab 100644 --- a/core/packages/google-auth-library-nodejs/test/test.jwt.ts +++ b/core/packages/google-auth-library-nodejs/test/test.jwt.ts @@ -22,6 +22,10 @@ import * as sinon from 'sinon'; import {GoogleAuth, JWT} from '../src'; import {CredentialRequest, JWTInput} from '../src/auth/credentials'; import * as jwtaccess from '../src/auth/jwtaccess'; +import { + SERVICE_ACCOUNT_LOOKUP_ENDPOINT, + RegionalAccessBoundaryData, +} from '../src/auth/regionalaccessboundary'; function removeBearerFromAuthorizationHeader(headers: Headers): string { return (headers.get('authorization') || '').replace('Bearer ', ''); @@ -68,6 +72,14 @@ describe('jwt', () => { json = createJSON(); jwt = new JWT(); sandbox = sinon.createSandbox(); + sandbox.stub(process, 'env').value({ + ...process.env, + GOOGLE_API_USE_CLIENT_CERTIFICATE: undefined, + GOOGLE_API_CERTIFICATE_CONFIG: undefined, + }); + sandbox + .stub(JWT.prototype, 'getRegionalAccessBoundaryUrl') + .resolves(undefined); }); afterEach(() => { @@ -1244,4 +1256,252 @@ describe('jwt', () => { assert.strictEqual(headers.get('authorization'), want); }); }); + + describe('regional access boundaries', () => { + const SERVICE_ACCOUNT_EMAIL = 'service-account@example.com'; + const MOCK_ACCESS_TOKEN = 'abc123'; + const MOCK_AUTH_HEADER = `Bearer ${MOCK_ACCESS_TOKEN}`; + + const EXPECTED_RAB_DATA: RegionalAccessBoundaryData = { + locations: ['sadad', 'asdad'], + encodedLocations: '000x9', + }; + + function setupRegionalAccessBoundaryNock( + email: string, + regionalAccessBoundaryData: RegionalAccessBoundaryData = EXPECTED_RAB_DATA, + authHeader = MOCK_AUTH_HEADER, + ): nock.Scope { + const lookupUrl = SERVICE_ACCOUNT_LOOKUP_ENDPOINT.replace( + '{service_account_email}', + encodeURIComponent(email), + ); + return nock(new URL(lookupUrl).origin) + .get(new URL(lookupUrl).pathname) + .matchHeader('authorization', authHeader) + .reply(200, regionalAccessBoundaryData); + } + + beforeEach(() => { + (JWT.prototype.getRegionalAccessBoundaryUrl as sinon.SinonStub).restore(); + }); + + afterEach(() => { + nock.cleanAll(); + }); + + it('should trigger asynchronous regional access boundaries refresh', async () => { + const jwt = new JWT({ + email: SERVICE_ACCOUNT_EMAIL, + keyFile: PEM_PATH, + scopes: ['http://bar', 'http://foo'], + subject: 'bar@subjectaccount.com', + }); + jwt.credentials = {refresh_token: 'jwt-placeholder'}; + + const tokenScope = createGTokenMock({access_token: MOCK_ACCESS_TOKEN}); + + let rabLookupCalled = false; + const rabScope = setupRegionalAccessBoundaryNock(SERVICE_ACCOUNT_EMAIL); + rabScope.on('request', () => { + rabLookupCalled = true; + }); + + // Initial call - headers should NOT have the RAB yet + const headers = await jwt.getRequestHeaders( + 'https://pubsub.googleapis.com', + ); + assert.strictEqual(headers.get('x-allowed-locations'), null); + + // Wait for background lookup + let attempts = 0; + while (!rabLookupCalled && attempts < 10) { + await new Promise(r => setTimeout(r, 50)); + attempts++; + } + assert.strictEqual(rabLookupCalled, true); + + // Give it a moment to update state + await new Promise(r => setTimeout(r, 50)); + assert.deepStrictEqual( + jwt.getRegionalAccessBoundary(), + EXPECTED_RAB_DATA, + ); + + tokenScope.done(); + rabScope.done(); + }); + + it('should fail RAB lookup if GOOGLE_API_USE_MTLS_ENDPOINT is always but client certificate is disabled', async () => { + process.env.GOOGLE_API_USE_MTLS_ENDPOINT = 'always'; + process.env.GOOGLE_API_USE_CLIENT_CERTIFICATE = 'false'; + + const jwt = new JWT({ + email: SERVICE_ACCOUNT_EMAIL, + keyFile: PEM_PATH, + scopes: ['http://bar', 'http://foo'], + subject: 'bar@subjectaccount.com', + }); + jwt.credentials = {refresh_token: 'jwt-placeholder'}; + + const tokenScope = createGTokenMock({access_token: MOCK_ACCESS_TOKEN}); + + // We trigger the background lookup by getting request headers. + await jwt.getRequestHeaders('https://pubsub.googleapis.com'); + + // Wait a bit for the async task to execute and fail + let attempts = 0; + while (!jwt.getRegionalAccessBoundaryCooldownTime() && attempts < 10) { + await new Promise(r => setTimeout(r, 50)); + attempts++; + } + + // It should enter cooldown because it failed to initialize mTLS + assert.ok(jwt.getRegionalAccessBoundaryCooldownTime() > Date.now()); + + tokenScope.done(); + }); + + it('should use mTLS endpoint for RAB lookup if GOOGLE_API_USE_MTLS_ENDPOINT is always and valid cert config is present', async () => { + process.env.GOOGLE_API_USE_MTLS_ENDPOINT = 'always'; + process.env.GOOGLE_API_CERTIFICATE_CONFIG = + './test/fixtures/external-account-cert/cert_config.json'; + + const jwt = new JWT({ + email: SERVICE_ACCOUNT_EMAIL, + keyFile: PEM_PATH, + scopes: ['http://bar', 'http://foo'], + subject: 'bar@subjectaccount.com', + }); + jwt.credentials = {refresh_token: 'jwt-placeholder'}; + + const tokenScope = createGTokenMock({access_token: MOCK_ACCESS_TOKEN}); + + // Construct and mock the mTLS lookup URL + const lookupUrl = SERVICE_ACCOUNT_LOOKUP_ENDPOINT.replace( + '{service_account_email}', + encodeURIComponent(SERVICE_ACCOUNT_EMAIL), + ).replace( + 'iamcredentials.googleapis.com', + 'iamcredentials.mtls.googleapis.com', + ); + + let rabLookupCalled = false; + const rabScope = nock(new URL(lookupUrl).origin) + .get(new URL(lookupUrl).pathname) + .matchHeader('authorization', MOCK_AUTH_HEADER) + .reply(() => { + rabLookupCalled = true; + return [200, EXPECTED_RAB_DATA]; + }); + + // We trigger the background lookup by getting request headers. + await jwt.getRequestHeaders('https://pubsub.googleapis.com'); + + // Wait a bit for the async task to execute + let attempts = 0; + while (!rabLookupCalled && attempts < 10) { + await new Promise(r => setTimeout(r, 50)); + attempts++; + } + + assert.strictEqual(rabLookupCalled, true); + assert.deepStrictEqual( + jwt.getRegionalAccessBoundary(), + EXPECTED_RAB_DATA, + ); + + tokenScope.done(); + rabScope.done(); + }); + + it('should trigger RAB refresh for self-signed JWT', async () => { + // Self-signed JWT (no scopes) + const keys = keypair(512); + const jwt = new JWT({ + email: SERVICE_ACCOUNT_EMAIL, + key: keys.private, + }); + jwt.credentials = {refresh_token: 'jwt-placeholder'}; + + const lookupUrl = SERVICE_ACCOUNT_LOOKUP_ENDPOINT.replace( + '{service_account_email}', + encodeURIComponent(SERVICE_ACCOUNT_EMAIL), + ); + + let rabLookupCalled = false; + // For self-signed JWT, the lookup uses the JWT itself as the token + const rabScope = nock(new URL(lookupUrl).origin) + .get(new URL(lookupUrl).pathname) + .reply(() => { + rabLookupCalled = true; + return [200, EXPECTED_RAB_DATA]; + }); + + const url = 'https://pubsub.googleapis.com'; + const headers = await jwt.getRequestHeaders(url); + + // Verify headers contain the self-signed JWT + const authHeader = headers.get('authorization'); + assert.ok(authHeader?.startsWith('Bearer ')); + + // Wait for background lookup + let attempts = 0; + while (!rabLookupCalled && attempts < 10) { + await new Promise(r => setTimeout(r, 50)); + attempts++; + } + assert.strictEqual(rabLookupCalled, true); + + await new Promise(r => setTimeout(r, 50)); + assert.deepStrictEqual( + jwt.getRegionalAccessBoundary(), + EXPECTED_RAB_DATA, + ); + + rabScope.done(); + }); + + it('should NOT add RAB headers for ID tokens', async () => { + const jwt = new JWT({ + email: SERVICE_ACCOUNT_EMAIL, + key: PEM_CONTENTS, + additionalClaims: {target_audience: 'some-audience'}, + }); + + // Setup a RAB lookup mock that should NOT be hit + const rabScope = setupRegionalAccessBoundaryNock(SERVICE_ACCOUNT_EMAIL); + + const scope = createGTokenMock({id_token: 'id-token-abc'}); + const headers = await jwt.getRequestHeaders( + 'https://pubsub.googleapis.com', + ); + + assert.strictEqual(headers.get('authorization'), 'Bearer id-token-abc'); + // Should NOT have the RAB header because it's an ID token + assert.strictEqual(headers.get('x-allowed-locations'), null); + + // Ensure RAB lookup was NOT called + assert.strictEqual(rabScope.isDone(), false); + + scope.done(); + }); + + it('should fail getRegionalAccessBoundaryUrl if no email is passed', async () => { + const jwt = new JWT({ + keyFile: PEM_PATH, + scopes: ['http://bar', 'http://foo'], + subject: 'bar@subjectaccount.com', + }); + // Ensure email is explicitly undefined + jwt.email = undefined; + + // Note: error happens in background during getRequestHeaders, + // but we can manually call getRegionalAccessBoundaryUrl to verify it throws. + await assert.rejects( + jwt.getRegionalAccessBoundaryUrl(), + /RegionalAccessBoundary: An email address is required for regional access boundary lookups but was not provided in the JwtClient options./, + ); + }); + }); }); diff --git a/core/packages/google-auth-library-nodejs/test/test.mtlsutils.ts b/core/packages/google-auth-library-nodejs/test/test.mtlsutils.ts new file mode 100644 index 000000000000..4a661b990ddd --- /dev/null +++ b/core/packages/google-auth-library-nodejs/test/test.mtlsutils.ts @@ -0,0 +1,199 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import * as assert from 'assert'; +import {describe, it, beforeEach, afterEach} from 'mocha'; +import * as sinon from 'sinon'; +import * as fs from 'fs'; +import * as path from 'path'; +import * as os from 'os'; +import { + canMtlsBeEnabled, + getClientCertAndKey, + CertificateSourceUnavailableError, + InvalidConfigurationError, + getMtlsEndpointUsagePolicy, + MtlsEndpointUsagePolicy, +} from '../src/auth/mtlsutils'; +import * as util from '../src/util'; + +describe('mtlsutils', () => { + let sandbox: sinon.SinonSandbox; + let tempDir: string; + + beforeEach(async () => { + sandbox = sinon.createSandbox(); + sandbox.stub(process, 'env').value({...process.env}); + tempDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'mtls-tests-')); + }); + + afterEach(async () => { + sandbox.restore(); + await fs.promises.rm(tempDir, {recursive: true, force: true}); + }); + + describe('canMtlsBeEnabled', () => { + it('returns false if GOOGLE_API_USE_CLIENT_CERTIFICATE is false', async () => { + process.env.GOOGLE_API_USE_CLIENT_CERTIFICATE = 'false'; + const result = await canMtlsBeEnabled(); + assert.strictEqual(result, false); + }); + + it('returns false if GOOGLE_API_USE_MTLS_ENDPOINT is never', async () => { + process.env.GOOGLE_API_USE_MTLS_ENDPOINT = 'never'; + const result = await canMtlsBeEnabled(); + assert.strictEqual(result, false); + }); + + it('returns true if valid cert config file is present', async () => { + process.env.GOOGLE_API_CERTIFICATE_CONFIG = + './test/fixtures/external-account-cert/cert_config.json'; + const result = await canMtlsBeEnabled(); + assert.strictEqual(result, true); + }); + + it('returns true even if cert config file is malformed', async () => { + process.env.GOOGLE_API_CERTIFICATE_CONFIG = + './test/fixtures/external-account-cert/cert_config_empty.json'; + const result = await canMtlsBeEnabled(); + assert.strictEqual(result, true); + }); + + it('returns true even if cert config is missing required workload properties', async () => { + process.env.GOOGLE_API_CERTIFICATE_CONFIG = + './test/fixtures/external-account-cert/cert_config_missing_cert_path.json'; + const result = await canMtlsBeEnabled(); + assert.strictEqual(result, true); + }); + + it('returns true even if cert config referenced files do not exist', async () => { + const invalidConfigPath = path.join(tempDir, 'invalid_config.json'); + const invalidConfigJson = { + cert_configs: { + workload: { + cert_path: path.join(tempDir, 'non_existent.crt'), + key_path: path.join(tempDir, 'non_existent.key'), + }, + }, + }; + await fs.promises.writeFile( + invalidConfigPath, + JSON.stringify(invalidConfigJson), + ); + process.env.GOOGLE_API_CERTIFICATE_CONFIG = invalidConfigPath; + const result = await canMtlsBeEnabled(); + assert.strictEqual(result, true); + }); + + it('returns false if no config is present', async () => { + delete process.env.GOOGLE_API_CERTIFICATE_CONFIG; + sandbox + .stub(util, 'getWellKnownCertificateConfigFileLocation') + .returns(path.join(tempDir, 'non_existent.json')); + const result = await canMtlsBeEnabled(); + assert.strictEqual(result, false); + }); + + it('returns true if GOOGLE_API_USE_MTLS_ENDPOINT is always, even if no config file is present', async () => { + process.env.GOOGLE_API_USE_MTLS_ENDPOINT = 'always'; + delete process.env.GOOGLE_API_CERTIFICATE_CONFIG; + sandbox + .stub(util, 'getWellKnownCertificateConfigFileLocation') + .returns(path.join(tempDir, 'non_existent.json')); + const result = await canMtlsBeEnabled(); + assert.strictEqual(result, true); + }); + + it('throws error if GOOGLE_API_USE_MTLS_ENDPOINT is always and GOOGLE_API_USE_CLIENT_CERTIFICATE is false', async () => { + process.env.GOOGLE_API_USE_MTLS_ENDPOINT = 'always'; + process.env.GOOGLE_API_USE_CLIENT_CERTIFICATE = 'false'; + await assert.rejects( + canMtlsBeEnabled(), + /mTLS is configured to ALWAYS, but client certificate usage was explicitly disabled via GOOGLE_API_USE_CLIENT_CERTIFICATE=false\./, + ); + }); + }); + + describe('getClientCertAndKey', () => { + it('loads cert and key from config successfully', async () => { + const result = await getClientCertAndKey( + './test/fixtures/external-account-cert/cert_config.json', + ); + assert.ok(result.cert); + assert.ok(result.key); + }); + + it('throws error if files resolved by config are malformed', async () => { + await assert.rejects( + getClientCertAndKey( + './test/fixtures/external-account-cert/cert_config_with_malformed_key.json', + ), + ); + }); + + it('throws error if cert config file is malformed', async () => { + await assert.rejects( + getClientCertAndKey( + './test/fixtures/external-account-cert/cert_config_empty.json', + ), + InvalidConfigurationError, + ); + }); + + it('throws error if cert config is missing required workload properties', async () => { + await assert.rejects( + getClientCertAndKey( + './test/fixtures/external-account-cert/cert_config_missing_cert_path.json', + ), + InvalidConfigurationError, + ); + }); + + it('throws error if cert config referenced files do not exist', async () => { + const invalidConfigPath = path.join(tempDir, 'invalid_config.json'); + const invalidConfigJson = { + cert_configs: { + workload: { + cert_path: path.join(tempDir, 'non_existent.crt'), + key_path: path.join(tempDir, 'non_existent.key'), + }, + }, + }; + await fs.promises.writeFile( + invalidConfigPath, + JSON.stringify(invalidConfigJson), + ); + await assert.rejects( + getClientCertAndKey(invalidConfigPath), + CertificateSourceUnavailableError, + ); + }); + }); + + describe('getMtlsEndpointUsagePolicy', () => { + it('returns NEVER or ALWAYS case-insensitively', () => { + process.env.GOOGLE_API_USE_MTLS_ENDPOINT = 'NeVeR'; + assert.strictEqual( + getMtlsEndpointUsagePolicy(), + MtlsEndpointUsagePolicy.NEVER, + ); + + process.env.GOOGLE_API_USE_MTLS_ENDPOINT = 'AlWaYs'; + assert.strictEqual( + getMtlsEndpointUsagePolicy(), + MtlsEndpointUsagePolicy.ALWAYS, + ); + }); + }); +}); diff --git a/core/packages/google-auth-library-nodejs/tsconfig.json b/core/packages/google-auth-library-nodejs/tsconfig.json index 572f3da71667..b9f7f940bae4 100644 --- a/core/packages/google-auth-library-nodejs/tsconfig.json +++ b/core/packages/google-auth-library-nodejs/tsconfig.json @@ -1,7 +1,10 @@ { "extends": "./node_modules/gts/tsconfig-google.json", "compilerOptions": { - "lib": ["DOM"], + "lib": [ + "es2023", + "DOM" + ], "composite": true, "rootDir": ".", "outDir": "build", diff --git a/packages/google-ads-admanager/package.json b/packages/google-ads-admanager/package.json index 95b10b9402fd..bc5e971c6d07 100644 --- a/packages/google-ads-admanager/package.json +++ b/packages/google-ads-admanager/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-ads-admanager", "keywords": [ diff --git a/packages/google-ads-datamanager/package.json b/packages/google-ads-datamanager/package.json index 11e10a2e7e32..96e4cd79e504 100644 --- a/packages/google-ads-datamanager/package.json +++ b/packages/google-ads-datamanager/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-ads-datamanager", "keywords": [ diff --git a/packages/google-ai-generativelanguage/package.json b/packages/google-ai-generativelanguage/package.json index e3df02b0d557..e123734d863f 100644 --- a/packages/google-ai-generativelanguage/package.json +++ b/packages/google-ai-generativelanguage/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-ai-generativelanguage", "keywords": [ diff --git a/packages/google-analytics-admin/package.json b/packages/google-analytics-admin/package.json index f83f73cf07ba..97d48dccee6a 100644 --- a/packages/google-analytics-admin/package.json +++ b/packages/google-analytics-admin/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-analytics-data/package.json b/packages/google-analytics-data/package.json index 173fed47f717..7a2839f701f2 100644 --- a/packages/google-analytics-data/package.json +++ b/packages/google-analytics-data/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-api-apikeys/package.json b/packages/google-api-apikeys/package.json index 84946ff96696..7ba7b5201739 100644 --- a/packages/google-api-apikeys/package.json +++ b/packages/google-api-apikeys/package.json @@ -13,7 +13,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-api-cloudquotas/package.json b/packages/google-api-cloudquotas/package.json index ad2bc9b6a73a..e868ebf4f0ce 100644 --- a/packages/google-api-cloudquotas/package.json +++ b/packages/google-api-cloudquotas/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-api-cloudquotas", "keywords": [ diff --git a/packages/google-api-servicecontrol/package.json b/packages/google-api-servicecontrol/package.json index ac24a75279d5..17f21759d3a8 100644 --- a/packages/google-api-servicecontrol/package.json +++ b/packages/google-api-servicecontrol/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-api-servicemanagement/package.json b/packages/google-api-servicemanagement/package.json index 1cc33c94c124..4ac0ccf20aef 100644 --- a/packages/google-api-servicemanagement/package.json +++ b/packages/google-api-servicemanagement/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-api-serviceusage/package.json b/packages/google-api-serviceusage/package.json index 245ef944e03b..84116eb5cbe1 100644 --- a/packages/google-api-serviceusage/package.json +++ b/packages/google-api-serviceusage/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-appengine/package.json b/packages/google-appengine/package.json index cab84229b33c..5aa194da1c6a 100644 --- a/packages/google-appengine/package.json +++ b/packages/google-appengine/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-apps-events-subscriptions/package.json b/packages/google-apps-events-subscriptions/package.json index fbc82c558b79..bfc75554e661 100644 --- a/packages/google-apps-events-subscriptions/package.json +++ b/packages/google-apps-events-subscriptions/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-apps-events-subscriptions", "keywords": [ diff --git a/packages/google-apps-meet/package.json b/packages/google-apps-meet/package.json index 627bdf04b987..5b50b2847f43 100644 --- a/packages/google-apps-meet/package.json +++ b/packages/google-apps-meet/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-apps-meet", "keywords": [ diff --git a/packages/google-area120-tables/package.json b/packages/google-area120-tables/package.json index 2260ba5ebe1f..339de75f899e 100644 --- a/packages/google-area120-tables/package.json +++ b/packages/google-area120-tables/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-chat/package.json b/packages/google-chat/package.json index 643a65aaea9e..6c0e589239bd 100644 --- a/packages/google-chat/package.json +++ b/packages/google-chat/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-chat", "keywords": [ diff --git a/packages/google-cloud-accessapproval/package.json b/packages/google-cloud-accessapproval/package.json index 8d3343a90886..32fb845e2868 100644 --- a/packages/google-cloud-accessapproval/package.json +++ b/packages/google-cloud-accessapproval/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-advisorynotifications/package.json b/packages/google-cloud-advisorynotifications/package.json index 3eefafa012fe..effdf1c330b8 100644 --- a/packages/google-cloud-advisorynotifications/package.json +++ b/packages/google-cloud-advisorynotifications/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-advisorynotifications", diff --git a/packages/google-cloud-aiplatform/package.json b/packages/google-cloud-aiplatform/package.json index 993d8f4203eb..b45ad6f8bb65 100644 --- a/packages/google-cloud-aiplatform/package.json +++ b/packages/google-cloud-aiplatform/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-alloydb/package.json b/packages/google-cloud-alloydb/package.json index b363bae9c59d..3cbef1a19f71 100644 --- a/packages/google-cloud-alloydb/package.json +++ b/packages/google-cloud-alloydb/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-alloydb", diff --git a/packages/google-cloud-apigateway/package.json b/packages/google-cloud-apigateway/package.json index d59481d6af43..e2bb6138e4d6 100644 --- a/packages/google-cloud-apigateway/package.json +++ b/packages/google-cloud-apigateway/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-apigeeconnect/package.json b/packages/google-cloud-apigeeconnect/package.json index f533dbcb3fa1..7aba6e7bfce3 100644 --- a/packages/google-cloud-apigeeconnect/package.json +++ b/packages/google-cloud-apigeeconnect/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-apigeeregistry/package.json b/packages/google-cloud-apigeeregistry/package.json index 95c12ec6f4c6..d8b61a63cf22 100644 --- a/packages/google-cloud-apigeeregistry/package.json +++ b/packages/google-cloud-apigeeregistry/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "keywords": [ "google apis client", diff --git a/packages/google-cloud-apihub/package.json b/packages/google-cloud-apihub/package.json index 918d885b8cad..5f91677da1dd 100644 --- a/packages/google-cloud-apihub/package.json +++ b/packages/google-cloud-apihub/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-apihub", "keywords": [ diff --git a/packages/google-cloud-apiregistry/package.json b/packages/google-cloud-apiregistry/package.json index 97c958c03a22..39cab84a0d33 100644 --- a/packages/google-cloud-apiregistry/package.json +++ b/packages/google-cloud-apiregistry/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-apiregistry", "keywords": [ diff --git a/packages/google-cloud-apphub/package.json b/packages/google-cloud-apphub/package.json index 9303e65606c6..d81e5d2e095e 100644 --- a/packages/google-cloud-apphub/package.json +++ b/packages/google-cloud-apphub/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-apphub", "keywords": [ diff --git a/packages/google-cloud-asset/package.json b/packages/google-cloud-asset/package.json index 8174dc8d485d..bae894738ecf 100644 --- a/packages/google-cloud-asset/package.json +++ b/packages/google-cloud-asset/package.json @@ -15,7 +15,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-assuredworkloads/package.json b/packages/google-cloud-assuredworkloads/package.json index 39580a5f1c01..8ae5b845bc2f 100644 --- a/packages/google-cloud-assuredworkloads/package.json +++ b/packages/google-cloud-assuredworkloads/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-auditmanager/package.json b/packages/google-cloud-auditmanager/package.json index 25c2e441c2fd..4e3f590cb940 100644 --- a/packages/google-cloud-auditmanager/package.json +++ b/packages/google-cloud-auditmanager/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-auditmanager", "keywords": [ diff --git a/packages/google-cloud-automl/package.json b/packages/google-cloud-automl/package.json index 6917e1b5dab5..74513d7c4ac0 100644 --- a/packages/google-cloud-automl/package.json +++ b/packages/google-cloud-automl/package.json @@ -14,7 +14,6 @@ }, "main": "build/src/index.js", "files": [ - "build/protos", "build/src" ], "keywords": [ diff --git a/packages/google-cloud-backupdr/package.json b/packages/google-cloud-backupdr/package.json index 96cd30e9320a..3f5ccc916b5b 100644 --- a/packages/google-cloud-backupdr/package.json +++ b/packages/google-cloud-backupdr/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-backupdr", "keywords": [ diff --git a/packages/google-cloud-baremetalsolution/package.json b/packages/google-cloud-baremetalsolution/package.json index 60cd3a5b2c51..f630a6efb563 100644 --- a/packages/google-cloud-baremetalsolution/package.json +++ b/packages/google-cloud-baremetalsolution/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-batch/package.json b/packages/google-cloud-batch/package.json index a29d67baa6d9..5911af269ad8 100644 --- a/packages/google-cloud-batch/package.json +++ b/packages/google-cloud-batch/package.json @@ -13,7 +13,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-beyondcorp-appconnections/package.json b/packages/google-cloud-beyondcorp-appconnections/package.json index cda7d6a7abb6..3d00ff2c1ad3 100644 --- a/packages/google-cloud-beyondcorp-appconnections/package.json +++ b/packages/google-cloud-beyondcorp-appconnections/package.json @@ -13,7 +13,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-beyondcorp-appconnectors/package.json b/packages/google-cloud-beyondcorp-appconnectors/package.json index 29f488a2a44d..53ad14b79435 100644 --- a/packages/google-cloud-beyondcorp-appconnectors/package.json +++ b/packages/google-cloud-beyondcorp-appconnectors/package.json @@ -13,7 +13,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-beyondcorp-appgateways/package.json b/packages/google-cloud-beyondcorp-appgateways/package.json index 2db3a8c5f69f..533fa2218a56 100644 --- a/packages/google-cloud-beyondcorp-appgateways/package.json +++ b/packages/google-cloud-beyondcorp-appgateways/package.json @@ -13,7 +13,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-beyondcorp-clientconnectorservices/package.json b/packages/google-cloud-beyondcorp-clientconnectorservices/package.json index 5cf6a535c9a8..0156743958e9 100644 --- a/packages/google-cloud-beyondcorp-clientconnectorservices/package.json +++ b/packages/google-cloud-beyondcorp-clientconnectorservices/package.json @@ -13,7 +13,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-beyondcorp-clientgateways/package.json b/packages/google-cloud-beyondcorp-clientgateways/package.json index 271b2f51975f..5dd7d8abb10d 100644 --- a/packages/google-cloud-beyondcorp-clientgateways/package.json +++ b/packages/google-cloud-beyondcorp-clientgateways/package.json @@ -13,7 +13,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-bigquery-analyticshub/package.json b/packages/google-cloud-bigquery-analyticshub/package.json index 8c5e32208741..6bb9038bb978 100644 --- a/packages/google-cloud-bigquery-analyticshub/package.json +++ b/packages/google-cloud-bigquery-analyticshub/package.json @@ -13,7 +13,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-bigquery-connection/package.json b/packages/google-cloud-bigquery-connection/package.json index 1441951fe361..2fc601cf1887 100644 --- a/packages/google-cloud-bigquery-connection/package.json +++ b/packages/google-cloud-bigquery-connection/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-bigquery-dataexchange/package.json b/packages/google-cloud-bigquery-dataexchange/package.json index e169b3c47d0e..75f0ca5df1b2 100644 --- a/packages/google-cloud-bigquery-dataexchange/package.json +++ b/packages/google-cloud-bigquery-dataexchange/package.json @@ -13,7 +13,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-bigquery-datapolicies/package.json b/packages/google-cloud-bigquery-datapolicies/package.json index e5dc0c04aebd..c673077d2fd5 100644 --- a/packages/google-cloud-bigquery-datapolicies/package.json +++ b/packages/google-cloud-bigquery-datapolicies/package.json @@ -13,7 +13,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-bigquery-datatransfer/package.json b/packages/google-cloud-bigquery-datatransfer/package.json index e80d51d87020..f6483fe18dd4 100644 --- a/packages/google-cloud-bigquery-datatransfer/package.json +++ b/packages/google-cloud-bigquery-datatransfer/package.json @@ -15,7 +15,6 @@ "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-bigquery-datatransfer", "main": "build/src/index.js", "files": [ - "build/protos", "build/src", "!build/src/**/*.map" ], diff --git a/packages/google-cloud-bigquery-migration/package.json b/packages/google-cloud-bigquery-migration/package.json index 3327bb76974b..15a29b016a8d 100644 --- a/packages/google-cloud-bigquery-migration/package.json +++ b/packages/google-cloud-bigquery-migration/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "keywords": [ "google apis client", diff --git a/packages/google-cloud-bigquery-reservation/package.json b/packages/google-cloud-bigquery-reservation/package.json index 6920ef193933..0164d5bb5c1d 100644 --- a/packages/google-cloud-bigquery-reservation/package.json +++ b/packages/google-cloud-bigquery-reservation/package.json @@ -13,7 +13,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-billing-budgets/package.json b/packages/google-cloud-billing-budgets/package.json index 55b33bde7556..2cb2e0dcff53 100644 --- a/packages/google-cloud-billing-budgets/package.json +++ b/packages/google-cloud-billing-budgets/package.json @@ -11,7 +11,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "devDependencies": { diff --git a/packages/google-cloud-billing/package.json b/packages/google-cloud-billing/package.json index 6b5758d6eaeb..bf31c367632a 100644 --- a/packages/google-cloud-billing/package.json +++ b/packages/google-cloud-billing/package.json @@ -11,7 +11,6 @@ "author": "Google LLC", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "main": "build/src/index.js", diff --git a/packages/google-cloud-binaryauthorization/package.json b/packages/google-cloud-binaryauthorization/package.json index 82f50c373bc2..fa567d24883f 100644 --- a/packages/google-cloud-binaryauthorization/package.json +++ b/packages/google-cloud-binaryauthorization/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-capacityplanner/package.json b/packages/google-cloud-capacityplanner/package.json index 036385eab352..4d2636e022fb 100644 --- a/packages/google-cloud-capacityplanner/package.json +++ b/packages/google-cloud-capacityplanner/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-capacityplanner", "keywords": [ diff --git a/packages/google-cloud-certificatemanager/package.json b/packages/google-cloud-certificatemanager/package.json index a7d0c4af0e3c..fd9aa5a25250 100644 --- a/packages/google-cloud-certificatemanager/package.json +++ b/packages/google-cloud-certificatemanager/package.json @@ -13,7 +13,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-ces/package.json b/packages/google-cloud-ces/package.json index 6f6142b5f4e6..93f4a6a41618 100644 --- a/packages/google-cloud-ces/package.json +++ b/packages/google-cloud-ces/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-ces", "keywords": [ diff --git a/packages/google-cloud-channel/package.json b/packages/google-cloud-channel/package.json index da1a4e4066c5..5a6f0b8554fa 100644 --- a/packages/google-cloud-channel/package.json +++ b/packages/google-cloud-channel/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-chronicle/package.json b/packages/google-cloud-chronicle/package.json index 27822363cdca..925367099268 100644 --- a/packages/google-cloud-chronicle/package.json +++ b/packages/google-cloud-chronicle/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-chronicle", "keywords": [ diff --git a/packages/google-cloud-cloudcontrolspartner/package.json b/packages/google-cloud-cloudcontrolspartner/package.json index 4a8f2ecf4f6f..f250a144ae49 100644 --- a/packages/google-cloud-cloudcontrolspartner/package.json +++ b/packages/google-cloud-cloudcontrolspartner/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-cloudcontrolspartner", "keywords": [ diff --git a/packages/google-cloud-clouddms/package.json b/packages/google-cloud-clouddms/package.json index 54a3d19047ea..7c21f65d335b 100644 --- a/packages/google-cloud-clouddms/package.json +++ b/packages/google-cloud-clouddms/package.json @@ -15,7 +15,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-cloudsecuritycompliance/package.json b/packages/google-cloud-cloudsecuritycompliance/package.json index 6203d043a617..d9ca96278d98 100644 --- a/packages/google-cloud-cloudsecuritycompliance/package.json +++ b/packages/google-cloud-cloudsecuritycompliance/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-cloudsecuritycompliance", "keywords": [ diff --git a/packages/google-cloud-commerce-consumer-procurement/package.json b/packages/google-cloud-commerce-consumer-procurement/package.json index 1c3a913ed9cc..ba9aa1fdcece 100644 --- a/packages/google-cloud-commerce-consumer-procurement/package.json +++ b/packages/google-cloud-commerce-consumer-procurement/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-commerce-consumer-procurement", "keywords": [ diff --git a/packages/google-cloud-compute/package.json b/packages/google-cloud-compute/package.json index fe7d6a4f1381..98b4abf49881 100644 --- a/packages/google-cloud-compute/package.json +++ b/packages/google-cloud-compute/package.json @@ -15,7 +15,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-confidentialcomputing/package.json b/packages/google-cloud-confidentialcomputing/package.json index 9168e7d984dc..5f70ef024598 100644 --- a/packages/google-cloud-confidentialcomputing/package.json +++ b/packages/google-cloud-confidentialcomputing/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-confidentialcomputing", "keywords": [ diff --git a/packages/google-cloud-config/package.json b/packages/google-cloud-config/package.json index fabd149c2b67..1d8e3a2a2289 100644 --- a/packages/google-cloud-config/package.json +++ b/packages/google-cloud-config/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-config", "keywords": [ diff --git a/packages/google-cloud-configdelivery/package.json b/packages/google-cloud-configdelivery/package.json index 0e4bd820198f..0fc85faa7a3c 100644 --- a/packages/google-cloud-configdelivery/package.json +++ b/packages/google-cloud-configdelivery/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-configdelivery", "keywords": [ diff --git a/packages/google-cloud-connectors/package.json b/packages/google-cloud-connectors/package.json index b931ac4a6ca8..58622585086a 100644 --- a/packages/google-cloud-connectors/package.json +++ b/packages/google-cloud-connectors/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-connectors", "keywords": [ diff --git a/packages/google-cloud-contactcenterinsights/package.json b/packages/google-cloud-contactcenterinsights/package.json index 9524c38e99fa..a81cee4110ee 100644 --- a/packages/google-cloud-contactcenterinsights/package.json +++ b/packages/google-cloud-contactcenterinsights/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-contentwarehouse/package.json b/packages/google-cloud-contentwarehouse/package.json index dff48a842a21..60e02b0051b1 100644 --- a/packages/google-cloud-contentwarehouse/package.json +++ b/packages/google-cloud-contentwarehouse/package.json @@ -13,7 +13,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-datacatalog-lineage-configmanagement/package.json b/packages/google-cloud-datacatalog-lineage-configmanagement/package.json index 94a4d8004033..2fb0c39d36ab 100644 --- a/packages/google-cloud-datacatalog-lineage-configmanagement/package.json +++ b/packages/google-cloud-datacatalog-lineage-configmanagement/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-datacatalog-lineage-configmanagement", "keywords": [ diff --git a/packages/google-cloud-datacatalog-lineage/package.json b/packages/google-cloud-datacatalog-lineage/package.json index b200468c73fc..149148ddcc29 100644 --- a/packages/google-cloud-datacatalog-lineage/package.json +++ b/packages/google-cloud-datacatalog-lineage/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-datacatalog-lineage", diff --git a/packages/google-cloud-datacatalog/package.json b/packages/google-cloud-datacatalog/package.json index e7fb11ad0d9a..c48483866ae3 100644 --- a/packages/google-cloud-datacatalog/package.json +++ b/packages/google-cloud-datacatalog/package.json @@ -11,7 +11,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "AUTHORS", "COPYING", "!build/src/**/*.map" diff --git a/packages/google-cloud-dataform/package.json b/packages/google-cloud-dataform/package.json index ec724f949873..de6c7d9a6735 100644 --- a/packages/google-cloud-dataform/package.json +++ b/packages/google-cloud-dataform/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-dataform", "keywords": [ diff --git a/packages/google-cloud-datafusion/package.json b/packages/google-cloud-datafusion/package.json index e914acd929b7..61fc5c436440 100644 --- a/packages/google-cloud-datafusion/package.json +++ b/packages/google-cloud-datafusion/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-datalabeling/package.json b/packages/google-cloud-datalabeling/package.json index b1a08f1fe461..5f0e60f82cea 100644 --- a/packages/google-cloud-datalabeling/package.json +++ b/packages/google-cloud-datalabeling/package.json @@ -14,7 +14,6 @@ }, "main": "build/src/index.js", "files": [ - "build/protos", "build/src", "!build/src/**/*.map" ], diff --git a/packages/google-cloud-dataplex/package.json b/packages/google-cloud-dataplex/package.json index f9d7e263434f..c5d2d1a9f519 100644 --- a/packages/google-cloud-dataplex/package.json +++ b/packages/google-cloud-dataplex/package.json @@ -13,7 +13,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-dataproc/package.json b/packages/google-cloud-dataproc/package.json index f65b9ba66b28..b6abe95c2bbc 100644 --- a/packages/google-cloud-dataproc/package.json +++ b/packages/google-cloud-dataproc/package.json @@ -14,7 +14,6 @@ }, "main": "build/src/index.js", "files": [ - "build/protos", "build/src", "!build/src/**/*.map" ], diff --git a/packages/google-cloud-dataqna/package.json b/packages/google-cloud-dataqna/package.json index 5ada76a9db02..a716065f4dd2 100644 --- a/packages/google-cloud-dataqna/package.json +++ b/packages/google-cloud-dataqna/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-datastream/package.json b/packages/google-cloud-datastream/package.json index b7e21f25cea7..301a4a0d46c4 100644 --- a/packages/google-cloud-datastream/package.json +++ b/packages/google-cloud-datastream/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-deploy/package.json b/packages/google-cloud-deploy/package.json index 3368e381b647..0561508ffc95 100644 --- a/packages/google-cloud-deploy/package.json +++ b/packages/google-cloud-deploy/package.json @@ -13,7 +13,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-developerconnect/package.json b/packages/google-cloud-developerconnect/package.json index e33e0489c3e4..582d4893831a 100644 --- a/packages/google-cloud-developerconnect/package.json +++ b/packages/google-cloud-developerconnect/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-developerconnect", "keywords": [ diff --git a/packages/google-cloud-devicestreaming/package.json b/packages/google-cloud-devicestreaming/package.json index d37f4f234762..e11b65df50ff 100644 --- a/packages/google-cloud-devicestreaming/package.json +++ b/packages/google-cloud-devicestreaming/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-devicestreaming", "keywords": [ diff --git a/packages/google-cloud-dialogflow-cx/package.json b/packages/google-cloud-dialogflow-cx/package.json index 0a21a5e82300..9b40d734e88c 100644 --- a/packages/google-cloud-dialogflow-cx/package.json +++ b/packages/google-cloud-dialogflow-cx/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-dialogflow/package.json b/packages/google-cloud-dialogflow/package.json index 9c8cdd4f026a..ec1d0ab8d186 100644 --- a/packages/google-cloud-dialogflow/package.json +++ b/packages/google-cloud-dialogflow/package.json @@ -14,7 +14,6 @@ }, "main": "build/src/index.js", "files": [ - "build/protos", "build/src", "!build/src/**/*.map" ], diff --git a/packages/google-cloud-discoveryengine/package.json b/packages/google-cloud-discoveryengine/package.json index 9148550e0040..cbf9d50ad917 100644 --- a/packages/google-cloud-discoveryengine/package.json +++ b/packages/google-cloud-discoveryengine/package.json @@ -13,7 +13,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-documentai/package.json b/packages/google-cloud-documentai/package.json index 31744e90a877..6bc34b8ca2fc 100644 --- a/packages/google-cloud-documentai/package.json +++ b/packages/google-cloud-documentai/package.json @@ -11,7 +11,6 @@ "author": "Google LLC", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "main": "build/src/index.js", diff --git a/packages/google-cloud-domains/package.json b/packages/google-cloud-domains/package.json index 498ed8c5a408..2b8c7f281ed5 100644 --- a/packages/google-cloud-domains/package.json +++ b/packages/google-cloud-domains/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-edgecontainer/package.json b/packages/google-cloud-edgecontainer/package.json index 43393263ea42..ae4cbc4817e6 100644 --- a/packages/google-cloud-edgecontainer/package.json +++ b/packages/google-cloud-edgecontainer/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-edgecontainer", "keywords": [ diff --git a/packages/google-cloud-edgenetwork/package.json b/packages/google-cloud-edgenetwork/package.json index b8a779798059..9f762ca14e8c 100644 --- a/packages/google-cloud-edgenetwork/package.json +++ b/packages/google-cloud-edgenetwork/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-edgenetwork", "keywords": [ diff --git a/packages/google-cloud-essentialcontacts/package.json b/packages/google-cloud-essentialcontacts/package.json index 6238de65fa3b..80729108af26 100644 --- a/packages/google-cloud-essentialcontacts/package.json +++ b/packages/google-cloud-essentialcontacts/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-eventarc-publishing/package.json b/packages/google-cloud-eventarc-publishing/package.json index 4d561d439114..b48825433c14 100644 --- a/packages/google-cloud-eventarc-publishing/package.json +++ b/packages/google-cloud-eventarc-publishing/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-eventarc/package.json b/packages/google-cloud-eventarc/package.json index 9149772226b9..ad6224a5a805 100644 --- a/packages/google-cloud-eventarc/package.json +++ b/packages/google-cloud-eventarc/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-filestore/package.json b/packages/google-cloud-filestore/package.json index be2e1a2aa12d..b9fe19d72289 100644 --- a/packages/google-cloud-filestore/package.json +++ b/packages/google-cloud-filestore/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-financialservices/package.json b/packages/google-cloud-financialservices/package.json index cc99c51efa83..a78613ca9d91 100644 --- a/packages/google-cloud-financialservices/package.json +++ b/packages/google-cloud-financialservices/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-financialservices", "keywords": [ diff --git a/packages/google-cloud-functions/package.json b/packages/google-cloud-functions/package.json index 4bfde7324b73..9535258ffe0e 100644 --- a/packages/google-cloud-functions/package.json +++ b/packages/google-cloud-functions/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-gdchardwaremanagement/package.json b/packages/google-cloud-gdchardwaremanagement/package.json index daa27a032126..3e1230739292 100644 --- a/packages/google-cloud-gdchardwaremanagement/package.json +++ b/packages/google-cloud-gdchardwaremanagement/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-gdchardwaremanagement", "keywords": [ diff --git a/packages/google-cloud-geminidataanalytics/package.json b/packages/google-cloud-geminidataanalytics/package.json index 0a0c332cc5e7..f03e4268af2f 100644 --- a/packages/google-cloud-geminidataanalytics/package.json +++ b/packages/google-cloud-geminidataanalytics/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-geminidataanalytics", "keywords": [ diff --git a/packages/google-cloud-gkebackup/package.json b/packages/google-cloud-gkebackup/package.json index 26bd31dec664..816edce7558c 100644 --- a/packages/google-cloud-gkebackup/package.json +++ b/packages/google-cloud-gkebackup/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-gkeconnect-gateway/package.json b/packages/google-cloud-gkeconnect-gateway/package.json index 35a2f998ee5a..f2ae1c3337e4 100644 --- a/packages/google-cloud-gkeconnect-gateway/package.json +++ b/packages/google-cloud-gkeconnect-gateway/package.json @@ -13,7 +13,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-gkehub/package.json b/packages/google-cloud-gkehub/package.json index f666e06f5522..8ecde6aa4132 100644 --- a/packages/google-cloud-gkehub/package.json +++ b/packages/google-cloud-gkehub/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-gkemulticloud/package.json b/packages/google-cloud-gkemulticloud/package.json index 40d34d63d94c..b98ba4de6126 100644 --- a/packages/google-cloud-gkemulticloud/package.json +++ b/packages/google-cloud-gkemulticloud/package.json @@ -13,7 +13,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-gkerecommender/package.json b/packages/google-cloud-gkerecommender/package.json index 03dd14944644..54936e28df31 100644 --- a/packages/google-cloud-gkerecommender/package.json +++ b/packages/google-cloud-gkerecommender/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-gkerecommender", "keywords": [ diff --git a/packages/google-cloud-gsuiteaddons/package.json b/packages/google-cloud-gsuiteaddons/package.json index 8409f3d02c40..0faeacf7dc09 100644 --- a/packages/google-cloud-gsuiteaddons/package.json +++ b/packages/google-cloud-gsuiteaddons/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-gsuiteaddons", diff --git a/packages/google-cloud-hypercomputecluster/package.json b/packages/google-cloud-hypercomputecluster/package.json index c8a890a05608..1c4f9fd302ea 100644 --- a/packages/google-cloud-hypercomputecluster/package.json +++ b/packages/google-cloud-hypercomputecluster/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-hypercomputecluster", "keywords": [ diff --git a/packages/google-cloud-iap/package.json b/packages/google-cloud-iap/package.json index 751e874f108d..ea9e551a46d4 100644 --- a/packages/google-cloud-iap/package.json +++ b/packages/google-cloud-iap/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-ids/package.json b/packages/google-cloud-ids/package.json index 21343b4ba784..0ea2c20a889f 100644 --- a/packages/google-cloud-ids/package.json +++ b/packages/google-cloud-ids/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-iot/package.json b/packages/google-cloud-iot/package.json index bea04c806631..8e0a884c0c39 100644 --- a/packages/google-cloud-iot/package.json +++ b/packages/google-cloud-iot/package.json @@ -14,7 +14,6 @@ }, "main": "build/src/index.js", "files": [ - "build/protos", "build/src", "!build/src/**/*.map" ], diff --git a/packages/google-cloud-kms-inventory/package.json b/packages/google-cloud-kms-inventory/package.json index 63febbeeb37e..8479c5332ac3 100644 --- a/packages/google-cloud-kms-inventory/package.json +++ b/packages/google-cloud-kms-inventory/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-kms/package.json b/packages/google-cloud-kms/package.json index 2a5f9b8b1cb3..897c59b616ff 100644 --- a/packages/google-cloud-kms/package.json +++ b/packages/google-cloud-kms/package.json @@ -14,7 +14,6 @@ }, "main": "build/src/index.js", "files": [ - "build/protos", "build/src", "!build/src/**/*.map" ], diff --git a/packages/google-cloud-language/package.json b/packages/google-cloud-language/package.json index 1e7fee968379..1f234b812ff7 100644 --- a/packages/google-cloud-language/package.json +++ b/packages/google-cloud-language/package.json @@ -15,7 +15,6 @@ "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-language", "main": "build/src/index.js", "files": [ - "build/protos", "build/src", "AUTHORS", "CONTRIBUTORS", diff --git a/packages/google-cloud-licensemanager/package.json b/packages/google-cloud-licensemanager/package.json index 7841e3b04616..dfffc8fb22fd 100644 --- a/packages/google-cloud-licensemanager/package.json +++ b/packages/google-cloud-licensemanager/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-licensemanager", "keywords": [ diff --git a/packages/google-cloud-lifesciences/package.json b/packages/google-cloud-lifesciences/package.json index 823026f96ef2..e05721854e69 100644 --- a/packages/google-cloud-lifesciences/package.json +++ b/packages/google-cloud-lifesciences/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-locationfinder/package.json b/packages/google-cloud-locationfinder/package.json index 8797e696df46..a3eee0df79f0 100644 --- a/packages/google-cloud-locationfinder/package.json +++ b/packages/google-cloud-locationfinder/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-locationfinder", "keywords": [ diff --git a/packages/google-cloud-lustre/package.json b/packages/google-cloud-lustre/package.json index ef51c87c0397..2dec5ce19723 100644 --- a/packages/google-cloud-lustre/package.json +++ b/packages/google-cloud-lustre/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-lustre", "keywords": [ diff --git a/packages/google-cloud-maintenance-api/package.json b/packages/google-cloud-maintenance-api/package.json index 9bef47ad6503..5cf3052338b0 100644 --- a/packages/google-cloud-maintenance-api/package.json +++ b/packages/google-cloud-maintenance-api/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-maintenance-api", "keywords": [ diff --git a/packages/google-cloud-managedidentities/package.json b/packages/google-cloud-managedidentities/package.json index bd7b1c68eb7e..cd14199d803a 100644 --- a/packages/google-cloud-managedidentities/package.json +++ b/packages/google-cloud-managedidentities/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-managedkafka-schemaregistry/package.json b/packages/google-cloud-managedkafka-schemaregistry/package.json index b632bee45700..e266a6714c81 100644 --- a/packages/google-cloud-managedkafka-schemaregistry/package.json +++ b/packages/google-cloud-managedkafka-schemaregistry/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-managedkafka-schemaregistry", "keywords": [ diff --git a/packages/google-cloud-managedkafka/package.json b/packages/google-cloud-managedkafka/package.json index f2971ecedcf3..344e59aeb8e8 100644 --- a/packages/google-cloud-managedkafka/package.json +++ b/packages/google-cloud-managedkafka/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-managedkafka", "keywords": [ diff --git a/packages/google-cloud-mediatranslation/package.json b/packages/google-cloud-mediatranslation/package.json index c57e69b8314e..b61a55a24d7c 100644 --- a/packages/google-cloud-mediatranslation/package.json +++ b/packages/google-cloud-mediatranslation/package.json @@ -11,7 +11,6 @@ "author": "Google LLC", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "main": "build/src/index.js", diff --git a/packages/google-cloud-memcache/package.json b/packages/google-cloud-memcache/package.json index 0e96d438d49f..c8936ce49316 100644 --- a/packages/google-cloud-memcache/package.json +++ b/packages/google-cloud-memcache/package.json @@ -13,7 +13,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "scripts": { diff --git a/packages/google-cloud-memorystore/package.json b/packages/google-cloud-memorystore/package.json index 3555f35a0204..c8aa61f28329 100644 --- a/packages/google-cloud-memorystore/package.json +++ b/packages/google-cloud-memorystore/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-memorystore", "keywords": [ diff --git a/packages/google-cloud-metastore/package.json b/packages/google-cloud-metastore/package.json index aea12215ebac..0fd1bd10682d 100644 --- a/packages/google-cloud-metastore/package.json +++ b/packages/google-cloud-metastore/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-migrationcenter/package.json b/packages/google-cloud-migrationcenter/package.json index c300a93ce876..1bdda5796adf 100644 --- a/packages/google-cloud-migrationcenter/package.json +++ b/packages/google-cloud-migrationcenter/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-migrationcenter", "keywords": [ diff --git a/packages/google-cloud-modelarmor/package.json b/packages/google-cloud-modelarmor/package.json index 71da28620250..38af82f7e1ea 100644 --- a/packages/google-cloud-modelarmor/package.json +++ b/packages/google-cloud-modelarmor/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-modelarmor", "keywords": [ diff --git a/packages/google-cloud-monitoring/package.json b/packages/google-cloud-monitoring/package.json index 47b2a38ac121..91f7686015b9 100644 --- a/packages/google-cloud-monitoring/package.json +++ b/packages/google-cloud-monitoring/package.json @@ -15,7 +15,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-netapp/package.json b/packages/google-cloud-netapp/package.json index 65bd700ed5e0..fa24d3461ebf 100644 --- a/packages/google-cloud-netapp/package.json +++ b/packages/google-cloud-netapp/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-netapp", "keywords": [ diff --git a/packages/google-cloud-networkconnectivity/package.json b/packages/google-cloud-networkconnectivity/package.json index 6e053c7ff1e5..1fdd7a98efb7 100644 --- a/packages/google-cloud-networkconnectivity/package.json +++ b/packages/google-cloud-networkconnectivity/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-networkmanagement/package.json b/packages/google-cloud-networkmanagement/package.json index 5b489227d809..b1bde7733493 100644 --- a/packages/google-cloud-networkmanagement/package.json +++ b/packages/google-cloud-networkmanagement/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-networksecurity/package.json b/packages/google-cloud-networksecurity/package.json index 40e35985e725..c6526bc4dec4 100644 --- a/packages/google-cloud-networksecurity/package.json +++ b/packages/google-cloud-networksecurity/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-networkservices/package.json b/packages/google-cloud-networkservices/package.json index 580657039847..d84593847ec4 100644 --- a/packages/google-cloud-networkservices/package.json +++ b/packages/google-cloud-networkservices/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-networkservices", "keywords": [ diff --git a/packages/google-cloud-notebooks/package.json b/packages/google-cloud-notebooks/package.json index e31df74385e6..b8a49b16bfca 100644 --- a/packages/google-cloud-notebooks/package.json +++ b/packages/google-cloud-notebooks/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-oracledatabase/package.json b/packages/google-cloud-oracledatabase/package.json index fe422f296afe..1fd7e20b8731 100644 --- a/packages/google-cloud-oracledatabase/package.json +++ b/packages/google-cloud-oracledatabase/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-oracledatabase", "keywords": [ diff --git a/packages/google-cloud-orchestration-airflow-service/package.json b/packages/google-cloud-orchestration-airflow-service/package.json index 0eb52f7c894c..eb827ae8437a 100644 --- a/packages/google-cloud-orchestration-airflow-service/package.json +++ b/packages/google-cloud-orchestration-airflow-service/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-orgpolicy/package.json b/packages/google-cloud-orgpolicy/package.json index f9a597d2fbcb..4525dde631da 100644 --- a/packages/google-cloud-orgpolicy/package.json +++ b/packages/google-cloud-orgpolicy/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-osconfig/package.json b/packages/google-cloud-osconfig/package.json index c87e8a6f2566..95ac39c88dfc 100644 --- a/packages/google-cloud-osconfig/package.json +++ b/packages/google-cloud-osconfig/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "scripts": { diff --git a/packages/google-cloud-oslogin/package.json b/packages/google-cloud-oslogin/package.json index 25fa1fc97696..ce0346e79b01 100644 --- a/packages/google-cloud-oslogin/package.json +++ b/packages/google-cloud-oslogin/package.json @@ -15,7 +15,6 @@ "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-oslogin", "main": "build/src/index.js", "files": [ - "build/protos", "build/src", "AUTHORS", "COPYING", diff --git a/packages/google-cloud-parallelstore/package.json b/packages/google-cloud-parallelstore/package.json index f6516cc47f96..ec8e1bf674aa 100644 --- a/packages/google-cloud-parallelstore/package.json +++ b/packages/google-cloud-parallelstore/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-parallelstore", "keywords": [ diff --git a/packages/google-cloud-parametermanager/package.json b/packages/google-cloud-parametermanager/package.json index 08526ba3e788..bc9e66066a36 100644 --- a/packages/google-cloud-parametermanager/package.json +++ b/packages/google-cloud-parametermanager/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-parametermanager", "keywords": [ diff --git a/packages/google-cloud-phishingprotection/package.json b/packages/google-cloud-phishingprotection/package.json index b9d3d1504cec..c623b4afe2f9 100644 --- a/packages/google-cloud-phishingprotection/package.json +++ b/packages/google-cloud-phishingprotection/package.json @@ -11,7 +11,6 @@ "description": "Phishing Protection API client for Node.js", "main": "build/src/index.js", "files": [ - "build/protos", "build/src", "!build/src/**/*.map" ], diff --git a/packages/google-cloud-policysimulator/package.json b/packages/google-cloud-policysimulator/package.json index eda18a7d008f..f6afe35edad0 100644 --- a/packages/google-cloud-policysimulator/package.json +++ b/packages/google-cloud-policysimulator/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-policysimulator", "keywords": [ diff --git a/packages/google-cloud-policytroubleshooter-iam/package.json b/packages/google-cloud-policytroubleshooter-iam/package.json index 630a8da306e1..43d2166ee720 100644 --- a/packages/google-cloud-policytroubleshooter-iam/package.json +++ b/packages/google-cloud-policytroubleshooter-iam/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "keywords": [ "google apis client", diff --git a/packages/google-cloud-policytroubleshooter/package.json b/packages/google-cloud-policytroubleshooter/package.json index 7cb0e448f488..a93e968f7b83 100644 --- a/packages/google-cloud-policytroubleshooter/package.json +++ b/packages/google-cloud-policytroubleshooter/package.json @@ -13,7 +13,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-privatecatalog/package.json b/packages/google-cloud-privatecatalog/package.json index 65dead7e5191..3d4c6b1a04a9 100644 --- a/packages/google-cloud-privatecatalog/package.json +++ b/packages/google-cloud-privatecatalog/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-privilegedaccessmanager/package.json b/packages/google-cloud-privilegedaccessmanager/package.json index 89cf305fe242..4a5fb8cdefb0 100644 --- a/packages/google-cloud-privilegedaccessmanager/package.json +++ b/packages/google-cloud-privilegedaccessmanager/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-privilegedaccessmanager", "keywords": [ diff --git a/packages/google-cloud-rapidmigrationassessment/package.json b/packages/google-cloud-rapidmigrationassessment/package.json index 2803740c7afb..b5e3a35239a3 100644 --- a/packages/google-cloud-rapidmigrationassessment/package.json +++ b/packages/google-cloud-rapidmigrationassessment/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-rapidmigrationassessment", "keywords": [ diff --git a/packages/google-cloud-recaptchaenterprise/package.json b/packages/google-cloud-recaptchaenterprise/package.json index 61c626a44767..8cd9cb298989 100644 --- a/packages/google-cloud-recaptchaenterprise/package.json +++ b/packages/google-cloud-recaptchaenterprise/package.json @@ -10,7 +10,6 @@ "description": "reCAPTCHA Enterprise API client for Node.js", "main": "build/src/index.js", "files": [ - "build/protos", "build/src", "AUTHORS", "COPYING", diff --git a/packages/google-cloud-recommender/package.json b/packages/google-cloud-recommender/package.json index 7b05024d5c10..aaeeea8c4587 100644 --- a/packages/google-cloud-recommender/package.json +++ b/packages/google-cloud-recommender/package.json @@ -12,7 +12,6 @@ "author": "Google LLC", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "main": "build/src/index.js", diff --git a/packages/google-cloud-redis-cluster/package.json b/packages/google-cloud-redis-cluster/package.json index b6e680951cc9..20f80ab8711d 100644 --- a/packages/google-cloud-redis-cluster/package.json +++ b/packages/google-cloud-redis-cluster/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-redis-cluster", "keywords": [ diff --git a/packages/google-cloud-redis/package.json b/packages/google-cloud-redis/package.json index 1cc16ca7c98e..ab65a4e8022f 100644 --- a/packages/google-cloud-redis/package.json +++ b/packages/google-cloud-redis/package.json @@ -15,7 +15,6 @@ "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-redis", "main": "build/src/index.js", "files": [ - "build/protos", "build/src", "!build/src/**/*.map" ], diff --git a/packages/google-cloud-resourcemanager/package.json b/packages/google-cloud-resourcemanager/package.json index 495304ce738e..513f77b6a8b3 100644 --- a/packages/google-cloud-resourcemanager/package.json +++ b/packages/google-cloud-resourcemanager/package.json @@ -17,7 +17,6 @@ "types": "./build/src/index.d.ts", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-retail/package.json b/packages/google-cloud-retail/package.json index 2ed434e78791..eb54aff7be04 100644 --- a/packages/google-cloud-retail/package.json +++ b/packages/google-cloud-retail/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-run/package.json b/packages/google-cloud-run/package.json index 2ca3429b94fe..2bedef3bfe94 100644 --- a/packages/google-cloud-run/package.json +++ b/packages/google-cloud-run/package.json @@ -11,7 +11,6 @@ "author": "Google LLC", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-saasplatform-saasservicemgmt/package.json b/packages/google-cloud-saasplatform-saasservicemgmt/package.json index 23698e87a4bf..a33abef9aa42 100644 --- a/packages/google-cloud-saasplatform-saasservicemgmt/package.json +++ b/packages/google-cloud-saasplatform-saasservicemgmt/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-saasplatform-saasservicemgmt", "keywords": [ diff --git a/packages/google-cloud-scheduler/package.json b/packages/google-cloud-scheduler/package.json index 31424589034b..e57e0c20e6b9 100644 --- a/packages/google-cloud-scheduler/package.json +++ b/packages/google-cloud-scheduler/package.json @@ -14,7 +14,6 @@ }, "main": "build/src/index.js", "files": [ - "build/protos", "build/src", "!build/src/**/*.map" ], diff --git a/packages/google-cloud-secretmanager/package.json b/packages/google-cloud-secretmanager/package.json index cc9a937d2e0c..7e0701fb6e9e 100644 --- a/packages/google-cloud-secretmanager/package.json +++ b/packages/google-cloud-secretmanager/package.json @@ -11,7 +11,6 @@ "author": "Google LLC", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-securesourcemanager/package.json b/packages/google-cloud-securesourcemanager/package.json index 32689672b885..c75dc068c767 100644 --- a/packages/google-cloud-securesourcemanager/package.json +++ b/packages/google-cloud-securesourcemanager/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-securesourcemanager", "keywords": [ diff --git a/packages/google-cloud-security-privateca/package.json b/packages/google-cloud-security-privateca/package.json index cb75c8d81065..1fdb207ceb98 100644 --- a/packages/google-cloud-security-privateca/package.json +++ b/packages/google-cloud-security-privateca/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-security-publicca/package.json b/packages/google-cloud-security-publicca/package.json index f8d637b78cdf..57f8e77c6efe 100644 --- a/packages/google-cloud-security-publicca/package.json +++ b/packages/google-cloud-security-publicca/package.json @@ -13,7 +13,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-securitycenter/package.json b/packages/google-cloud-securitycenter/package.json index d7a4c3f08a20..81fff4d17495 100644 --- a/packages/google-cloud-securitycenter/package.json +++ b/packages/google-cloud-securitycenter/package.json @@ -14,7 +14,6 @@ }, "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "main": "build/src/index.js", diff --git a/packages/google-cloud-securitycentermanagement/package.json b/packages/google-cloud-securitycentermanagement/package.json index a892c12b1892..664f8fef393f 100644 --- a/packages/google-cloud-securitycentermanagement/package.json +++ b/packages/google-cloud-securitycentermanagement/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-securitycentermanagement", "keywords": [ diff --git a/packages/google-cloud-servicedirectory/package.json b/packages/google-cloud-servicedirectory/package.json index 9e13a0e424b8..38991f9a9c1d 100644 --- a/packages/google-cloud-servicedirectory/package.json +++ b/packages/google-cloud-servicedirectory/package.json @@ -11,7 +11,6 @@ "author": "Google LLC", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "main": "build/src/index.js", diff --git a/packages/google-cloud-servicehealth/package.json b/packages/google-cloud-servicehealth/package.json index a39f895ce54f..7f4afdef7983 100644 --- a/packages/google-cloud-servicehealth/package.json +++ b/packages/google-cloud-servicehealth/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-servicehealth", "keywords": [ diff --git a/packages/google-cloud-shell/package.json b/packages/google-cloud-shell/package.json index 6af9a5bcd6ed..165a43be404d 100644 --- a/packages/google-cloud-shell/package.json +++ b/packages/google-cloud-shell/package.json @@ -13,7 +13,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-speech/package.json b/packages/google-cloud-speech/package.json index 1e2c1f3648e8..e3660fc2d2be 100644 --- a/packages/google-cloud-speech/package.json +++ b/packages/google-cloud-speech/package.json @@ -14,7 +14,6 @@ }, "main": "./build/src/index.js", "files": [ - "build/protos", "build/src", "AUTHORS", "LICENSE", diff --git a/packages/google-cloud-sql/package.json b/packages/google-cloud-sql/package.json index 1bcee49d2c3b..e7fc8484b20c 100644 --- a/packages/google-cloud-sql/package.json +++ b/packages/google-cloud-sql/package.json @@ -12,8 +12,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "keywords": [ "google apis client", diff --git a/packages/google-cloud-storagebatchoperations/package.json b/packages/google-cloud-storagebatchoperations/package.json index 36851693093c..3579a24f0c34 100644 --- a/packages/google-cloud-storagebatchoperations/package.json +++ b/packages/google-cloud-storagebatchoperations/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-storagebatchoperations", "keywords": [ diff --git a/packages/google-cloud-storageinsights/package.json b/packages/google-cloud-storageinsights/package.json index 44a056e855f9..11c51292f0bc 100644 --- a/packages/google-cloud-storageinsights/package.json +++ b/packages/google-cloud-storageinsights/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-storageinsights", "keywords": [ diff --git a/packages/google-cloud-support/package.json b/packages/google-cloud-support/package.json index 4aa01d27af77..fe41ce90d844 100644 --- a/packages/google-cloud-support/package.json +++ b/packages/google-cloud-support/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-support", "keywords": [ diff --git a/packages/google-cloud-talent/package.json b/packages/google-cloud-talent/package.json index 8ce162d521ba..5264228fd428 100644 --- a/packages/google-cloud-talent/package.json +++ b/packages/google-cloud-talent/package.json @@ -14,7 +14,6 @@ }, "main": "build/src/index.js", "files": [ - "build/protos", "build/src", "!build/src/**/*.map" ], diff --git a/packages/google-cloud-telcoautomation/package.json b/packages/google-cloud-telcoautomation/package.json index 8e545a45eeb0..27dba675fe65 100644 --- a/packages/google-cloud-telcoautomation/package.json +++ b/packages/google-cloud-telcoautomation/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-telcoautomation", "keywords": [ diff --git a/packages/google-cloud-texttospeech/package.json b/packages/google-cloud-texttospeech/package.json index b8869e4ca20b..4491bf003e2f 100644 --- a/packages/google-cloud-texttospeech/package.json +++ b/packages/google-cloud-texttospeech/package.json @@ -14,7 +14,6 @@ }, "main": "build/src/index.js", "files": [ - "build/protos", "build/src", "!build/src/**/*.map" ], diff --git a/packages/google-cloud-tpu/package.json b/packages/google-cloud-tpu/package.json index 96b34e790eb6..a2357c17c13e 100644 --- a/packages/google-cloud-tpu/package.json +++ b/packages/google-cloud-tpu/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-translate/package.json b/packages/google-cloud-translate/package.json index 5da83865c29f..ff069882945f 100644 --- a/packages/google-cloud-translate/package.json +++ b/packages/google-cloud-translate/package.json @@ -16,7 +16,6 @@ "types": "build/src/index.d.ts", "files": [ "build/src", - "build/protos", "!build/src/**/*.map", "!build/src/**/*.map" ], diff --git a/packages/google-cloud-vectorsearch/package.json b/packages/google-cloud-vectorsearch/package.json index 74982db39501..8ea3a769e6d1 100644 --- a/packages/google-cloud-vectorsearch/package.json +++ b/packages/google-cloud-vectorsearch/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-vectorsearch", "keywords": [ diff --git a/packages/google-cloud-video-livestream/package.json b/packages/google-cloud-video-livestream/package.json index 23ca35dbe24f..592a34d916e3 100644 --- a/packages/google-cloud-video-livestream/package.json +++ b/packages/google-cloud-video-livestream/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-video-stitcher/package.json b/packages/google-cloud-video-stitcher/package.json index 2511ba940485..257f729fc5ab 100644 --- a/packages/google-cloud-video-stitcher/package.json +++ b/packages/google-cloud-video-stitcher/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-video-transcoder/package.json b/packages/google-cloud-video-transcoder/package.json index 1e2096fe9337..d5f6313ff4eb 100644 --- a/packages/google-cloud-video-transcoder/package.json +++ b/packages/google-cloud-video-transcoder/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-videointelligence/package.json b/packages/google-cloud-videointelligence/package.json index 4abd179afb17..7f95cea664e0 100644 --- a/packages/google-cloud-videointelligence/package.json +++ b/packages/google-cloud-videointelligence/package.json @@ -14,7 +14,6 @@ }, "main": "build/src/index.js", "files": [ - "build/protos", "build/src", "LICENSE", "!build/src/**/*.map" diff --git a/packages/google-cloud-vision/package.json b/packages/google-cloud-vision/package.json index 9a7e7517108c..e2904818b1df 100644 --- a/packages/google-cloud-vision/package.json +++ b/packages/google-cloud-vision/package.json @@ -15,7 +15,6 @@ "main": "build/src/index.js", "types": "build/src/index.d.ts", "files": [ - "build/protos", "build/src", "!build/src/**/*.map" ], diff --git a/packages/google-cloud-visionai/package.json b/packages/google-cloud-visionai/package.json index 3dab6549b7ce..a3abcd03faec 100644 --- a/packages/google-cloud-visionai/package.json +++ b/packages/google-cloud-visionai/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-visionai", "keywords": [ diff --git a/packages/google-cloud-vmmigration/package.json b/packages/google-cloud-vmmigration/package.json index 023ff779d106..b887dbd35a9b 100644 --- a/packages/google-cloud-vmmigration/package.json +++ b/packages/google-cloud-vmmigration/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-vmwareengine/package.json b/packages/google-cloud-vmwareengine/package.json index 6d234f852114..2f7e4efee1b7 100644 --- a/packages/google-cloud-vmwareengine/package.json +++ b/packages/google-cloud-vmwareengine/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-vmwareengine", diff --git a/packages/google-cloud-vpcaccess/package.json b/packages/google-cloud-vpcaccess/package.json index 29e90e030777..cc5165564e66 100644 --- a/packages/google-cloud-vpcaccess/package.json +++ b/packages/google-cloud-vpcaccess/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-webrisk/package.json b/packages/google-cloud-webrisk/package.json index 9b58e1072aac..21abc5a28e62 100644 --- a/packages/google-cloud-webrisk/package.json +++ b/packages/google-cloud-webrisk/package.json @@ -10,7 +10,6 @@ "description": "Web Risk API client for Node.js", "main": "build/src/index.js", "files": [ - "build/protos", "build/src", "!build/src/**/*.map" ], diff --git a/packages/google-cloud-websecurityscanner/package.json b/packages/google-cloud-websecurityscanner/package.json index 3d04f97d309e..94eeccd658b5 100644 --- a/packages/google-cloud-websecurityscanner/package.json +++ b/packages/google-cloud-websecurityscanner/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-workflows/package.json b/packages/google-cloud-workflows/package.json index 32e7e1072dc9..1c8ed149655c 100644 --- a/packages/google-cloud-workflows/package.json +++ b/packages/google-cloud-workflows/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-cloud-workloadmanager/package.json b/packages/google-cloud-workloadmanager/package.json index 7447f84df3f0..db867feea798 100644 --- a/packages/google-cloud-workloadmanager/package.json +++ b/packages/google-cloud-workloadmanager/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-workloadmanager", "keywords": [ diff --git a/packages/google-cloud-workstations/package.json b/packages/google-cloud-workstations/package.json index cc323da30f41..f15a6929b242 100644 --- a/packages/google-cloud-workstations/package.json +++ b/packages/google-cloud-workstations/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-cloud-workstations", diff --git a/packages/google-container/package.json b/packages/google-container/package.json index 0c08e8af6745..8545bd15460f 100644 --- a/packages/google-container/package.json +++ b/packages/google-container/package.json @@ -14,7 +14,6 @@ }, "main": "build/src/index.js", "files": [ - "build/protos", "build/src", "!build/src/**/*.map" ], diff --git a/packages/google-dataflow/package.json b/packages/google-dataflow/package.json index bb9f73ca3a1e..43aa1351f558 100644 --- a/packages/google-dataflow/package.json +++ b/packages/google-dataflow/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-devtools-artifactregistry/package.json b/packages/google-devtools-artifactregistry/package.json index 8ac2562c6aaa..e4132ab755bc 100644 --- a/packages/google-devtools-artifactregistry/package.json +++ b/packages/google-devtools-artifactregistry/package.json @@ -13,7 +13,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-devtools-cloudbuild/package.json b/packages/google-devtools-cloudbuild/package.json index 4fec7a8be3f3..ed81e79bfb4e 100644 --- a/packages/google-devtools-cloudbuild/package.json +++ b/packages/google-devtools-cloudbuild/package.json @@ -12,7 +12,6 @@ "browser": "src/browser.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-devtools-cloudprofiler/package.json b/packages/google-devtools-cloudprofiler/package.json index a824c067fffd..fcb3ce9cf039 100644 --- a/packages/google-devtools-cloudprofiler/package.json +++ b/packages/google-devtools-cloudprofiler/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-devtools-cloudprofiler", "keywords": [ diff --git a/packages/google-devtools-containeranalysis/package.json b/packages/google-devtools-containeranalysis/package.json index 8a4f5b3fda22..77b5311fce9c 100644 --- a/packages/google-devtools-containeranalysis/package.json +++ b/packages/google-devtools-containeranalysis/package.json @@ -13,7 +13,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-iam-credentials/package.json b/packages/google-iam-credentials/package.json index 8bc2f83a5b6d..63a349458dbc 100644 --- a/packages/google-iam-credentials/package.json +++ b/packages/google-iam-credentials/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-iam/package.json b/packages/google-iam/package.json index be05131d0b84..084d7f7e87f5 100644 --- a/packages/google-iam/package.json +++ b/packages/google-iam/package.json @@ -13,7 +13,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-identity-accesscontextmanager/package.json b/packages/google-identity-accesscontextmanager/package.json index aaa51f646f19..c9d72d776a33 100644 --- a/packages/google-identity-accesscontextmanager/package.json +++ b/packages/google-identity-accesscontextmanager/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-maps-addressvalidation/package.json b/packages/google-maps-addressvalidation/package.json index d283929400a7..b51d0d48d797 100644 --- a/packages/google-maps-addressvalidation/package.json +++ b/packages/google-maps-addressvalidation/package.json @@ -13,7 +13,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-maps-areainsights/package.json b/packages/google-maps-areainsights/package.json index bf1e8cbcbb7a..81924913b1c8 100644 --- a/packages/google-maps-areainsights/package.json +++ b/packages/google-maps-areainsights/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-maps-areainsights", "keywords": [ diff --git a/packages/google-maps-fleetengine-delivery/package.json b/packages/google-maps-fleetengine-delivery/package.json index 1bec5713fb4c..1d84158cc1d5 100644 --- a/packages/google-maps-fleetengine-delivery/package.json +++ b/packages/google-maps-fleetengine-delivery/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-maps-fleetengine-delivery", "keywords": [ diff --git a/packages/google-maps-fleetengine/package.json b/packages/google-maps-fleetengine/package.json index 1b865b8a6ad2..d618f1e5ac8b 100644 --- a/packages/google-maps-fleetengine/package.json +++ b/packages/google-maps-fleetengine/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-maps-fleetengine", "keywords": [ diff --git a/packages/google-maps-geocode/package.json b/packages/google-maps-geocode/package.json index da9f9bf07d4a..557b1c2a5062 100644 --- a/packages/google-maps-geocode/package.json +++ b/packages/google-maps-geocode/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-maps-geocode", "keywords": [ diff --git a/packages/google-maps-mapsplatformdatasets/package.json b/packages/google-maps-mapsplatformdatasets/package.json index 2b3fab5f2ca1..3e35bc3ff7df 100644 --- a/packages/google-maps-mapsplatformdatasets/package.json +++ b/packages/google-maps-mapsplatformdatasets/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-maps-mapsplatformdatasets", diff --git a/packages/google-maps-navconnect/package.json b/packages/google-maps-navconnect/package.json index f99069ac6e8a..3a15d0158de9 100644 --- a/packages/google-maps-navconnect/package.json +++ b/packages/google-maps-navconnect/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-maps-navconnect", "keywords": [ diff --git a/packages/google-maps-places/package.json b/packages/google-maps-places/package.json index 0a5cc7a1febb..6bc980f3efb2 100644 --- a/packages/google-maps-places/package.json +++ b/packages/google-maps-places/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-maps-places", "keywords": [ diff --git a/packages/google-maps-routeoptimization/package.json b/packages/google-maps-routeoptimization/package.json index 644456e6057b..0a0528c148aa 100644 --- a/packages/google-maps-routeoptimization/package.json +++ b/packages/google-maps-routeoptimization/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-maps-routeoptimization", "keywords": [ diff --git a/packages/google-maps-routing/package.json b/packages/google-maps-routing/package.json index 31bedb4cfe8d..4e32d178aa73 100644 --- a/packages/google-maps-routing/package.json +++ b/packages/google-maps-routing/package.json @@ -13,7 +13,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-maps-solar/package.json b/packages/google-maps-solar/package.json index e6739c5e9f93..772e6fca90be 100644 --- a/packages/google-maps-solar/package.json +++ b/packages/google-maps-solar/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-maps-solar", "keywords": [ diff --git a/packages/google-marketingplatform-admin/package.json b/packages/google-marketingplatform-admin/package.json index df5edfb9379f..8093d6e063bd 100644 --- a/packages/google-marketingplatform-admin/package.json +++ b/packages/google-marketingplatform-admin/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-marketingplatform-admin", "keywords": [ diff --git a/packages/google-monitoring-dashboard/package.json b/packages/google-monitoring-dashboard/package.json index 841f16d29db6..b7d061f86113 100644 --- a/packages/google-monitoring-dashboard/package.json +++ b/packages/google-monitoring-dashboard/package.json @@ -12,7 +12,6 @@ "author": "Google LLC", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "main": "build/src/index.js", diff --git a/packages/google-privacy-dlp/package.json b/packages/google-privacy-dlp/package.json index 4c30af21c31f..131976fd4f0c 100644 --- a/packages/google-privacy-dlp/package.json +++ b/packages/google-privacy-dlp/package.json @@ -14,7 +14,6 @@ }, "main": "build/src/index.js", "files": [ - "build/protos", "build/src", "!build/src/**/*.map" ], diff --git a/packages/google-shopping-css/package.json b/packages/google-shopping-css/package.json index 856d6449e89c..5a2e363bea32 100644 --- a/packages/google-shopping-css/package.json +++ b/packages/google-shopping-css/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-shopping-css", "keywords": [ diff --git a/packages/google-shopping-merchant-accounts/package.json b/packages/google-shopping-merchant-accounts/package.json index c82f199f828b..0b4ba69c002c 100644 --- a/packages/google-shopping-merchant-accounts/package.json +++ b/packages/google-shopping-merchant-accounts/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-shopping-merchant-accounts", "keywords": [ diff --git a/packages/google-shopping-merchant-conversions/package.json b/packages/google-shopping-merchant-conversions/package.json index 6a6b31fe5af8..5f7d31e1e6cc 100644 --- a/packages/google-shopping-merchant-conversions/package.json +++ b/packages/google-shopping-merchant-conversions/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-shopping-merchant-conversions", "keywords": [ diff --git a/packages/google-shopping-merchant-datasources/package.json b/packages/google-shopping-merchant-datasources/package.json index 15c35404310b..7aad38fb953b 100644 --- a/packages/google-shopping-merchant-datasources/package.json +++ b/packages/google-shopping-merchant-datasources/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-shopping-merchant-datasources", "keywords": [ diff --git a/packages/google-shopping-merchant-inventories/package.json b/packages/google-shopping-merchant-inventories/package.json index 7a26b6989518..3e13679a3bb1 100644 --- a/packages/google-shopping-merchant-inventories/package.json +++ b/packages/google-shopping-merchant-inventories/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-shopping-merchant-inventories", "keywords": [ diff --git a/packages/google-shopping-merchant-issueresolution/package.json b/packages/google-shopping-merchant-issueresolution/package.json index 37076822f893..e217b56e4d7f 100644 --- a/packages/google-shopping-merchant-issueresolution/package.json +++ b/packages/google-shopping-merchant-issueresolution/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-shopping-merchant-issueresolution", "keywords": [ diff --git a/packages/google-shopping-merchant-lfp/package.json b/packages/google-shopping-merchant-lfp/package.json index ee125338c3aa..8fb93296965a 100644 --- a/packages/google-shopping-merchant-lfp/package.json +++ b/packages/google-shopping-merchant-lfp/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-shopping-merchant-lfp", "keywords": [ diff --git a/packages/google-shopping-merchant-notifications/package.json b/packages/google-shopping-merchant-notifications/package.json index 6f79520704ea..64bc95b39e35 100644 --- a/packages/google-shopping-merchant-notifications/package.json +++ b/packages/google-shopping-merchant-notifications/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-shopping-merchant-notifications", "keywords": [ diff --git a/packages/google-shopping-merchant-ordertracking/package.json b/packages/google-shopping-merchant-ordertracking/package.json index 69e2dbe9fe8e..45b65b37c580 100644 --- a/packages/google-shopping-merchant-ordertracking/package.json +++ b/packages/google-shopping-merchant-ordertracking/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-shopping-merchant-ordertracking", "keywords": [ diff --git a/packages/google-shopping-merchant-products/package.json b/packages/google-shopping-merchant-products/package.json index 2e375ba6fa8a..c507ecdc408d 100644 --- a/packages/google-shopping-merchant-products/package.json +++ b/packages/google-shopping-merchant-products/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-shopping-merchant-products", "keywords": [ diff --git a/packages/google-shopping-merchant-promotions/package.json b/packages/google-shopping-merchant-promotions/package.json index 6ff4476e1df4..4509604343b9 100644 --- a/packages/google-shopping-merchant-promotions/package.json +++ b/packages/google-shopping-merchant-promotions/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-shopping-merchant-promotions", "keywords": [ diff --git a/packages/google-shopping-merchant-quota/package.json b/packages/google-shopping-merchant-quota/package.json index e248d18e65a9..2b0c14ede5e3 100644 --- a/packages/google-shopping-merchant-quota/package.json +++ b/packages/google-shopping-merchant-quota/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-shopping-merchant-quota", "keywords": [ diff --git a/packages/google-shopping-merchant-reports/package.json b/packages/google-shopping-merchant-reports/package.json index 0fbdd9781e40..a168d64457e7 100644 --- a/packages/google-shopping-merchant-reports/package.json +++ b/packages/google-shopping-merchant-reports/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-shopping-merchant-reports", "keywords": [ diff --git a/packages/google-shopping-merchant-reviews/package.json b/packages/google-shopping-merchant-reviews/package.json index 0d11ef5e8fcc..121b14228a55 100644 --- a/packages/google-shopping-merchant-reviews/package.json +++ b/packages/google-shopping-merchant-reviews/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-shopping-merchant-reviews", "keywords": [ diff --git a/packages/google-storage-control/package.json b/packages/google-storage-control/package.json index 55686cf6a02f..9862ec7542a9 100644 --- a/packages/google-storage-control/package.json +++ b/packages/google-storage-control/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-storage-control", "keywords": [ diff --git a/packages/google-storagetransfer/package.json b/packages/google-storagetransfer/package.json index c05a215e8ac5..418a503670a9 100644 --- a/packages/google-storagetransfer/package.json +++ b/packages/google-storagetransfer/package.json @@ -12,7 +12,6 @@ "main": "build/src/index.js", "files": [ "build/src", - "build/protos", "!build/src/**/*.map" ], "keywords": [ diff --git a/packages/google-streetview-publish/package.json b/packages/google-streetview-publish/package.json index 19bc0e0d9017..a640fad33ba7 100644 --- a/packages/google-streetview-publish/package.json +++ b/packages/google-streetview-publish/package.json @@ -11,8 +11,7 @@ "author": "Google LLC", "main": "build/src/index.js", "files": [ - "build/src", - "build/protos" + "build/src" ], "homepage": "https://github.com/googleapis/google-cloud-node/tree/main/packages/google-streetview-publish", "keywords": [ diff --git a/packages/grafeas/package.json b/packages/grafeas/package.json index 71e4475056e2..364b88950c9c 100644 --- a/packages/grafeas/package.json +++ b/packages/grafeas/package.json @@ -10,7 +10,6 @@ "description": "Grafeas API client for Node.js", "main": "build/src/index.js", "files": [ - "build/protos", "build/src", "!build/src/**/*.map" ],