From 5278a8e62c14fcc5cc02e4bd7b36e68a4ed48b72 Mon Sep 17 00:00:00 2001 From: Seth Vargo Date: Mon, 16 Aug 2021 11:25:27 -0400 Subject: [PATCH] feat(kms): add samples for new rng and hmac kms apis (#487) --- samples/createKeyAsymmetricDecrypt.js | 16 +++- samples/createKeyAsymmetricSign.js | 16 +++- samples/createKeyHsm.js | 16 +++- samples/createKeyLabels.js | 12 ++- samples/createKeyMac.js | 76 +++++++++++++++++ samples/createKeyRing.js | 12 ++- samples/createKeyRotationSchedule.js | 12 ++- samples/createKeySymmetricEncryptDecrypt.js | 12 ++- samples/createKeyVersion.js | 12 ++- samples/decryptAsymmetric.js | 12 ++- samples/decryptSymmetric.js | 12 ++- samples/destroyKeyVersion.js | 12 ++- samples/disableKeyVersion.js | 12 ++- samples/enableKeyVersion.js | 12 ++- samples/encryptAsymmetric.js | 12 ++- samples/encryptSymmetric.js | 12 ++- samples/generateRandomBytes.js | 65 ++++++++++++++ samples/getKeyLabels.js | 12 ++- samples/getKeyVersionAttestation.js | 12 ++- samples/getPublicKey.js | 12 ++- samples/iamAddMember.js | 12 ++- samples/iamGetPolicy.js | 12 ++- samples/iamRemoveMember.js | 12 ++- samples/quickstart.js | 12 ++- samples/restoreKeyVersion.js | 12 ++- samples/signAsymmetric.js | 12 ++- samples/signMac.js | 82 ++++++++++++++++++ samples/test/kms.test.js | 95 +++++++++++++++++++++ samples/updateKeyAddRotation.js | 12 ++- samples/updateKeyRemoveLabels.js | 12 ++- samples/updateKeyRemoveRotation.js | 12 ++- samples/updateKeySetPrimary.js | 12 ++- samples/updateKeyUpdateLabels.js | 12 ++- samples/verifyAsymmetricEc.js | 12 ++- samples/verifyAsymmetricRsa.js | 12 ++- samples/verifyMac.js | 80 +++++++++++++++++ 36 files changed, 689 insertions(+), 93 deletions(-) create mode 100644 samples/createKeyMac.js create mode 100644 samples/generateRandomBytes.js create mode 100644 samples/signMac.js create mode 100644 samples/verifyMac.js diff --git a/samples/createKeyAsymmetricDecrypt.js b/samples/createKeyAsymmetricDecrypt.js index 6bfaee05..e688fdbe 100644 --- a/samples/createKeyAsymmetricDecrypt.js +++ b/samples/createKeyAsymmetricDecrypt.js @@ -47,6 +47,10 @@ async function main( versionTemplate: { algorithm: 'RSA_DECRYPT_OAEP_2048_SHA256', }, + + // Optional: customize how long key versions should be kept before + // destroying. + destroyScheduledDuration: {seconds: 60 * 60 * 24}, }, }); @@ -59,8 +63,14 @@ async function main( } module.exports.main = main; -/* c8 ignore next 4 */ +/* c8 ignore next 10 */ if (require.main === module) { - const args = process.argv.slice(2); - main(...args).catch(console.error); + main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; + }); + process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; + }); } diff --git a/samples/createKeyAsymmetricSign.js b/samples/createKeyAsymmetricSign.js index 9d0314dc..73a99898 100644 --- a/samples/createKeyAsymmetricSign.js +++ b/samples/createKeyAsymmetricSign.js @@ -47,6 +47,10 @@ async function main( versionTemplate: { algorithm: 'RSA_SIGN_PKCS1_2048_SHA256', }, + + // Optional: customize how long key versions should be kept before + // destroying. + destroyScheduledDuration: {seconds: 60 * 60 * 24}, }, }); @@ -59,8 +63,14 @@ async function main( } module.exports.main = main; -/* c8 ignore next 4 */ +/* c8 ignore next 10 */ if (require.main === module) { - const args = process.argv.slice(2); - main(...args).catch(console.error); + main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; + }); + process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; + }); } diff --git a/samples/createKeyHsm.js b/samples/createKeyHsm.js index 5ccdc947..9592c3e7 100644 --- a/samples/createKeyHsm.js +++ b/samples/createKeyHsm.js @@ -48,6 +48,10 @@ async function main( algorithm: 'GOOGLE_SYMMETRIC_ENCRYPTION', protectionLevel: 'HSM', }, + + // Optional: customize how long key versions should be kept before + // destroying. + destroyScheduledDuration: {seconds: 60 * 60 * 24}, }, }); @@ -60,8 +64,14 @@ async function main( } module.exports.main = main; -/* c8 ignore next 4 */ +/* c8 ignore next 10 */ if (require.main === module) { - const args = process.argv.slice(2); - main(...args).catch(console.error); + main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; + }); + process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; + }); } diff --git a/samples/createKeyLabels.js b/samples/createKeyLabels.js index 71460cf5..412eca44 100644 --- a/samples/createKeyLabels.js +++ b/samples/createKeyLabels.js @@ -63,8 +63,14 @@ async function main( } module.exports.main = main; -/* c8 ignore next 4 */ +/* c8 ignore next 10 */ if (require.main === module) { - const args = process.argv.slice(2); - main(...args).catch(console.error); + main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; + }); + process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; + }); } diff --git a/samples/createKeyMac.js b/samples/createKeyMac.js new file mode 100644 index 00000000..ce117b2b --- /dev/null +++ b/samples/createKeyMac.js @@ -0,0 +1,76 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +async function main( + projectId = 'my-project', + locationId = 'us-east1', + keyRingId = 'my-key-ring', + id = 'my-mac-key' +) { + // [START kms_create_key_mac] + // + // TODO(developer): Uncomment these variables before running the sample. + // + // const projectId = 'my-project'; + // const locationId = 'us-east1'; + // const keyRingId = 'my-key-ring'; + // const id = 'my-mac-key'; + + // Imports the Cloud KMS library + const {KeyManagementServiceClient} = require('@google-cloud/kms'); + + // Instantiates a client + const client = new KeyManagementServiceClient(); + + // Build the parent key ring name + const keyRingName = client.keyRingPath(projectId, locationId, keyRingId); + + async function createKeyMac() { + const [key] = await client.createCryptoKey({ + parent: keyRingName, + cryptoKeyId: id, + cryptoKey: { + purpose: 'MAC', + versionTemplate: { + algorithm: 'HMAC_SHA256', + }, + + // Optional: customize how long key versions should be kept before + // destroying. + destroyScheduledDuration: {seconds: 60 * 60 * 24}, + }, + }); + + console.log(`Created mac key: ${key.name}`); + return key; + } + + return createKeyMac(); + // [END kms_create_key_mac] +} +module.exports.main = main; + +/* c8 ignore next 10 */ +if (require.main === module) { + main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; + }); + process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; + }); +} diff --git a/samples/createKeyRing.js b/samples/createKeyRing.js index 90820afa..36b2110f 100644 --- a/samples/createKeyRing.js +++ b/samples/createKeyRing.js @@ -51,8 +51,14 @@ async function main( } module.exports.main = main; -/* c8 ignore next 4 */ +/* c8 ignore next 10 */ if (require.main === module) { - const args = process.argv.slice(2); - main(...args).catch(console.error); + main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; + }); + process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; + }); } diff --git a/samples/createKeyRotationSchedule.js b/samples/createKeyRotationSchedule.js index 93d0d04c..23f3d5fe 100644 --- a/samples/createKeyRotationSchedule.js +++ b/samples/createKeyRotationSchedule.js @@ -69,8 +69,14 @@ async function main( } module.exports.main = main; -/* c8 ignore next 4 */ +/* c8 ignore next 10 */ if (require.main === module) { - const args = process.argv.slice(2); - main(...args).catch(console.error); + main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; + }); + process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; + }); } diff --git a/samples/createKeySymmetricEncryptDecrypt.js b/samples/createKeySymmetricEncryptDecrypt.js index 6f1ab1df..e4677347 100644 --- a/samples/createKeySymmetricEncryptDecrypt.js +++ b/samples/createKeySymmetricEncryptDecrypt.js @@ -59,8 +59,14 @@ async function main( } module.exports.main = main; -/* c8 ignore next 4 */ +/* c8 ignore next 10 */ if (require.main === module) { - const args = process.argv.slice(2); - main(...args).catch(console.error); + main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; + }); + process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; + }); } diff --git a/samples/createKeyVersion.js b/samples/createKeyVersion.js index 03747cb7..5230f763 100644 --- a/samples/createKeyVersion.js +++ b/samples/createKeyVersion.js @@ -52,8 +52,14 @@ async function main( } module.exports.main = main; -/* c8 ignore next 4 */ +/* c8 ignore next 10 */ if (require.main === module) { - const args = process.argv.slice(2); - main(...args).catch(console.error); + main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; + }); + process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; + }); } diff --git a/samples/decryptAsymmetric.js b/samples/decryptAsymmetric.js index ba962813..d7bf5134 100644 --- a/samples/decryptAsymmetric.js +++ b/samples/decryptAsymmetric.js @@ -89,8 +89,14 @@ async function main( } module.exports.main = main; -/* c8 ignore next 4 */ +/* c8 ignore next 10 */ if (require.main === module) { - const args = process.argv.slice(2); - main(...args).catch(console.error); + main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; + }); + process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; + }); } diff --git a/samples/decryptSymmetric.js b/samples/decryptSymmetric.js index 0401ed03..0291717a 100644 --- a/samples/decryptSymmetric.js +++ b/samples/decryptSymmetric.js @@ -75,8 +75,14 @@ async function main( } module.exports.main = main; -/* c8 ignore next 4 */ +/* c8 ignore next 10 */ if (require.main === module) { - const args = process.argv.slice(2); - main(...args).catch(console.error); + main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; + }); + process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; + }); } diff --git a/samples/destroyKeyVersion.js b/samples/destroyKeyVersion.js index b5511cc2..0a657132 100644 --- a/samples/destroyKeyVersion.js +++ b/samples/destroyKeyVersion.js @@ -60,8 +60,14 @@ async function main( } module.exports.main = main; -/* c8 ignore next 4 */ +/* c8 ignore next 10 */ if (require.main === module) { - const args = process.argv.slice(2); - main(...args).catch(console.error); + main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; + }); + process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; + }); } diff --git a/samples/disableKeyVersion.js b/samples/disableKeyVersion.js index 976094c6..a16db8e2 100644 --- a/samples/disableKeyVersion.js +++ b/samples/disableKeyVersion.js @@ -66,8 +66,14 @@ async function main( } module.exports.main = main; -/* c8 ignore next 4 */ +/* c8 ignore next 10 */ if (require.main === module) { - const args = process.argv.slice(2); - main(...args).catch(console.error); + main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; + }); + process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; + }); } diff --git a/samples/enableKeyVersion.js b/samples/enableKeyVersion.js index d73ade3e..dec512b3 100644 --- a/samples/enableKeyVersion.js +++ b/samples/enableKeyVersion.js @@ -66,8 +66,14 @@ async function main( } module.exports.main = main; -/* c8 ignore next 4 */ +/* c8 ignore next 10 */ if (require.main === module) { - const args = process.argv.slice(2); - main(...args).catch(console.error); + main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; + }); + process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; + }); } diff --git a/samples/encryptAsymmetric.js b/samples/encryptAsymmetric.js index 45fd2c5d..bea1311c 100644 --- a/samples/encryptAsymmetric.js +++ b/samples/encryptAsymmetric.js @@ -93,8 +93,14 @@ async function main( } module.exports.main = main; -/* c8 ignore next 4 */ +/* c8 ignore next 10 */ if (require.main === module) { - const args = process.argv.slice(2); - main(...args).catch(console.error); + main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; + }); + process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; + }); } diff --git a/samples/encryptSymmetric.js b/samples/encryptSymmetric.js index 9158b04b..283492b1 100644 --- a/samples/encryptSymmetric.js +++ b/samples/encryptSymmetric.js @@ -77,8 +77,14 @@ async function main( } module.exports.main = main; -/* c8 ignore next 4 */ +/* c8 ignore next 10 */ if (require.main === module) { - const args = process.argv.slice(2); - main(...args).catch(console.error); + main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; + }); + process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; + }); } diff --git a/samples/generateRandomBytes.js b/samples/generateRandomBytes.js new file mode 100644 index 00000000..6f0dc17f --- /dev/null +++ b/samples/generateRandomBytes.js @@ -0,0 +1,65 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +async function main( + projectId = 'my-project', + locationId = 'us-east1', + numBytes = 256 +) { + // [START kms_generate_random_bytes] + // + // TODO(developer): Uncomment these variables before running the sample. + // + // const projectId = 'my-project'; + // const locationId = 'us-east1'; + // const numBytes = 256; + + // Imports the Cloud KMS library + const {KeyManagementServiceClient} = require('@google-cloud/kms'); + + // Instantiates a client + const client = new KeyManagementServiceClient(); + + // Build the location name + const locationName = client.locationPath(projectId, locationId); + + async function generateRandomBytes() { + const [randomBytesResponse] = await client.generateRandomBytes({ + location: locationName, + lengthBytes: numBytes, + protectionLevel: 'HSM', + }); + + console.log(`Random bytes: ${randomBytesResponse.data.toString('base64')}`); + return randomBytesResponse; + } + + return generateRandomBytes(); + // [END kms_generate_random_bytes] +} +module.exports.main = main; + +/* c8 ignore next 10 */ +if (require.main === module) { + main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; + }); + process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; + }); +} diff --git a/samples/getKeyLabels.js b/samples/getKeyLabels.js index 728b124e..bee79d48 100644 --- a/samples/getKeyLabels.js +++ b/samples/getKeyLabels.js @@ -55,8 +55,14 @@ async function main( } module.exports.main = main; -/* c8 ignore next 4 */ +/* c8 ignore next 10 */ if (require.main === module) { - const args = process.argv.slice(2); - main(...args).catch(console.error); + main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; + }); + process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; + }); } diff --git a/samples/getKeyVersionAttestation.js b/samples/getKeyVersionAttestation.js index dbd621e6..4674873e 100644 --- a/samples/getKeyVersionAttestation.js +++ b/samples/getKeyVersionAttestation.js @@ -67,8 +67,14 @@ async function main( } module.exports.main = main; -/* c8 ignore next 4 */ +/* c8 ignore next 10 */ if (require.main === module) { - const args = process.argv.slice(2); - main(...args).catch(console.error); + main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; + }); + process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; + }); } diff --git a/samples/getPublicKey.js b/samples/getPublicKey.js index d70a337d..f47a9f78 100644 --- a/samples/getPublicKey.js +++ b/samples/getPublicKey.js @@ -71,8 +71,14 @@ async function main( } module.exports.main = main; -/* c8 ignore next 4 */ +/* c8 ignore next 10 */ if (require.main === module) { - const args = process.argv.slice(2); - main(...args).catch(console.error); + main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; + }); + process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; + }); } diff --git a/samples/iamAddMember.js b/samples/iamAddMember.js index 4010167c..7ab63acd 100644 --- a/samples/iamAddMember.js +++ b/samples/iamAddMember.js @@ -75,8 +75,14 @@ async function main( } module.exports.main = main; -/* c8 ignore next 4 */ +/* c8 ignore next 10 */ if (require.main === module) { - const args = process.argv.slice(2); - main(...args).catch(console.error); + main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; + }); + process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; + }); } diff --git a/samples/iamGetPolicy.js b/samples/iamGetPolicy.js index c28bd3e2..bccabc80 100644 --- a/samples/iamGetPolicy.js +++ b/samples/iamGetPolicy.js @@ -67,8 +67,14 @@ async function main( } module.exports.main = main; -/* c8 ignore next 4 */ +/* c8 ignore next 10 */ if (require.main === module) { - const args = process.argv.slice(2); - main(...args).catch(console.error); + main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; + }); + process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; + }); } diff --git a/samples/iamRemoveMember.js b/samples/iamRemoveMember.js index b920ef79..2f6f2cd9 100644 --- a/samples/iamRemoveMember.js +++ b/samples/iamRemoveMember.js @@ -82,8 +82,14 @@ async function main( } module.exports.main = main; -/* c8 ignore next 4 */ +/* c8 ignore next 10 */ if (require.main === module) { - const args = process.argv.slice(2); - main(...args).catch(console.error); + main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; + }); + process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; + }); } diff --git a/samples/quickstart.js b/samples/quickstart.js index 503a8dcd..9253bd22 100644 --- a/samples/quickstart.js +++ b/samples/quickstart.js @@ -48,8 +48,14 @@ async function main(projectId = 'my-project', locationId = 'us-east1') { } module.exports.main = main; -/* c8 ignore next 4 */ +/* c8 ignore next 10 */ if (require.main === module) { - const args = process.argv.slice(2); - main(...args).catch(console.error); + main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; + }); + process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; + }); } diff --git a/samples/restoreKeyVersion.js b/samples/restoreKeyVersion.js index e2121f6d..f4366a0d 100644 --- a/samples/restoreKeyVersion.js +++ b/samples/restoreKeyVersion.js @@ -60,8 +60,14 @@ async function main( } module.exports.main = main; -/* c8 ignore next 4 */ +/* c8 ignore next 10 */ if (require.main === module) { - const args = process.argv.slice(2); - main(...args).catch(console.error); + main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; + }); + process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; + }); } diff --git a/samples/signAsymmetric.js b/samples/signAsymmetric.js index 08b40d9d..3b6dd0aa 100644 --- a/samples/signAsymmetric.js +++ b/samples/signAsymmetric.js @@ -101,8 +101,14 @@ async function main( } module.exports.main = main; -/* c8 ignore next 4 */ +/* c8 ignore next 10 */ if (require.main === module) { - const args = process.argv.slice(2); - main(...args).catch(console.error); + main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; + }); + process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; + }); } diff --git a/samples/signMac.js b/samples/signMac.js new file mode 100644 index 00000000..69a800b8 --- /dev/null +++ b/samples/signMac.js @@ -0,0 +1,82 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +async function main( + projectId = 'your-project-id', + locationId = 'us-east1', + keyRingId = 'my-key-ring', + keyId = 'my-key', + versionId = '123', + data = Buffer.from('...') +) { + // [START kms_sign_mac] + // + // TODO(developer): Uncomment these variables before running the sample. + // + // const projectId = 'your-project-id'; + // const locationId = 'us-east1'; + // const keyRingId = 'my-key-ring'; + // const keyId = 'my-key'; + // const versionId = '123'; + // const data = Buffer.from('...'); + + // Imports the Cloud KMS library + const {KeyManagementServiceClient} = require('@google-cloud/kms'); + + // Instantiates a client + const client = new KeyManagementServiceClient(); + + // Build the version name + const versionName = client.cryptoKeyVersionPath( + projectId, + locationId, + keyRingId, + keyId, + versionId + ); + + async function signMac() { + // Sign the data with Cloud KMS + const [signResponse] = await client.macSign({ + name: versionName, + data: data, + }); + + // Example of how to display signature. Because the signature is in a binary + // format, you need to encode the output before printing it to a console or + // displaying it on a screen. + const encoded = signResponse.mac.toString('base64'); + console.log(`Signature: ${encoded}`); + + return signResponse; + } + + return signMac(); + // [END kms_sign_mac] +} +module.exports.main = main; + +/* c8 ignore next 10 */ +if (require.main === module) { + main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; + }); + process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; + }); +} diff --git a/samples/test/kms.test.js b/samples/test/kms.test.js index 5bda07cc..57eeb776 100644 --- a/samples/test/kms.test.js +++ b/samples/test/kms.test.js @@ -30,6 +30,7 @@ const asymmetricSignEcKeyId = v4(); const asymmetricSignRsaKeyId = v4(); const hsmKeyId = v4(); const symmetricKeyId = v4(); +const hmacKeyId = v4(); const nodeMajorVersion = parseInt(process.version.match(/v?(\d+).*/)[1]); @@ -181,6 +182,31 @@ describe('Cloud KMS samples', () => { ), 'ENABLED' ); + + await client.createCryptoKey({ + parent: client.keyRingPath(projectId, locationId, keyRingId), + cryptoKeyId: hmacKeyId, + cryptoKey: { + purpose: 'MAC', + versionTemplate: { + algorithm: 'HMAC_SHA256', + }, + labels: { + foo: 'bar', + zip: 'zap', + }, + }, + }); + await waitForState( + client.cryptoKeyVersionPath( + projectId, + locationId, + keyRingId, + hmacKeyId, + 1 + ), + 'ENABLED' + ); }); beforeEach(async () => { @@ -255,6 +281,13 @@ describe('Cloud KMS samples', () => { assert.equal(key.labels.cost_center, 'cc1234'); }); + it('creates mac keys', async () => { + const sample = require('../createKeyMac'); + const key = await sample.main(projectId, locationId, keyRingId, v4()); + assert.equal(key.purpose, 'MAC'); + assert.equal(key.versionTemplate.algorithm, 'HMAC_SHA256'); + }); + it('creates key rings', async () => { const sample = require('../createKeyRing'); const keyRing = await sample.main(projectId, locationId, v4()); @@ -452,6 +485,12 @@ describe('Cloud KMS samples', () => { assert.equal(decryptResponse.plaintext.toString('utf8'), plaintext); }); + it('generates random bytes', async () => { + const sample = require('../generateRandomBytes'); + const result = await sample.main(projectId, locationId, 256); + assert.equal(result.data.length, 256); + }); + it('gets keys with labels', async () => { const sample = require('../getKeyLabels'); const key = await sample.main( @@ -626,6 +665,34 @@ describe('Cloud KMS samples', () => { assert.isTrue(verified); }); + it('signs with mac keys', async () => { + const data = 'my data'; + + const sample = require('../signMac'); + const result = await sample.main( + projectId, + locationId, + keyRingId, + hmacKeyId, + 1, + Buffer.from(data) + ); + + const [verifyResponse] = await client.macVerify({ + name: client.cryptoKeyVersionPath( + projectId, + locationId, + keyRingId, + hmacKeyId, + 1 + ), + data: Buffer.from(data), + mac: result.mac, + }); + + assert.isTrue(verifyResponse.success); + }); + it('adds rotation schedules', async () => { const sample = require('../updateKeyAddRotation'); const key = await sample.main( @@ -757,4 +824,32 @@ describe('Cloud KMS samples', () => { assert.isTrue(verified); }); + + it('verifies with mac keys', async () => { + const data = 'my data'; + + const [signResponse] = await client.macSign({ + name: client.cryptoKeyVersionPath( + projectId, + locationId, + keyRingId, + hmacKeyId, + 1 + ), + data: Buffer.from(data), + }); + + const sample = require('../verifyMac'); + const result = await sample.main( + projectId, + locationId, + keyRingId, + hmacKeyId, + 1, + Buffer.from(data), + signResponse.mac + ); + + assert.isTrue(result.success); + }); }); diff --git a/samples/updateKeyAddRotation.js b/samples/updateKeyAddRotation.js index d00bca8d..634675bc 100644 --- a/samples/updateKeyAddRotation.js +++ b/samples/updateKeyAddRotation.js @@ -68,8 +68,14 @@ async function main( } module.exports.main = main; -/* c8 ignore next 4 */ +/* c8 ignore next 10 */ if (require.main === module) { - const args = process.argv.slice(2); - main(...args).catch(console.error); + main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; + }); + process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; + }); } diff --git a/samples/updateKeyRemoveLabels.js b/samples/updateKeyRemoveLabels.js index 6981ea13..bef2b533 100644 --- a/samples/updateKeyRemoveLabels.js +++ b/samples/updateKeyRemoveLabels.js @@ -59,8 +59,14 @@ async function main( } module.exports.main = main; -/* c8 ignore next 4 */ +/* c8 ignore next 10 */ if (require.main === module) { - const args = process.argv.slice(2); - main(...args).catch(console.error); + main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; + }); + process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; + }); } diff --git a/samples/updateKeyRemoveRotation.js b/samples/updateKeyRemoveRotation.js index fcd5ae82..2e355f06 100644 --- a/samples/updateKeyRemoveRotation.js +++ b/samples/updateKeyRemoveRotation.js @@ -59,8 +59,14 @@ async function main( } module.exports.main = main; -/* c8 ignore next 4 */ +/* c8 ignore next 10 */ if (require.main === module) { - const args = process.argv.slice(2); - main(...args).catch(console.error); + main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; + }); + process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; + }); } diff --git a/samples/updateKeySetPrimary.js b/samples/updateKeySetPrimary.js index 5da1768d..046de0b2 100644 --- a/samples/updateKeySetPrimary.js +++ b/samples/updateKeySetPrimary.js @@ -55,8 +55,14 @@ async function main( } module.exports.main = main; -/* c8 ignore next 4 */ +/* c8 ignore next 10 */ if (require.main === module) { - const args = process.argv.slice(2); - main(...args).catch(console.error); + main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; + }); + process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; + }); } diff --git a/samples/updateKeyUpdateLabels.js b/samples/updateKeyUpdateLabels.js index 2325994d..d23ef895 100644 --- a/samples/updateKeyUpdateLabels.js +++ b/samples/updateKeyUpdateLabels.js @@ -61,8 +61,14 @@ async function main( } module.exports.main = main; -/* c8 ignore next 4 */ +/* c8 ignore next 10 */ if (require.main === module) { - const args = process.argv.slice(2); - main(...args).catch(console.error); + main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; + }); + process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; + }); } diff --git a/samples/verifyAsymmetricEc.js b/samples/verifyAsymmetricEc.js index 71b6b1ae..ce0c3997 100644 --- a/samples/verifyAsymmetricEc.js +++ b/samples/verifyAsymmetricEc.js @@ -77,8 +77,14 @@ async function main( } module.exports.main = main; -/* c8 ignore next 4 */ +/* c8 ignore next 10 */ if (require.main === module) { - const args = process.argv.slice(2); - main(...args).catch(console.error); + main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; + }); + process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; + }); } diff --git a/samples/verifyAsymmetricRsa.js b/samples/verifyAsymmetricRsa.js index 7fef55e9..d380355c 100644 --- a/samples/verifyAsymmetricRsa.js +++ b/samples/verifyAsymmetricRsa.js @@ -78,8 +78,14 @@ async function main( } module.exports.main = main; -/* c8 ignore next 4 */ +/* c8 ignore next 10 */ if (require.main === module) { - const args = process.argv.slice(2); - main(...args).catch(console.error); + main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; + }); + process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; + }); } diff --git a/samples/verifyMac.js b/samples/verifyMac.js new file mode 100644 index 00000000..fa880d49 --- /dev/null +++ b/samples/verifyMac.js @@ -0,0 +1,80 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +async function main( + projectId = 'your-project-id', + locationId = 'us-east1', + keyRingId = 'my-key-ring', + keyId = 'my-key', + versionId = '123', + data = Buffer.from('...'), + signature = Buffer.from('...') +) { + // [START kms_verify_mac] + // + // TODO(developer): Uncomment these variables before running the sample. + // + // const projectId = 'your-project-id'; + // const locationId = 'us-east1'; + // const keyRingId = 'my-key-ring'; + // const keyId = 'my-key'; + // const versionId = '123'; + // const data = Buffer.from('...'); + // const signature = Buffer.from('...'); + + // Imports the Cloud KMS library + const {KeyManagementServiceClient} = require('@google-cloud/kms'); + + // Instantiates a client + const client = new KeyManagementServiceClient(); + + // Build the version name + const versionName = client.cryptoKeyVersionPath( + projectId, + locationId, + keyRingId, + keyId, + versionId + ); + + async function verifyMac() { + // Verify the data with Cloud KMS + const [verifyResponse] = await client.macVerify({ + name: versionName, + data: data, + mac: signature, + }); + + console.log(`Verified: ${verifyResponse.success}`); + return verifyResponse; + } + + return verifyMac(); + // [END kms_verify_mac] +} +module.exports.main = main; + +/* c8 ignore next 10 */ +if (require.main === module) { + main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; + }); + process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; + }); +}