-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
AWS SDK v3 support #13
Comments
I am also facing this issue |
I was able to hack one up in typescript for non-temporary access keys (no tokens) using only v3 APIs. Needs additional work, but might start as a base. /* eslint-disable max-classes-per-file */
import { Sha256 } from '@aws-crypto/sha256-js';
import { createScope, SignatureV4 } from '@smithy/signature-v4';
import { auth, Client as Cassandra } from 'cassandra-driver';
import { createHash } from 'crypto';
import fs from 'fs';
import _ from 'lodash';
class SigV4Authenticator implements auth.Authenticator {
private readonly region: string;
private readonly accessKeyId: string;
private readonly secretAccessKey: string;
public static readonly AWS4_SIGNING_ALGORITHM = 'AWS4-HMAC-SHA256';
constructor(props: { region: string; accessKeyId: string; secretAccessKey: string }) {
this.region = props.region;
this.accessKeyId = props.accessKeyId;
this.secretAccessKey = props.secretAccessKey;
}
/* Calling class expects to be a method, so cannot make static even though it is a static function */
/* eslint-disable-next-line class-methods-use-this */
initialResponse = (callback: (error: Error | null, buffer: Buffer | null) => void): void => {
callback(null, Buffer.from('SigV4\0\0', 'utf8'));
};
private static handleError =
(callback: (error: Error | null, buffer: Buffer | null) => void) =>
(err: unknown): void => {
callback(_.isError(err) ? err : new Error(JSON.stringify(err)), null);
};
private handleSignature =
(timestamp: string, callback: (error: Error | null, buffer: Buffer | null) => void) =>
(signature: string): void => {
const payload = `signature=${signature},access_key=${this.accessKeyId},amzdate=${timestamp}`;
callback(null, Buffer.from(payload, 'utf-8'));
};
evaluateChallenge = (challenge: Buffer, callback: (error: Error | null, buffer: Buffer | null) => void) => {
const res = challenge.toString().split('nonce=');
if (res.length < 2) {
callback(new Error(`could not parse nonce: ${challenge.toString()}`), null);
return;
}
const nonce = res[1].split(',')[0];
const timestamp = new Date().toISOString();
/* eslint-disable-next-line no-useless-escape */
const timestampDate = timestamp.replace(/[:\-]|\.\d{3}/g, '').slice(0, 8);
const nonceHash = Buffer.from(createHash('sha256').update(nonce, 'utf-8').digest()).toString('hex');
const scope = createScope(timestampDate, this.region, 'cassandra');
const headers = [
`X-Amz-Algorithm=${SigV4Authenticator.AWS4_SIGNING_ALGORITHM}`,
`X-Amz-Credential=${this.accessKeyId}%2F${encodeURIComponent(scope)}`,
`X-Amz-Date=${encodeURIComponent(timestamp)}`,
'X-Amz-Expires=900',
].sort();
const canonicalRequest = `PUT\n/authenticate\n${headers.join('&')}\nhost:cassandra\n\nhost\n${nonceHash}`;
const digest = Buffer.from(createHash('sha256').update(canonicalRequest, 'utf-8').digest()).toString('hex');
const stringToSign = `${SigV4Authenticator.AWS4_SIGNING_ALGORITHM}\n${timestamp}\n${scope}\n${digest}`;
const signer = new SignatureV4({
service: 'cassandra',
region: this.region,
credentials: {
accessKeyId: this.accessKeyId,
secretAccessKey: this.secretAccessKey,
},
sha256: Sha256,
});
signer
.sign(stringToSign)
.then(this.handleSignature(timestamp, callback))
.catch(SigV4Authenticator.handleError(callback));
};
/* Calling class expects to be a method, so cannot make static even though it is a static function */
/* eslint-disable-next-line class-methods-use-this */
onAuthenticationSuccess = (): void => {};
}
class SigV4AuthProvider implements auth.AuthProvider {
private readonly region: string;
private readonly accessKeyId: string;
private readonly secretAccessKey: string;
constructor(props: { region?: string; accessKeyId: string; secretAccessKey: string }) {
Object.setPrototypeOf(this, auth.PlainTextAuthProvider.prototype);
const region = props.region || process.env.AWS_REGION;
if (_.isNil(region)) throw new Error('no AWS region specified');
this.region = region;
this.accessKeyId = props.accessKeyId;
this.secretAccessKey = props.secretAccessKey;
}
newAuthenticator = (): auth.Authenticator =>
new SigV4Authenticator({
region: this.region,
accessKeyId: this.accessKeyId,
secretAccessKey: this.secretAccessKey,
});
}
const client = new Cassandra({
contactPoints: ['cassandra.us-east-1.amazonaws.com'],
localDataCenter: 'us-east-1',
authProvider: new SigV4AuthProvider({
region: 'us-east-1',
accessKeyId: '<REDACTED>',
secretAccessKey: '<REDACTED>',
}),
sslOptions: {
ca: [fs.readFileSync('/home/<REDACTED>/.cassandra/sf-class2-root.crt', 'utf-8')],
host: 'cassandra.us-east-1.amazonaws.com',
rejectUnauthorized: true,
},
protocolOptions: { port: 9142 },
});
const query = 'SELECT * FROM system_schema.keyspaces';
client.execute(query).then((result) => console.log('Row from Keyspaces:', result)); |
2024 and this issue is still open. |
is there any news about that? |
2025 no update at all, is it dead AWS? |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Any roadmap to migrate to AWS SDK V3?
The text was updated successfully, but these errors were encountered: