diff --git a/sdk/attestation/attestation/CHANGELOG.md b/sdk/attestation/attestation/CHANGELOG.md index 6ced7a40f9b6..576a417f3235 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 @@ -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/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..c86267a4e474 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", @@ -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" } ] }, 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/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..08908dc39684 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,17 +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) { credentialScopes = ["https://attest.azure.net/.default"]; diff --git a/sdk/attestation/attestation/src/constants.ts b/sdk/attestation/attestation/src/constants.ts deleted file mode 100644 index 2a542c1515b7..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-beta.5"; 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 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")