1- // import { diag } from '@opentelemetry/api';
2- // import { getNodeVersion } from '../../../../utils';
1+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+ // SPDX-License-Identifier: Apache-2.0
3+ import { diag } from '@opentelemetry/api' ;
4+ import { getNodeVersion } from '../../../../utils' ;
5+ let SignatureV4 : any ;
6+ let HttpRequest : any ;
7+ let defaultProvider : any ;
8+ let Sha256 : any ;
39
4- // let SignatureV4: any;
5- // let HttpRequest: any;
6- // let defaultProvider: any;
7- // let Sha256: any;
10+ let dependenciesLoaded = false ;
811
9- // const nodeVersionSupported = getNodeVersion() >= 16;
12+ if ( getNodeVersion ( ) >= 16 ) {
13+ try {
14+ defaultProvider = require ( '@aws-sdk/credential-provider-node' ) . defaultProvider ;
15+ Sha256 = require ( '@aws-crypto/sha256-js' ) . Sha256 ;
16+ SignatureV4 = require ( '@smithy/signature-v4' ) . SignatureV4 ;
17+ HttpRequest = require ( '@smithy/protocol-http' ) . HttpRequest ;
18+ dependenciesLoaded = true ;
19+ } catch ( error ) {
20+ diag . error ( `Failed to load required AWS dependency for SigV4 Signing: ${ error } ` ) ;
21+ }
22+ } else {
23+ diag . error ( 'SigV4 signing requires at least Node major version 16' ) ;
24+ }
1025
11- // if (nodeVersionSupported) {
12- // try {
13- // const { defaultProvider: awsDefaultProvider } = require('@aws-sdk/credential-provider-node');
14- // const { Sha256: awsSha256 } = require('@aws-crypto/sha256-js');
15- // const { SignatureV4: awsSignatureV4 } = require('@smithy/signature-v4');
16- // const { HttpRequest: awsHttpRequest } = require('@smithy/protocol-http');
17-
18- // // Assign to module-level variables
19- // defaultProvider = awsDefaultProvider;
20- // Sha256 = awsSha256;
21- // SignatureV4 = awsSignatureV4;
22- // HttpRequest = awsHttpRequest;
23- // } catch (error) {
24- // diag.error(`Failed to load required AWS dependency for SigV4 Signing: ${error}`);
25- // }
26- // }
26+ export class AwsAuthenticator {
27+ private region : string ;
28+ private service : string ;
2729
28- // export class AwsAuthenticator {
30+ constructor ( region : string , service : string ) {
31+ this . region = region ;
32+ this . service = service ;
33+ }
2934
30- // private static readonly SERVICE_NAME: string = 'xray';
31- // private endpoint: string;
32- // private region: string;
33- // private service: string ;
35+ public async authenticate ( endpoint : string , headers : Record < string , string > , serializedData : Uint8Array | undefined ) {
36+ // Only do SigV4 Signing if the required dependencies are installed.
37+ if ( dependenciesLoaded ) {
38+ const url = new URL ( endpoint ) ;
3439
35- // // Holds the dependencies needed to sign the SigV4 headers
36- // private defaultProvider: any;
37- // private sha256: any;
38- // private signatureV4: any;
39- // private httpRequest: any;
40+ if ( serializedData == undefined ) {
41+ diag . error ( 'Given serialized data is undefined. Not authenticating.' ) ;
42+ return ;
43+ }
4044
41- // constructor(endpoint: string, region: string, service: string) {
42- // this.endpoint = endpoint;
43- // this.region = region;
44- // this.service = service;
45-
46- // }
45+ const cleanedHeaders = this . removeSigV4Headers ( headers ) ;
4746
48- // // if (oldHeaders) {
49- // // const request = new this.httpRequest({
50- // // method: 'POST',
51- // // protocol: 'https',
52- // // hostname: url.hostname,
53- // // path: url.pathname,
54- // // body: serializedSpans,
55- // // headers: {
56- // // ...this.removeSigV4Headers(oldHeaders),
57- // // host: url.hostname,
58- // // },
59- // // });
60-
61- // // try {
62- // // const signer = new this.signatureV4({
63- // // credentials: this.defaultProvider(),
64- // // region: this.region,
65- // // service: OTLPAwsSpanExporter.SERVICE_NAME,
66- // // sha256: this.sha256,
67- // // });
68-
69- // // const signedRequest = await signer.sign(request);
70-
71- // // // See type: https://github.com/open-telemetry/opentelemetry-js/blob/experimental/v0.57.1/experimental/packages/otlp-exporter-base/src/transport/http-transport-types.ts#L31
72- // // const newHeaders: () => Record<string, string> = () => signedRequest.headers;
73- // // this['_delegate']._transport._transport._parameters.headers = newHeaders;
74- // // } catch (exception) {
75- // // diag.debug(
76- // // `Failed to sign/authenticate the given exported Span request to OTLP XRay endpoint with error: ${exception}`
77- // // );
78- // // }
79- // // }
80- // }
47+ const request = new HttpRequest . httpRequest ( {
48+ method : 'POST' ,
49+ protocol : 'https' ,
50+ hostname : url . hostname ,
51+ path : url . pathname ,
52+ body : serializedData ,
53+ headers : {
54+ ...cleanedHeaders ,
55+ host : url . hostname ,
56+ } ,
57+ } ) ;
58+
59+ try {
60+ const signer = new SignatureV4 ( {
61+ credentials : defaultProvider ( ) ,
62+ region : this . region ,
63+ service : this . service ,
64+ sha256 : Sha256 ,
65+ } ) ;
66+
67+ const signedRequest = await signer . sign ( request ) ;
68+
69+ return signedRequest . headers ;
70+ } catch ( exception ) {
71+ diag . debug (
72+ `Failed to sign/authenticate the given exported Span request to OTLP XRay endpoint with error: ${ exception } `
73+ ) ;
74+ }
75+ }
76+
77+ return headers ;
78+ }
79+
80+ // Cleans up Sigv4 headers from headers to avoid accidentally copying them to the new headers
81+ private removeSigV4Headers ( headers : Record < string , string > ) {
82+ const newHeaders : Record < string , string > = { } ;
83+ const sigV4Headers = [ 'x-amz-date' , 'authorization' , 'x-amz-content-sha256' , 'x-amz-security-token' ] ;
84+
85+ for ( const key in headers ) {
86+ if ( ! sigV4Headers . includes ( key . toLowerCase ( ) ) ) {
87+ newHeaders [ key ] = headers [ key ] ;
88+ }
89+ }
90+ return newHeaders ;
91+ }
92+ }
0 commit comments