fix: Make AWS credential work with global AWS services (#9631)

This commit is contained in:
Elias Meire
2024-06-05 16:53:45 +02:00
committed by GitHub
parent a946ead46e
commit 9dbea7393a
3 changed files with 188 additions and 19 deletions

View File

@@ -126,6 +126,28 @@ export const regions = [
] as const;
export type AWSRegion = (typeof regions)[number]['name'];
export type AwsCredentialsType = {
region: AWSRegion;
accessKeyId: string;
secretAccessKey: string;
temporaryCredentials: boolean;
customEndpoints: boolean;
sessionToken?: string;
rekognitionEndpoint?: string;
lambdaEndpoint?: string;
snsEndpoint?: string;
sesEndpoint?: string;
sqsEndpoint?: string;
s3Endpoint?: string;
};
// Some AWS services are global and don't have a region
// https://docs.aws.amazon.com/general/latest/gr/rande.html#global-endpoints
// Example: iam.amazonaws.com (global), s3.us-east-1.amazonaws.com (regional)
function parseAwsUrl(url: URL): { region: AWSRegion | null; service: string } {
const [service, region] = url.hostname.replace('amazonaws.com', '').split('.');
return { service, region: region as AWSRegion };
}
export class Aws implements ICredentialType {
name = 'aws';
@@ -276,18 +298,19 @@ export class Aws implements ICredentialType {
];
async authenticate(
credentials: ICredentialDataDecryptedObject,
rawCredentials: ICredentialDataDecryptedObject,
requestOptions: IHttpRequestOptions,
): Promise<IHttpRequestOptions> {
const credentials = rawCredentials as AwsCredentialsType;
let endpoint: URL;
let service = requestOptions.qs?.service as string;
let path = requestOptions.qs?.path;
let path = (requestOptions.qs?.path as string) ?? '';
const method = requestOptions.method;
let body = requestOptions.body;
let region = credentials.region;
if (requestOptions.qs?._region) {
region = requestOptions.qs._region as string;
region = requestOptions.qs._region as AWSRegion;
delete requestOptions.qs._region;
}
@@ -310,36 +333,40 @@ export class Aws implements ICredentialType {
console.log(err);
}
}
service = endpoint.hostname.split('.')[0];
region = endpoint.hostname.split('.')[1];
const parsed = parseAwsUrl(endpoint);
service = parsed.service;
if (parsed.region) {
region = parsed.region;
}
} else {
if (!requestOptions.baseURL && !requestOptions.url) {
let endpointString: string;
if (service === 'lambda' && credentials.lambdaEndpoint) {
endpointString = credentials.lambdaEndpoint as string;
endpointString = credentials.lambdaEndpoint;
} else if (service === 'sns' && credentials.snsEndpoint) {
endpointString = credentials.snsEndpoint as string;
endpointString = credentials.snsEndpoint;
} else if (service === 'sqs' && credentials.sqsEndpoint) {
endpointString = credentials.sqsEndpoint as string;
endpointString = credentials.sqsEndpoint;
} else if (service === 's3' && credentials.s3Endpoint) {
endpointString = credentials.s3Endpoint as string;
endpointString = credentials.s3Endpoint;
} else if (service === 'ses' && credentials.sesEndpoint) {
endpointString = credentials.sesEndpoint as string;
endpointString = credentials.sesEndpoint;
} else if (service === 'rekognition' && credentials.rekognitionEndpoint) {
endpointString = credentials.rekognitionEndpoint as string;
endpointString = credentials.rekognitionEndpoint;
} else if (service === 'sqs' && credentials.sqsEndpoint) {
endpointString = credentials.sqsEndpoint as string;
endpointString = credentials.sqsEndpoint;
} else if (service) {
endpointString = `https://${service}.${region}.amazonaws.com`;
}
endpoint = new URL(
endpointString!.replace('{region}', region as string) + (path as string),
);
endpoint = new URL(endpointString!.replace('{region}', region) + path);
} else {
// If no endpoint is set, we try to decompose the path and use the default endpoint
const customUrl = new URL(`${requestOptions.baseURL!}${requestOptions.url}${path ?? ''}`);
service = customUrl.hostname.split('.')[0];
region = customUrl.hostname.split('.')[1];
const customUrl = new URL(`${requestOptions.baseURL!}${requestOptions.url}${path}`);
const parsed = parseAwsUrl(customUrl);
service = parsed.service;
if (parsed.region) {
region = parsed.region;
}
if (service === 'sts') {
try {
customUrl.searchParams.set('Action', 'GetCallerIdentity');