Skip to content
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

Prepare for GA release #16619

Merged
merged 8 commits into from
Jul 29, 2021
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions sdk/attestation/attestation/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
# Release History

## 1.0.0-beta.5 (Unreleased)
## 1.0.0 (2021-08-10)

### Features Added
LarryOsterman marked this conversation as resolved.
Show resolved Hide resolved

Added hand authored implementation for policy management certificate APIs: `getPolicyManagementCertificates`, `addPolicyManagementCertificate` and `removePolicyManagementCertificate`.

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

Expand Down
57 changes: 31 additions & 26 deletions sdk/attestation/attestation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -250,8 +250,8 @@ const client = new AttestationAdministrationClient(endpoint, new DefaultAzureCre
const newPolicy = `<New Policy Document>`;

// Set the new attestation policy. Set the policy as an secured policy.
const privateKey = <Get isolated mode private key from storage>
const certificate = <Get certificate associated with that private key>
const privateKey = <Retrieve isolated mode private key from storage>
const certificate = <Retrieve certificate associated with that private key>

const setPolicyResult = await client.setPolicy(
KnownAttestationType.OpenEnclave,
Expand All @@ -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:
Expand All @@ -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.

Expand All @@ -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
});
```
Expand All @@ -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();
Expand All @@ -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}`);
}
```

Expand Down
10 changes: 7 additions & 3 deletions sdk/attestation/attestation/package.json
Original file line number Diff line number Diff line change
@@ -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",
Expand All @@ -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"
}
]
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

import { SpanStatusCode } from "@azure/core-tracing";

import { SDK_VERSION } from "./constants";
import { GeneratedClient } from "./generated/generatedClient";

import { logger } from "./logger";
Expand Down Expand Up @@ -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 = {
Expand Down
11 changes: 0 additions & 11 deletions sdk/attestation/attestation/src/attestationClient.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand Down Expand Up @@ -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) {
Expand Down
4 changes: 0 additions & 4 deletions sdk/attestation/attestation/src/constants.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -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}`
Expand Down
2 changes: 1 addition & 1 deletion sdk/attestation/attestation/swagger/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion sdk/attestation/attestation/test/utils/cryptoUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down