From b182cb6b04b20bcedf1a721ea5746dcde64a920a Mon Sep 17 00:00:00 2001 From: Gus Narea Date: Wed, 5 Apr 2023 02:34:34 +0900 Subject: [PATCH] test: Refactor functional tests (#32) --- README.md | 5 +-- src/functional_tests/aws.test.ts | 40 ++++++++++------------ src/functional_tests/gcp.test.ts | 59 +++++++++++++++----------------- src/functional_tests/gcpUtils.ts | 21 ------------ src/functional_tests/utils.ts | 22 ++++++++++++ 5 files changed, 71 insertions(+), 76 deletions(-) delete mode 100644 src/functional_tests/gcpUtils.ts create mode 100644 src/functional_tests/utils.ts diff --git a/README.md b/README.md index 13bad91..2911cb9 100644 --- a/README.md +++ b/README.md @@ -32,8 +32,9 @@ async function init(): Promise { The following environment variables must be defined depending on the adapter: - AWS adapter: - - `AWS_KMS_ENDPOINT` (optional). - - `AWS_KMS_REGION` (optional). + - [`AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/loading-node-credentials-environment.html) (optional when running on AWS infrastructure). + - `AWS_KMS_ENDPOINT` (optional when running on AWS infrastructure). + - `AWS_KMS_REGION` (optional when running on AWS infrastructure). - GCP adapter: - [`GOOGLE_APPLICATION_CREDENTIALS`](https://cloud.google.com/docs/authentication/getting-started) (optional when running on GCP infrastructure). - `GCP_KMS_KEYRING` (required). diff --git a/src/functional_tests/aws.test.ts b/src/functional_tests/aws.test.ts index 5023cc4..94d02cd 100644 --- a/src/functional_tests/aws.test.ts +++ b/src/functional_tests/aws.test.ts @@ -1,28 +1,24 @@ -import { KMSClient } from '@aws-sdk/client-kms'; +import { initKmsProviderFromEnv, KmsRsaPssProvider } from '../index'; +import { RSA_PSS_CREATION_ALGORITHM, RSA_PSS_SIGN_ALGORITHM } from '../testUtils/webcrypto'; +import { PLAINTEXT, verifyAsymmetricSignature } from './utils'; -import { AwsKmsRsaPssProvider } from '../lib/aws/AwsKmsRsaPssProvider'; -import { PLAINTEXT } from '../testUtils/stubs'; -import { - NODEJS_CRYPTO, - RSA_PSS_CREATION_ALGORITHM, - RSA_PSS_SIGN_ALGORITHM, -} from '../testUtils/webcrypto'; - -const CLIENT = new KMSClient({ - credentials: { accessKeyId: 'accessKeyId', secretAccessKey: 'secretAccessKey' }, - endpoint: 'http://localhost:8080', - region: 'eu-west-2', +let provider: KmsRsaPssProvider; +let keyPair: CryptoKeyPair; +beforeAll(async () => { + provider = await initKmsProviderFromEnv('AWS'); + keyPair = await provider.generateKey(RSA_PSS_CREATION_ALGORITHM, true, ['sign', 'verify']); +}); +afterAll(async () => { + if (keyPair) { + await provider?.destroyKey(keyPair.privateKey); + } + await provider?.close(); }); test('AWS KMS', async () => { - const provider = new AwsKmsRsaPssProvider(CLIENT); - const keyPair = (await provider.generateKey(RSA_PSS_CREATION_ALGORITHM, true, [ - 'sign', - 'verify', - ])) as CryptoKeyPair; - const signature = await provider.sign(RSA_PSS_SIGN_ALGORITHM, keyPair.privateKey, PLAINTEXT); + const { publicKey, privateKey } = keyPair; + + const signature = await provider.sign(RSA_PSS_SIGN_ALGORITHM, privateKey, PLAINTEXT); - await expect( - NODEJS_CRYPTO.subtle.verify(RSA_PSS_SIGN_ALGORITHM, keyPair.publicKey, signature, PLAINTEXT), - ).resolves.toBe(true); + await expect(verifyAsymmetricSignature(publicKey, signature, PLAINTEXT)).resolves.toBe(true); }); diff --git a/src/functional_tests/gcp.test.ts b/src/functional_tests/gcp.test.ts index 701b60d..d369ac4 100644 --- a/src/functional_tests/gcp.test.ts +++ b/src/functional_tests/gcp.test.ts @@ -1,55 +1,52 @@ -import { constants, createVerify } from 'crypto'; +import { KeyManagementServiceClient } from '@google-cloud/kms'; import { initKmsProviderFromEnv, KmsRsaPssProvider } from '../index'; -import { derPublicKeyToPem } from '../testUtils/asn1'; -import { createKeyRingIfMissing } from './gcpUtils'; -import { - derSerializePublicKey, - RSA_PSS_CREATION_ALGORITHM, - RSA_PSS_SIGN_ALGORITHM, -} from '../testUtils/webcrypto'; - -const PLAINTEXT = Buffer.from('this is the plaintext'); +import { PLAINTEXT, verifyAsymmetricSignature } from './utils'; +import { RSA_PSS_CREATION_ALGORITHM, RSA_PSS_SIGN_ALGORITHM } from '../testUtils/webcrypto'; if (!process.env.GOOGLE_APPLICATION_CREDENTIALS) { throw new Error('GOOGLE_APPLICATION_CREDENTIALS must be defined'); } -let gcpProvider: KmsRsaPssProvider; +let provider: KmsRsaPssProvider; let keyPair: CryptoKeyPair; beforeAll(async () => { - gcpProvider = await initKmsProviderFromEnv('GCP'); + provider = await initKmsProviderFromEnv('GCP'); await createKeyRingIfMissing(process.env.GCP_KMS_KEYRING!, process.env.GCP_KMS_LOCATION!); - keyPair = await gcpProvider.generateKey(RSA_PSS_CREATION_ALGORITHM, true, ['sign', 'verify']); + keyPair = await provider.generateKey(RSA_PSS_CREATION_ALGORITHM, true, ['sign', 'verify']); }); afterAll(async () => { if (keyPair) { - await gcpProvider?.destroyKey(keyPair.privateKey); + await provider?.destroyKey(keyPair.privateKey); } - await gcpProvider?.close(); + await provider?.close(); }); -test('Lifecycle', async () => { +test('GCP KMS', async () => { const { publicKey, privateKey } = keyPair; - const signature = await gcpProvider.sign(RSA_PSS_SIGN_ALGORITHM, privateKey, PLAINTEXT); + const signature = await provider.sign(RSA_PSS_SIGN_ALGORITHM, privateKey, PLAINTEXT); await expect(verifyAsymmetricSignature(publicKey, signature, PLAINTEXT)).resolves.toBe(true); }); -async function verifyAsymmetricSignature( - publicKey: CryptoKey, - signature: ArrayBuffer, - plaintext: Buffer, -): Promise { - const verify = createVerify('sha256'); - verify.update(plaintext); - verify.end(); - - const publicKeyDer = await derSerializePublicKey(publicKey); - return verify.verify( - { key: derPublicKeyToPem(publicKeyDer), padding: constants.RSA_PKCS1_PSS_PADDING }, - new Uint8Array(signature), - ); +export async function createKeyRingIfMissing(keyRingId: string, location: string): Promise { + const kmsClient = new KeyManagementServiceClient(); + const project = await kmsClient.getProjectId(); + const keyRingName = kmsClient.keyRingPath(project, location, keyRingId); + try { + await kmsClient.getKeyRing({ name: keyRingName }); + } catch (err) { + if ((err as any).code !== 5) { + throw err; + } + + // Key ring was not found + const locationPath = kmsClient.locationPath(project, location); + await kmsClient.createKeyRing({ parent: locationPath, keyRingId }); + } + + await kmsClient.close(); + return keyRingName; } diff --git a/src/functional_tests/gcpUtils.ts b/src/functional_tests/gcpUtils.ts deleted file mode 100644 index ea55172..0000000 --- a/src/functional_tests/gcpUtils.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { KeyManagementServiceClient } from '@google-cloud/kms'; - -export async function createKeyRingIfMissing(keyRingId: string, location: string): Promise { - const kmsClient = new KeyManagementServiceClient(); - const project = await kmsClient.getProjectId(); - const keyRingName = kmsClient.keyRingPath(project, location, keyRingId); - try { - await kmsClient.getKeyRing({ name: keyRingName }); - } catch (err) { - if ((err as any).code !== 5) { - throw err; - } - - // Key ring was not found - const locationPath = kmsClient.locationPath(project, location); - await kmsClient.createKeyRing({ parent: locationPath, keyRingId }); - } - - await kmsClient.close(); - return keyRingName; -} diff --git a/src/functional_tests/utils.ts b/src/functional_tests/utils.ts new file mode 100644 index 0000000..959a040 --- /dev/null +++ b/src/functional_tests/utils.ts @@ -0,0 +1,22 @@ +import { constants, createVerify } from 'crypto'; + +import { derSerializePublicKey } from '../testUtils/webcrypto'; +import { derPublicKeyToPem } from '../testUtils/asn1'; + +export const PLAINTEXT = Buffer.from('this is the plaintext'); + +export async function verifyAsymmetricSignature( + publicKey: CryptoKey, + signature: ArrayBuffer, + plaintext: Buffer, +): Promise { + const verify = createVerify('sha256'); + verify.update(plaintext); + verify.end(); + + const publicKeyDer = await derSerializePublicKey(publicKey); + return verify.verify( + { key: derPublicKeyToPem(publicKeyDer), padding: constants.RSA_PKCS1_PSS_PADDING }, + new Uint8Array(signature), + ); +}