From 61ea80e21cd405497d6179308d4f38469cd44fce Mon Sep 17 00:00:00 2001 From: Larry Osterman Date: Wed, 28 Jul 2021 10:48:33 -0700 Subject: [PATCH 1/8] Prepare for GA release --- sdk/attestation/attestation/CHANGELOG.md | 2 +- sdk/attestation/attestation/README.md | 57 +++++++++++--------- sdk/attestation/attestation/package.json | 2 +- sdk/attestation/attestation/src/constants.ts | 2 +- 4 files changed, 34 insertions(+), 29 deletions(-) diff --git a/sdk/attestation/attestation/CHANGELOG.md b/sdk/attestation/attestation/CHANGELOG.md index 6ced7a40f9b6..66a33fc2d8cd 100644 --- a/sdk/attestation/attestation/CHANGELOG.md +++ b/sdk/attestation/attestation/CHANGELOG.md @@ -1,6 +1,6 @@ # Release History -## 1.0.0-beta.5 (Unreleased) +## 1.0.0 (2021-08-10) ### Features Added diff --git a/sdk/attestation/attestation/README.md b/sdk/attestation/attestation/README.md index a44155e31f36..fd355676c6c6 100644 --- a/sdk/attestation/attestation/README.md +++ b/sdk/attestation/attestation/README.md @@ -43,8 +43,9 @@ npm install @azure/attestation ### Authenticate the client -In order to interact with the Microsoft Azure Attestation service, you'll need to create an instance of the [Attestation Client][attestation_client] or [Attestation Administration Client][attestation_admin_client] class. You need a **attestation instance url**, which you may see as "DNS Name" in the portal, -and **client secret credentials (client id, client secret, tenant id)** to instantiate a client object. +In order to interact with the Microsoft Azure Attestation service, you'll need to create an instance of the [Attestation Client][attestation_client] or [Attestation Administration Client][attestation_admin_client] class. You need a **attestation instance url**, which will either be the "Attest URI" +shown in the portal, or will be one of the shared attestation providers. +You will also need client credentials to use the Attestation Administration Client or call the `attestTpm` API. Client credentials require **(client id, client secret, tenant id)** to instantiate a client object. In this getting started section, we'll be authenticating using client secret credentials through the [DefaultAzureCredential][defaultazurecredential] provider, but we offer more authentication mechanisms through the [@azure/identity][azure_identity] package. To install the @azure/identity package: @@ -109,7 +110,7 @@ The Microsoft Azure Attestation service runs in two separate modes: "Isolated" a provide additional information beyond their authentication credentials to verify that they are authorized to modify the state of an attestation instance. Finally, each region in which the Microsoft Azure Attestation service is available supports a "shared" instance, which -can be used to attest SGX enclaves which only need verification against the azure baseline (there are no policies applied to the shared instance). TPM attestation is not available in the shared instance. +can be used to attest SGX enclaves which only need verification against the azure baseline (there are no policies applied to the shared provider). TPM attestation is not available in the shared provider. While the shared instance requires AAD authentication, it does not have any RBAC policies - any customer with a valid AAD bearer token can attest using the shared instance. ### Attestation @@ -187,9 +188,8 @@ const client = new AttestationClient(endpoint, {credentials: credentials}); const attestationSigners = await client.getAttestationSigners(); ``` -If your `endpoint` is one of the shared attestation endpoints, then you do not need -to provide credentials to access the endpoint. So a shared client can be created -with: +If you are not calling the `attestTpm` API, you do not need to provide credentials +to access the attestation client. This means a client can be created simply with: ```ts const client = new AttestationClient(endpoint); @@ -250,8 +250,8 @@ const client = new AttestationAdministrationClient(endpoint, new DefaultAzureCre const newPolicy = ``; // Set the new attestation policy. Set the policy as an secured policy. -const privateKey = -const certificate = +const privateKey = +const certificate = const setPolicyResult = await client.setPolicy( KnownAttestationType.OpenEnclave, @@ -263,13 +263,11 @@ const setPolicyResult = await client.setPolicy( ); ``` -Under the covers, the setPolicy APIs create a [JSON Web Token][json_web_token] based on the policy document and signing information which is sent to the attestation service. +Under the covers, the setPolicy APIs create a [JSON Web Token][json_web_token] containing on the policy document `certificate` and signed with the `privateKey` which is then sent to the attestation service. -Clients need to be able to verify that the attestation policy document was not modified before the policy document was received by the attestation service's enclave. +If a client wishes to ensure that the attestation policy document was not modified before the policy document was received by the attestation service's enclave, they can use the properties returned in the [PolicyResult][attestation_policy_result] objct which can be used to verify that the service received the policy document: -There are two properties provided in the [PolicyResult][attestation_policy_result] that can be used to verify that the service received the policy document: - -- [`policySigner`][attestation_policy_result_parameters] - if the `setPolicy` call included a signing certificate, this will be the certificate provided at the time of the `setPolicy` call. If no policy signer was set, this will be null. +- [`policySigner`][attestation_policy_result_parameters] - if the `setPolicy` call included a `certificate`, this value will be the certificate provided at the time of the `setPolicy` call. If no policy signer was set, this will be null. - [`policyTokenHash`][attestation_policy_result_parameters] - this is the hash of the [JSON Web Signature][json_web_token] sent to the service for the setPolicy API. To verify the hash, clients can create an attestation policy token (a helper class which represents the token used to set the attestation policy) and verify the hash generated from that token: @@ -281,16 +279,14 @@ const expectedPolicy = createAttestationPolicyToken( certificate); // Use your favorite SHA256 hash generator function to create a hash of the -// stringized JWS. The code in this package uses `KJUR.crypto.Util.hashString(buffer, "sha256")` -// from the `jsrsasign` library, but any crypto library will -// work. +// stringized JWS. const expectedHash = generateSha256Hash(expectedPolicy.serialize()); -// The hash returned in expectedHash will match the value in +// The hash returned in expectedHash should match the value in // `setResult.body.policyTokenHash`. ``` -### Attest SGX Enclave +### Attest SGX and Open Enclave Use the [`attestSgxEnclave`][attest_sgx] method to attest an SGX enclave. @@ -308,10 +304,10 @@ The client can then send that Attestation Token (which contains the serialized k This example shows one common pattern of calling into the attestation service to retrieve an attestation token associated with a request. -This example assumes that you have an existing `AttestationClient` object which is configured with the base URI for your endpoint. It also assumes that you have an SGX Quote (`quote`) generated from within the SGX enclave you are attesting, and "Runtime Data" (`binaryRuntimeData`) which is referenced in the SGX Quote. +This example assumes that you have an existing `AttestationClient` object which is configured with the Attest URI for your endpoint. It also assumes that you have an OpenEnclave report (`report`) generated from within the SGX enclave you are attesting, and "Runtime Data" (`binaryRuntimeData`) which is referenced in the SGX Quote. ```ts -const attestationResult = await client.attestOpenEnclave(quote, { +const attestationResult = await client.attestOpenEnclave(report, { runTimeData: binaryRuntimeData }); ``` @@ -321,16 +317,27 @@ intended to be interpreted as JSON data. In that case, the client should specify the attest API call: ```ts -const attestationResult = await client.attestOpenEnclave(quote, { +const attestationResult = await client.attestOpenEnclave(report, { runTimeJson: binaryRuntimeData }); ``` +Similarly, if you are using the Intel SDK to generate a "quote", you can validate the quote using: + +```ts +const attestationResult = await client.attestSgxEnclave(quote, { + runTimeData: binaryRuntimeData +}); +``` + Additional information on how to perform attestation token validation can be found in the [MAA Service Attestation Sample](https://github.com/Azure-Samples/microsoft-azure-attestation). ### Retrieve Token Certificates -Use `getSigningCertificates` to retrieve the certificates which can be used to validate the token returned from the attestation service. +Use `getSigningCertificates` to retrieve the certificates which can be used to +validate the token returned from the attestation service. Note that this call +creates a client with azure credentials, that is not needed if you are calling +the `attestSgxEnclave` or `attestOpenEnclave` APIs ```ts const credentials = new DefaultAzureCredential(); @@ -348,11 +355,9 @@ Most Attestation service operations will raise exceptions defined in [Azure Core ```ts try { - await client.attestSgxEnclave(_openEnclaveReport, { - runTimeJson: stringToBytes('{"bogus": 10 }') - }); + await client.attestSgxEnclave(openEnclaveReport); } catch (error) { - console.log(`Expected Exception thrown for invalid request: ${error.message}`); + console.log(`Exception thrown for invalid request: ${error.message}`); } ``` diff --git a/sdk/attestation/attestation/package.json b/sdk/attestation/attestation/package.json index b552acbbb0ac..2e773e9d98d3 100644 --- a/sdk/attestation/attestation/package.json +++ b/sdk/attestation/attestation/package.json @@ -1,6 +1,6 @@ { "name": "@azure/attestation", - "version": "1.0.0-beta.5", + "version": "1.0.0", "description": "Javascript/Typescript client implementation for the Microsoft Azure Attestation service.", "sdk-type": "client", "main": "dist/index.js", diff --git a/sdk/attestation/attestation/src/constants.ts b/sdk/attestation/attestation/src/constants.ts index 2a542c1515b7..74649cd0dec9 100644 --- a/sdk/attestation/attestation/src/constants.ts +++ b/sdk/attestation/attestation/src/constants.ts @@ -1,4 +1,4 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -export const SDK_VERSION: string = "1.0.0-beta.5"; +export const SDK_VERSION: string = "1.0.0"; From bfc1e6a3cfb9484f0ce0afb6ecbdb73d24bf04e8 Mon Sep 17 00:00:00 2001 From: Larry Osterman Date: Wed, 28 Jul 2021 11:20:40 -0700 Subject: [PATCH 2/8] Pull request feedback; updated swagger version # --- sdk/attestation/attestation/CHANGELOG.md | 4 +++- .../attestation/src/generated/generatedClientContext.ts | 2 +- sdk/attestation/attestation/swagger/readme.md | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/sdk/attestation/attestation/CHANGELOG.md b/sdk/attestation/attestation/CHANGELOG.md index 66a33fc2d8cd..576a417f3235 100644 --- a/sdk/attestation/attestation/CHANGELOG.md +++ b/sdk/attestation/attestation/CHANGELOG.md @@ -8,7 +8,9 @@ Added hand authored implementation for policy management certificate APIs: `getP Simplified the calling pattern for the Attest family of APIs. Simplified some model types to be reflected as either parameters or interfaces. -The attestation family of APIs no longer requires authentication credentials +The attestation family of APIs no longer requires authentication credentials. +The attestation family of APIs now accepts Blob objects in addition to Uint8Array +and Buffer objects as inputs. ### Breaking Changes diff --git a/sdk/attestation/attestation/src/generated/generatedClientContext.ts b/sdk/attestation/attestation/src/generated/generatedClientContext.ts index 4761691748e6..d6f89afd9584 100644 --- a/sdk/attestation/attestation/src/generated/generatedClientContext.ts +++ b/sdk/attestation/attestation/src/generated/generatedClientContext.ts @@ -31,7 +31,7 @@ export class GeneratedClientContext extends coreClient.ServiceClient { requestContentType: "application/json; charset=utf-8" }; - const packageDetails = `azsdk-js-attestation/1.0.0-beta.2`; + const packageDetails = `azsdk-js-attestation/1.0.0`; const userAgentPrefix = options.userAgentOptions && options.userAgentOptions.userAgentPrefix ? `${options.userAgentOptions.userAgentPrefix} ${packageDetails}` diff --git a/sdk/attestation/attestation/swagger/readme.md b/sdk/attestation/attestation/swagger/readme.md index 1dec5035a515..cc901c7e92ec 100644 --- a/sdk/attestation/attestation/swagger/readme.md +++ b/sdk/attestation/attestation/swagger/readme.md @@ -17,7 +17,7 @@ autorest README.md ```yaml package-name: "@azure/attestation" -package-version: 1.0.0-beta.2 +package-version: 1.0.0 tag: package-2020-10-01 generate-metadata: false license-header: MICROSOFT_MIT_NO_VERSION From 3321db27d4e961521b11c327e2a86716f1169bf8 Mon Sep 17 00:00:00 2001 From: Larry Osterman Date: Wed, 28 Jul 2021 13:09:41 -0700 Subject: [PATCH 3/8] Use 1024 bit keys instead of 2048 bit keys --- sdk/attestation/attestation/samples-dev/utils/cryptoUtils.ts | 2 +- sdk/attestation/attestation/test/utils/cryptoUtils.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/attestation/attestation/samples-dev/utils/cryptoUtils.ts b/sdk/attestation/attestation/samples-dev/utils/cryptoUtils.ts index f5d519fa8c36..369521f442a5 100644 --- a/sdk/attestation/attestation/samples-dev/utils/cryptoUtils.ts +++ b/sdk/attestation/attestation/samples-dev/utils/cryptoUtils.ts @@ -16,7 +16,7 @@ export function createECDSKey(): [string, string] { } export function createRSAKey(): [string, string] { - const keyPair = jsrsasign.KEYUTIL.generateKeypair("RSA", 2048); + const keyPair = jsrsasign.KEYUTIL.generateKeypair("RSA", 1024); return [ jsrsasign.KEYUTIL.getPEM(keyPair.prvKeyObj, "PKCS8PRV"), jsrsasign.KEYUTIL.getPEM(keyPair.pubKeyObj, "PKCS8PUB") diff --git a/sdk/attestation/attestation/test/utils/cryptoUtils.ts b/sdk/attestation/attestation/test/utils/cryptoUtils.ts index f5d519fa8c36..369521f442a5 100644 --- a/sdk/attestation/attestation/test/utils/cryptoUtils.ts +++ b/sdk/attestation/attestation/test/utils/cryptoUtils.ts @@ -16,7 +16,7 @@ export function createECDSKey(): [string, string] { } export function createRSAKey(): [string, string] { - const keyPair = jsrsasign.KEYUTIL.generateKeypair("RSA", 2048); + const keyPair = jsrsasign.KEYUTIL.generateKeypair("RSA", 1024); return [ jsrsasign.KEYUTIL.getPEM(keyPair.prvKeyObj, "PKCS8PRV"), jsrsasign.KEYUTIL.getPEM(keyPair.pubKeyObj, "PKCS8PUB") From 425a52dd749819fb19d90319861bbda81666e642 Mon Sep 17 00:00:00 2001 From: Larry Osterman Date: Wed, 28 Jul 2021 14:11:03 -0700 Subject: [PATCH 4/8] Added readme.md to versioned elements --- sdk/attestation/attestation/package.json | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sdk/attestation/attestation/package.json b/sdk/attestation/attestation/package.json index 2e773e9d98d3..c86267a4e474 100644 --- a/sdk/attestation/attestation/package.json +++ b/sdk/attestation/attestation/package.json @@ -17,8 +17,12 @@ "//metadata": { "constantPaths": [ { - "path": "src/constants.ts", - "prefix": "SDK_VERSION" + "path": "src/generated/generatedClientContext.ts", + "prefix": "packageDetails" + }, + { + "path": "swagger/README.md", + "prefix": "package-version" } ] }, From aee430f9edaecdc151685a7d039930882f792eea Mon Sep 17 00:00:00 2001 From: Larry Osterman Date: Wed, 28 Jul 2021 15:20:16 -0700 Subject: [PATCH 5/8] Oops - still need constants.ts --- sdk/attestation/attestation/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/attestation/attestation/package.json b/sdk/attestation/attestation/package.json index c86267a4e474..90beaaee8e90 100644 --- a/sdk/attestation/attestation/package.json +++ b/sdk/attestation/attestation/package.json @@ -17,8 +17,8 @@ "//metadata": { "constantPaths": [ { - "path": "src/generated/generatedClientContext.ts", - "prefix": "packageDetails" + "path": "src/constants.ts", + "prefix": "SDK_VERSION" }, { "path": "swagger/README.md", From 3ece44eef6ef32c761bcfdeb74e8bfa5a16a2ba4 Mon Sep 17 00:00:00 2001 From: Larry Osterman Date: Wed, 28 Jul 2021 15:26:07 -0700 Subject: [PATCH 6/8] Rely on generated client for versioning --- sdk/attestation/attestation/package.json | 4 ---- .../src/attestationAdministrationClient.ts | 12 ------------ sdk/attestation/attestation/src/attestationClient.ts | 11 ----------- sdk/attestation/attestation/src/constants.ts | 4 ---- 4 files changed, 31 deletions(-) delete mode 100644 sdk/attestation/attestation/src/constants.ts diff --git a/sdk/attestation/attestation/package.json b/sdk/attestation/attestation/package.json index 90beaaee8e90..776c578e11a0 100644 --- a/sdk/attestation/attestation/package.json +++ b/sdk/attestation/attestation/package.json @@ -16,10 +16,6 @@ }, "//metadata": { "constantPaths": [ - { - "path": "src/constants.ts", - "prefix": "SDK_VERSION" - }, { "path": "swagger/README.md", "prefix": "package-version" diff --git a/sdk/attestation/attestation/src/attestationAdministrationClient.ts b/sdk/attestation/attestation/src/attestationAdministrationClient.ts index c959cc121bd5..d623f5c53f33 100644 --- a/sdk/attestation/attestation/src/attestationAdministrationClient.ts +++ b/sdk/attestation/attestation/src/attestationAdministrationClient.ts @@ -3,7 +3,6 @@ import { SpanStatusCode } from "@azure/core-tracing"; -import { SDK_VERSION } from "./constants"; import { GeneratedClient } from "./generated/generatedClient"; import { logger } from "./logger"; @@ -101,17 +100,6 @@ export class AttestationAdministrationClient { credentials: TokenCredential, options: AttestationAdministrationClientOptions = {} ) { - // The below code helps us set a proper User-Agent header on all requests - const libInfo = `azsdk-js-api-security-attestation/${SDK_VERSION}`; - if (!options.userAgentOptions) { - options.userAgentOptions = {}; - } - if (options.userAgentOptions.userAgentPrefix) { - options.userAgentOptions.userAgentPrefix = `${options.userAgentOptions.userAgentPrefix} ${libInfo}`; - } else { - options.userAgentOptions.userAgentPrefix = libInfo; - } - this._validationOptions = options.validationOptions; const internalPipelineOptions: GeneratedClientOptionalParams = { diff --git a/sdk/attestation/attestation/src/attestationClient.ts b/sdk/attestation/attestation/src/attestationClient.ts index fea71c863d21..75d4823c8a3e 100644 --- a/sdk/attestation/attestation/src/attestationClient.ts +++ b/sdk/attestation/attestation/src/attestationClient.ts @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import { SDK_VERSION } from "./constants"; import { GeneratedClient } from "./generated/generatedClient"; import { AttestationSigner, AttestationTokenValidationOptions, AttestationResult } from "./models"; @@ -163,16 +162,6 @@ export class AttestationClient { */ constructor(endpoint: string, options: AttestationClientOptions = {}) { - // The below code helps us set a proper User-Agent header on all requests - const libInfo = `azsdk-js-api-security-attestation/${SDK_VERSION}`; - if (!options.userAgentOptions) { - options.userAgentOptions = {}; - } - if (options.userAgentOptions.userAgentPrefix) { - options.userAgentOptions.userAgentPrefix = `${options.userAgentOptions.userAgentPrefix} ${libInfo}`; - } else { - options.userAgentOptions.userAgentPrefix = libInfo; - } let credentialScopes: string[] | undefined = undefined; if (options.credentials) { diff --git a/sdk/attestation/attestation/src/constants.ts b/sdk/attestation/attestation/src/constants.ts deleted file mode 100644 index 74649cd0dec9..000000000000 --- a/sdk/attestation/attestation/src/constants.ts +++ /dev/null @@ -1,4 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -export const SDK_VERSION: string = "1.0.0"; From ab6c7376675cd04b1bb46ce7da29a87c9e9fc017 Mon Sep 17 00:00:00 2001 From: Larry Osterman Date: Wed, 28 Jul 2021 15:31:40 -0700 Subject: [PATCH 7/8] Accidentally removed generatedClientContext --- sdk/attestation/attestation/package.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sdk/attestation/attestation/package.json b/sdk/attestation/attestation/package.json index 776c578e11a0..c86267a4e474 100644 --- a/sdk/attestation/attestation/package.json +++ b/sdk/attestation/attestation/package.json @@ -16,6 +16,10 @@ }, "//metadata": { "constantPaths": [ + { + "path": "src/generated/generatedClientContext.ts", + "prefix": "packageDetails" + }, { "path": "swagger/README.md", "prefix": "package-version" From 1341b9faeb455f7fc6c62d8fc125a55697c8d0c8 Mon Sep 17 00:00:00 2001 From: Larry Osterman Date: Thu, 29 Jul 2021 08:48:47 -0700 Subject: [PATCH 8/8] Prettier --- sdk/attestation/attestation/src/attestationClient.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/sdk/attestation/attestation/src/attestationClient.ts b/sdk/attestation/attestation/src/attestationClient.ts index 75d4823c8a3e..08908dc39684 100644 --- a/sdk/attestation/attestation/src/attestationClient.ts +++ b/sdk/attestation/attestation/src/attestationClient.ts @@ -162,7 +162,6 @@ export class AttestationClient { */ constructor(endpoint: string, options: AttestationClientOptions = {}) { - let credentialScopes: string[] | undefined = undefined; if (options.credentials) { credentialScopes = ["https://attest.azure.net/.default"];