Some checks failed
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled
173 lines
4.7 KiB
TypeScript
173 lines
4.7 KiB
TypeScript
import type {
|
|
ICredentialDataDecryptedObject,
|
|
ICredentialType,
|
|
IHttpRequestOptions,
|
|
INodeProperties,
|
|
} from 'n8n-workflow';
|
|
import { ApplicationError } from 'n8n-workflow';
|
|
|
|
import { type AwsAssumeRoleCredentialsType, type AWSRegion } from './common/aws/types';
|
|
import { awsCustomEndpoints, awsRegionProperty } from './common/aws/descriptions';
|
|
import {
|
|
assumeRole,
|
|
awsCredentialsTest,
|
|
awsGetSignInOptionsAndUpdateRequest,
|
|
signOptions,
|
|
} from './common/aws/utils';
|
|
|
|
export class AwsAssumeRole implements ICredentialType {
|
|
name = 'awsAssumeRole';
|
|
|
|
displayName = 'AWS (Assume Role)';
|
|
|
|
documentationUrl = 'awsassumerole';
|
|
|
|
icon = { light: 'file:icons/AWS.svg', dark: 'file:icons/AWS.dark.svg' } as const;
|
|
|
|
properties: INodeProperties[] = [
|
|
awsRegionProperty,
|
|
{
|
|
displayName: 'Use System Credentials',
|
|
name: 'useSystemCredentialsForRole',
|
|
description:
|
|
'Use system credentials (environment variables, container role, etc.) to call STS.AssumeRole. Access to AWS system credentials is disabled by default and must be explicitly enabled. See <a href="https://docs.n8n.io/integrations/credentials/awsassumerole/">documentation</a> for more information.',
|
|
type: 'boolean',
|
|
default: false,
|
|
displayOptions: {
|
|
hideOnCloud: true,
|
|
},
|
|
},
|
|
{
|
|
displayName: 'STS Access Key ID',
|
|
name: 'stsAccessKeyId',
|
|
description: 'Access Key ID to use for the STS.AssumeRole call',
|
|
// eslint-disable-next-line n8n-nodes-base/cred-class-field-type-options-password-missing
|
|
type: 'string',
|
|
displayOptions: {
|
|
show: {
|
|
useSystemCredentialsForRole: [false],
|
|
},
|
|
},
|
|
required: true,
|
|
default: '',
|
|
},
|
|
{
|
|
displayName: 'STS Access Key Secret',
|
|
name: 'stsSecretAccessKey',
|
|
description: 'Secret Access Key to use for the STS.AssumeRole call',
|
|
type: 'string',
|
|
displayOptions: {
|
|
show: {
|
|
useSystemCredentialsForRole: [false],
|
|
},
|
|
},
|
|
required: true,
|
|
default: '',
|
|
typeOptions: {
|
|
password: true,
|
|
},
|
|
},
|
|
{
|
|
displayName: 'STS Session Token (optional)',
|
|
name: 'stsSessionToken',
|
|
description: 'Session Token to use for the STS.AssumeRole call',
|
|
type: 'string',
|
|
displayOptions: {
|
|
show: {
|
|
useSystemCredentialsForRole: [false],
|
|
},
|
|
},
|
|
default: '',
|
|
typeOptions: {
|
|
password: true,
|
|
},
|
|
},
|
|
|
|
{
|
|
displayName: 'Role ARN',
|
|
name: 'roleArn',
|
|
description: 'The ARN of the role to assume (e.g., arn:aws:iam::123456789012:role/MyRole)',
|
|
type: 'string',
|
|
required: true,
|
|
default: '',
|
|
placeholder: 'arn:aws:iam::123456789012:role/MyRole',
|
|
},
|
|
{
|
|
displayName: 'External ID',
|
|
name: 'externalId',
|
|
description:
|
|
"External ID for cross-account role assumption (should be required by your role's trust policy)",
|
|
type: 'string',
|
|
required: true,
|
|
default: '',
|
|
typeOptions: {
|
|
password: true,
|
|
},
|
|
},
|
|
{
|
|
displayName: 'Role Session Name',
|
|
name: 'roleSessionName',
|
|
description: 'Name for the role session',
|
|
type: 'string',
|
|
required: true,
|
|
default: 'n8n-session',
|
|
},
|
|
...awsCustomEndpoints,
|
|
];
|
|
|
|
async authenticate(
|
|
decryptedCredentials: ICredentialDataDecryptedObject,
|
|
requestOptions: IHttpRequestOptions,
|
|
): Promise<IHttpRequestOptions> {
|
|
const credentials = decryptedCredentials as AwsAssumeRoleCredentialsType;
|
|
const service = requestOptions.qs?.service as string;
|
|
const path = (requestOptions.qs?.path as string) ?? '';
|
|
const method = requestOptions.method;
|
|
|
|
let region = credentials.region;
|
|
if (requestOptions.qs?._region) {
|
|
region = requestOptions.qs._region as AWSRegion;
|
|
delete requestOptions.qs._region;
|
|
}
|
|
|
|
let finalCredentials = credentials;
|
|
let securityHeaders: {
|
|
accessKeyId: string;
|
|
secretAccessKey: string;
|
|
sessionToken: string;
|
|
};
|
|
|
|
if (!credentials.roleArn || credentials.roleArn.trim() === '') {
|
|
throw new ApplicationError('Role ARN is required when assuming a role.');
|
|
}
|
|
if (!credentials.externalId || credentials.externalId.trim() === '') {
|
|
throw new ApplicationError('External ID is required when assuming a role.');
|
|
}
|
|
if (!credentials.roleSessionName || credentials.roleSessionName.trim() === '') {
|
|
throw new ApplicationError('Role Session Name is required when assuming a role.');
|
|
}
|
|
try {
|
|
securityHeaders = await assumeRole(credentials, region);
|
|
finalCredentials = { ...credentials, ...securityHeaders };
|
|
} catch (error) {
|
|
console.error('Failed to assume role:', error);
|
|
throw new ApplicationError(
|
|
`Failed to assume role: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
);
|
|
}
|
|
|
|
const { signOpts, url } = awsGetSignInOptionsAndUpdateRequest(
|
|
requestOptions,
|
|
finalCredentials,
|
|
path,
|
|
method,
|
|
service,
|
|
region,
|
|
);
|
|
|
|
return signOptions(requestOptions, signOpts, securityHeaders, url, method);
|
|
}
|
|
|
|
test = awsCredentialsTest;
|
|
}
|