aws-crt
Version:
NodeJS/browser bindings to the aws-c-* libraries
292 lines (233 loc) • 11.2 kB
text/typescript
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/
import { auth as native, http as native_http } from '../index';
import { io as native_io } from '../index';
import { ProxyConfig, ProxyTestType } from "@test/proxy";
import { InputStream } from './io';
import { PassThrough } from "stream";
import { aws_sign_request, aws_verify_sigv4a_signing } from './auth';
const DATE_STR = '2015-08-30T12:36:00Z';
// Test values copied from aws-c-auth/tests/aws-sig-v4-test-suite/get-vanilla"
const SIGV4TEST_ACCESS_KEY_ID = 'AKIDEXAMPLE';
const SIGV4TEST_SECRET_ACCESS_KEY = 'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY';
const SIGV4TEST_SERVICE = 'service';
const SIGV4TEST_REGION = 'us-east-1';
const SIGV4TEST_METHOD = 'GET';
const SIGV4TEST_PATH = '/';
const SIGV4TEST_UNSIGNED_HEADERS: [string, string][] = [
['Host', 'example.amazonaws.com']
];
const SIGV4TEST_SIGNED_HEADERS: [string, string][] = [
['Host', 'example.amazonaws.com'],
['Authorization', 'AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=5fa00fa31553b73ebf1942676e86291e8372ff2a2260956d9b8aae1d763fbf31'],
['X-Amz-Date', DATE_STR.replace(/[-:]/g, '')],
];
const SIGV4ATEST_SIGNED_HEADERS: [string, string][] = [
['Host', 'example.amazonaws.com'],
['X-Amz-Date', DATE_STR.replace(/[-:]/g, '')],
['X-Amz-Region-Set', SIGV4TEST_REGION],
['Authorization', 'AWS4-ECDSA-P256-SHA256 Credential=AKIDEXAMPLE/20150830/service/aws4_request, SignedHeaders=host;x-amz-date;x-amz-region-set, Signature='],
];
const SIGV4ATEST_EXPECTED_CANONICAL_REQUEST: string =
SIGV4TEST_METHOD + "\n" +
SIGV4TEST_PATH + "\n" +
"\n" +
"host:example.amazonaws.com\n" +
"x-amz-date:20150830T123600Z\n" +
"x-amz-region-set:" + SIGV4TEST_REGION + "\n" +
"\n" +
"host;x-amz-date;x-amz-region-set\n" +
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
const ECC_KEY_PUB = {
X: "b6618f6a65740a99e650b33b6b4b5bd0d43b176d721a3edfea7e7d2d56d936b1",
Y: "865ed22a7eadc9c5cb9d2cbaca1b3699139fedc5043dc6661864218330c8e518"
};
test('AWS Signer SigV4 Headers', async () => {
const credentials_provider = native.AwsCredentialsProvider.newStatic(
SIGV4TEST_ACCESS_KEY_ID,
SIGV4TEST_SECRET_ACCESS_KEY,
);
const signing_config: native.AwsSigningConfig = {
algorithm: native.AwsSigningAlgorithm.SigV4,
signature_type: native.AwsSignatureType.HttpRequestViaHeaders,
provider: credentials_provider,
region: SIGV4TEST_REGION,
service: SIGV4TEST_SERVICE,
date: new Date(DATE_STR),
signed_body_value: native.AwsSignedBodyValue.EmptySha256,
signed_body_header: native.AwsSignedBodyHeaderType.None,
};
let http_request = new native_http.HttpRequest(
SIGV4TEST_METHOD,
SIGV4TEST_PATH,
new native_http.HttpHeaders(SIGV4TEST_UNSIGNED_HEADERS));
const signing_result = await aws_sign_request(http_request, signing_config);
expect(http_request).toBe(signing_result); // should be same object
// everything should be the same EXCEPT the addition of the Authorization header
expect(http_request.method).toBe(SIGV4TEST_METHOD);
expect(http_request.path).toBe(SIGV4TEST_PATH);
const expected_headers = [...SIGV4TEST_SIGNED_HEADERS].sort()
const signed_headers = [...http_request.headers._flatten()].sort()
expect(signed_headers).toEqual(expected_headers)
});
test('AWS Signer SigV4 Request with body', async () => {
const credentials_provider = native.AwsCredentialsProvider.newStatic(
SIGV4TEST_ACCESS_KEY_ID,
SIGV4TEST_SECRET_ACCESS_KEY,
);
const signing_config: native.AwsSigningConfig = {
algorithm: native.AwsSigningAlgorithm.SigV4,
signature_type: native.AwsSignatureType.HttpRequestViaHeaders,
provider: credentials_provider,
region: SIGV4TEST_REGION,
service: SIGV4TEST_SERVICE,
date: new Date(DATE_STR),
signed_body_header: native.AwsSignedBodyHeaderType.None,
};
let stream = new PassThrough();
let body_stream;
stream.write("test");
stream.end(() => {
body_stream = new InputStream(stream);
});
let http_request = new native_http.HttpRequest(
SIGV4TEST_METHOD,
SIGV4TEST_PATH,
new native_http.HttpHeaders(SIGV4TEST_UNSIGNED_HEADERS),
body_stream);
const signing_result = await aws_sign_request(http_request, signing_config);
expect(http_request).toBe(signing_result); // should be same object
// everything should be the same EXCEPT the addition of the Authorization header
expect(http_request.method).toBe(SIGV4TEST_METHOD);
expect(http_request.path).toBe(SIGV4TEST_PATH);
});
test('AWS Signer SigV4A Headers', async () => {
const credentials_provider = native.AwsCredentialsProvider.newStatic(
SIGV4TEST_ACCESS_KEY_ID,
SIGV4TEST_SECRET_ACCESS_KEY,
);
const signing_config: native.AwsSigningConfig = {
algorithm: native.AwsSigningAlgorithm.SigV4Asymmetric,
signature_type: native.AwsSignatureType.HttpRequestViaHeaders,
provider: credentials_provider,
region: SIGV4TEST_REGION,
service: SIGV4TEST_SERVICE,
date: new Date(DATE_STR),
signed_body_value: native.AwsSignedBodyValue.EmptySha256,
signed_body_header: native.AwsSignedBodyHeaderType.None,
};
let http_request = new native_http.HttpRequest(
SIGV4TEST_METHOD,
SIGV4TEST_PATH,
new native_http.HttpHeaders(SIGV4TEST_UNSIGNED_HEADERS));
// copy the request for verification
let ori_http_request = new native_http.HttpRequest(
SIGV4TEST_METHOD,
SIGV4TEST_PATH,
new native_http.HttpHeaders(SIGV4TEST_UNSIGNED_HEADERS));
const signing_result = await aws_sign_request(http_request, signing_config);
expect(http_request).toBe(signing_result); // should be same object
// everything should be the same EXCEPT the addition of the Authorization header
expect(http_request.method).toBe(SIGV4TEST_METHOD);
expect(http_request.path).toBe(SIGV4TEST_PATH);
// Get the signature string
let authorization = http_request.headers.get("Authorization");
let separator = "Signature=";
let splits = authorization.split(separator);
let signature = splits[splits.length - 1];
// Add the signature to expected header
SIGV4ATEST_SIGNED_HEADERS[3][1] += signature;
expect(http_request.headers._flatten()).toEqual(SIGV4ATEST_SIGNED_HEADERS);
// Verify the signature
let verification_result = aws_verify_sigv4a_signing(
ori_http_request, signing_config, SIGV4ATEST_EXPECTED_CANONICAL_REQUEST, signature, ECC_KEY_PUB.X, ECC_KEY_PUB.Y);
expect(verification_result).toBe(true);
});
// Without a binding for fetching credentials yet, so just check creation successful
test('Default credentials provider create', async () => {
const credentials_provider = native.AwsCredentialsProvider.newDefault(new native_io.ClientBootstrap());
expect(credentials_provider);
});
test('Default credentials provider create no bootstrap', async () => {
const credentials_provider = native.AwsCredentialsProvider.newDefault();
expect(credentials_provider);
});
test('Cognito credentials provider create success - minimal config', async () => {
let config : native.CognitoCredentialsProviderConfig = {
endpoint: "sample.com",
identity: "MyIdentity"
};
const credentials_provider = native.AwsCredentialsProvider.newCognito(config);
expect(credentials_provider);
});
test('Cognito credentials provider create success - maximal config', async () => {
let tlsCtx : native_io.ClientTlsContext = new native_io.ClientTlsContext();
let config : native.CognitoCredentialsProviderConfig = {
endpoint: "sample.com",
identity: "MyIdentity",
logins: [
{ identityProviderName: "SecureProvider", identityProviderToken: "RootAccess" },
{ identityProviderName: "SketchyProvider", identityProviderToken: "ImIn" },
],
customRoleArn: "arn:us-east-1:totally4real",
tlsContext: tlsCtx,
bootstrap: new native_io.ClientBootstrap(),
};
const credentials_provider = native.AwsCredentialsProvider.newCognito(config);
expect(credentials_provider);
});
const AWS_TESTING_COGNITO_IDENTITY : string = process.env.AWS_TESTING_COGNITO_IDENTITY ?? "";
function hasCognitoTestEnvironment() {
return AWS_TESTING_COGNITO_IDENTITY !== "";
}
const conditional_test = (condition : boolean) => condition ? it : it.skip;
async function do_body_request_signing(provider: native.AwsCredentialsProvider) {
const signing_config: native.AwsSigningConfig = {
algorithm: native.AwsSigningAlgorithm.SigV4,
signature_type: native.AwsSignatureType.HttpRequestViaHeaders,
provider: provider,
region: SIGV4TEST_REGION,
service: SIGV4TEST_SERVICE,
date: new Date(DATE_STR),
signed_body_header: native.AwsSignedBodyHeaderType.None,
};
let stream = new PassThrough();
let body_stream;
stream.write("test");
stream.end(() => {
body_stream = new InputStream(stream);
});
let http_request = new native_http.HttpRequest(
SIGV4TEST_METHOD,
SIGV4TEST_PATH,
new native_http.HttpHeaders(SIGV4TEST_UNSIGNED_HEADERS),
body_stream);
return await aws_sign_request(http_request, signing_config);
}
conditional_test(hasCognitoTestEnvironment())('Cognito credentials provider usage success - signing', async () => {
let config : native.CognitoCredentialsProviderConfig = {
endpoint: "cognito-identity.us-east-1.amazonaws.com",
identity: AWS_TESTING_COGNITO_IDENTITY
};
const credentials_provider = native.AwsCredentialsProvider.newCognito(config);
expect(credentials_provider);
const signing_result = await do_body_request_signing(credentials_provider);
expect(signing_result.method).toBe(SIGV4TEST_METHOD);
expect(signing_result.path).toBe(SIGV4TEST_PATH);
});
conditional_test(hasCognitoTestEnvironment() && ProxyConfig.is_valid())('Cognito credentials provider through http proxy usage success - signing', async () => {
let proxyOptions: native_http.HttpProxyOptions = ProxyConfig.create_http_proxy_options_from_environment(
ProxyTestType.TUNNELING_HTTPS, native_http.HttpProxyAuthenticationType.None);
let config : native.CognitoCredentialsProviderConfig = {
endpoint: "cognito-identity.us-east-1.amazonaws.com",
identity: AWS_TESTING_COGNITO_IDENTITY,
httpProxyOptions: proxyOptions
};
const credentials_provider = native.AwsCredentialsProvider.newCognito(config);
expect(credentials_provider);
const signing_result = await do_body_request_signing(credentials_provider);
expect(signing_result.method).toBe(SIGV4TEST_METHOD);
expect(signing_result.path).toBe(SIGV4TEST_PATH);
});