snowflake-sdk
Version:
Node.js driver for Snowflake
110 lines • 4.42 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getAwsCredentials = getAwsCredentials;
exports.getAwsRegion = getAwsRegion;
exports.getStsHostname = getStsHostname;
exports.getAwsAttestationToken = getAwsAttestationToken;
const credential_provider_node_1 = require("@aws-sdk/credential-provider-node");
const client_sts_1 = require("@aws-sdk/client-sts");
const ec2_metadata_service_1 = require("@aws-sdk/ec2-metadata-service");
const protocol_http_1 = require("@smithy/protocol-http");
const signature_v4_1 = require("@smithy/signature-v4");
const sha256_js_1 = require("@aws-crypto/sha256-js");
const logger_1 = __importDefault(require("../../logger"));
async function getAwsCredentials(region, impersonationPath = []) {
(0, logger_1.default)().debug('Getting AWS credentials from default provider');
let credentials = await (0, credential_provider_node_1.defaultProvider)()();
for (const roleArn of impersonationPath) {
(0, logger_1.default)().debug(`Getting AWS credentials from impersonation role: ${roleArn}`);
const stsClient = new client_sts_1.STSClient({
credentials,
region,
});
const command = new client_sts_1.AssumeRoleCommand({
RoleArn: roleArn,
RoleSessionName: 'identity-federation-session',
});
const { Credentials } = await stsClient.send(command);
if (Credentials?.AccessKeyId && Credentials?.SecretAccessKey) {
credentials = {
accessKeyId: Credentials.AccessKeyId,
secretAccessKey: Credentials.SecretAccessKey,
sessionToken: Credentials.SessionToken,
};
}
else {
throw new Error(`Failed to get credentials from impersonation role ${roleArn}`);
}
}
return credentials;
}
async function getAwsRegion() {
if (process.env.AWS_REGION) {
(0, logger_1.default)().debug('Getting AWS region from AWS_REGION');
return process.env.AWS_REGION; // Lambda
}
else {
(0, logger_1.default)().debug('Getting AWS region from EC2 metadata service');
return new ec2_metadata_service_1.MetadataService().request('/latest/meta-data/placement/region', {}); // EC2
}
}
function getStsHostname(region) {
const domain = region.startsWith('cn-') ? 'amazonaws.com.cn' : 'amazonaws.com';
return `sts.${region}.${domain}`;
}
async function getAwsAttestationToken(useOutboundToken = false, impersonationPath) {
const region = await getAwsRegion();
const credentials = await getAwsCredentials(region, impersonationPath);
if (useOutboundToken) {
return getOutboundWebIdentityToken(region, credentials);
}
else {
return getCallerIdentityToken(region, credentials);
}
}
async function getCallerIdentityToken(region, credentials) {
const stsHostname = getStsHostname(region);
const request = new protocol_http_1.HttpRequest({
method: 'POST',
protocol: 'https',
hostname: stsHostname,
path: '/',
headers: {
host: stsHostname,
'x-snowflake-audience': 'snowflakecomputing.com',
},
query: {
Action: 'GetCallerIdentity',
Version: '2011-06-15',
},
});
const signedRequest = await new signature_v4_1.SignatureV4({
credentials,
applyChecksum: false,
region,
service: 'sts',
sha256: sha256_js_1.Sha256,
}).sign(request);
const token = {
url: `https://${stsHostname}/?Action=GetCallerIdentity&Version=2011-06-15`,
method: 'POST',
headers: signedRequest.headers,
};
return btoa(JSON.stringify(token));
}
async function getOutboundWebIdentityToken(region, credentials) {
const stsClient = new client_sts_1.STSClient({ credentials, region });
const response = await stsClient.send(new client_sts_1.GetWebIdentityTokenCommand({
Audience: ['snowflakecomputing.com'],
SigningAlgorithm: 'ES384',
}));
const token = response.WebIdentityToken;
if (!token) {
throw new Error('Failed to obtain AWS web identity token from STS');
}
return token;
}
//# sourceMappingURL=attestation_aws.js.map