Skip to content

Commit

Permalink
Significant update to samples (Azure#25545)
Browse files Browse the repository at this point in the history
* Significant update to samples
  • Loading branch information
LarryOsterman authored Nov 24, 2021
1 parent 7849438 commit 6527358
Show file tree
Hide file tree
Showing 36 changed files with 2,920 additions and 484 deletions.
1 change: 1 addition & 0 deletions sdk/attestation/azure-security-attestation/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ on the `AttestationClientBuilder` class and implemented a new `AttestationAdmini
with the `listPolicyManagementCertificates`, `addPolicyManagementCertificate` and `removePolicyManagementCertificate` APIs on the `AttestationAdministrationClient` object.
* Removed `JsonWebKey`, `JsonWebKeySet`, `PolicyCertificatesModificationResult`, `PolicyCertificatesModifyResponse`, and `CertificatesResponse` objects
because they are no longer a part of the public API surface.
* Refactored `AttestationSigningKey` class to require certificate and signing key parameters in constructor.

### Bugs Fixed
* Attestation tests now all pass when run in Live mode.
Expand Down
196 changes: 140 additions & 56 deletions sdk/attestation/azure-security-attestation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,88 +83,173 @@ For more information on attestation policies, see [Attestation Policy](https://d
When an attestation instance is running in "Isolated" mode, the customer who created the instance will have provided
a policy management certificate at the time the instance is created. All policy modification operations require that the customer sign
the policy data with one of the existing policy management certificates. The Policy Management Certificate Management APIs enable
clients to "roll" the policy management certificates.
clients to add, remove or enumerate the policy management certificates.


## Examples

* [Attest an SGX enclave](#attest-sgx-enclave)
* [Get attestation policy](#get-attestation-policy)
* [Instantiate a synchronous attestation client](#create-a-synchronous-attestation-client)
* [Retrieve token validation certificates](#retrieve-token-certificates)
* [Attest an SGX enclave](#attest-an-sgx-enclave)
* [Instantiate a synchronous administrative client](#create-a-synchronous-administrative-client)
* [Get attestation policy](#retrieve-current-attestation-policy-for-openenclave)
* [Set unsigned attestation policy](#set-unsigned-attestation-policy-aad-clients-only)
* [Set signed attestation policy](#set-signed-attestation-policy)
* [List policy management certificates](#list-attestation-signing-certificates)
* [Add policy management certificate](#add-attestation-signing-certificate)

### Create a synchronous attestation client
The `AttestationClientBuilder` class is used to create instances of the attestation client:

```java readme-sample-create-synchronous-client
AttestationClientBuilder attestationBuilder = new AttestationClientBuilder();
// Note that the "attest" calls do not require authentication.
AttestationClient client = attestationBuilder
.endpoint(endpoint)
.buildClient();
```

### Attest SGX Enclave
### Retrieve Token Certificates

Use the `attestSgxEnclave` method to attest an SGX enclave.
<!-- embedme src\samples\com\azure\security\attestation\ReadmeSamples.java#L36-L44 -->
```java
AttestSgxEnclaveRequest request = new AttestSgxEnclaveRequest();
request.setQuote(decodedSgxQuote);
RuntimeData runtimeData = new RuntimeData();
runtimeData.setDataType(DataType.BINARY);
runtimeData.setData(decodedRuntimeData);
request.setRuntimeData(runtimeData);
AttestationResponse response = client.attestSgxEnclave(request);

JWTClaimsSet claims = null;
Use `listAttestationSigners` to retrieve the set of certificates which can be used to validate the token returned from the attestation service.
Normally, this information is not required as the attestation SDK will perform the validation as a part of the interaction with the
attestation service, however the APIs are provided for completeness and to facilitate customer's independently validating
attestation results.

```java readme-sample-getSigningCertificates
List<AttestationSigner> certs = client.listAttestationSigners();

certs.forEach(cert -> {
System.out.println("Found certificate.");
if (cert.getKeyId() != null) {
System.out.println(" Certificate Key ID: " + cert.getKeyId());
} else {
System.out.println(" Signer does not have a Key ID");
}
cert.getCertificates().forEach(chainElement -> {
System.out.println(" Cert Subject: " + chainElement.getSubjectDN().getName());
System.out.println(" Cert Issuer: " + chainElement.getIssuerDN().getName());
});
});
```
### Attest an SGX Enclave

### Get attestation policy
Use the `attestSgxEnclave` method to attest an SGX enclave.
```java readme-sample-attest-sgx-enclave
BinaryData decodedRuntimeData = BinaryData.fromBytes(SampleCollateral.getRunTimeData());
BinaryData sgxQuote = BinaryData.fromBytes(SampleCollateral.getSgxEnclaveQuote());

The `attestationPolicyClient.get` method retrieves the attestation policy from the service.
Attestation Policies are instanced on a per-attestation type basis, the `AttestationType` parameter defines the type to retrieve.
The response to an attestation policy get is a JSON Web Token signed by the attestation service.
The token contains an `x-ms-policy` claim, which in turn contains the secured (or unsecured) attestation policy document which was
set by the customer.
// Attest evidence from an OpenEnclave enclave specifying runtime data which should be
// interpreted as binary data.
AttestationResult result = client.attestSgxEnclave(new AttestationOptions(sgxQuote)
.setRunTimeData(
new AttestationData(decodedRuntimeData, AttestationDataInterpretation.BINARY)));

The attestation policy document is a JSON Web Signature object, with a single field named `AttestationPolicy`, whose value is the actual policy document encoded in Base64Url.
String issuer = result.getIssuer();

<!-- embedme src\samples\com\azure\security\attestation\ReadmeSamples.java#L59-L84 -->
```java
System.out.println("Attest Sgx Enclave completed. Issuer: " + issuer);
System.out.printf("Runtime Data Length: %d\n", result.getEnclaveHeldData().getLength());
```

sponse policyResponse = client.get(AttestationType.SGX_ENCLAVE);
testationToken(httpClient, clientUri, policyResponse.getToken())
scribe(claims -> {
if (claims != null) {
### Create a synchronous administrative client
All administrative clients are authenticated.
```java readme-sample-create-admin-client
AttestationAdministrationClientBuilder attestationBuilder = new AttestationAdministrationClientBuilder();
// Note that the "policy" calls require authentication.
AttestationAdministrationClient client = attestationBuilder
.endpoint(endpoint)
.credential(new DefaultAzureCredentialBuilder().build())
.buildClient();
```

String policyDocument = claims.getClaims().get("x-ms-policy").toString();
### Retrieve current attestation policy for OpenEnclave
Use the `getAttestationPolicy` API to retrieve the current attestation policy for a given TEE.
```java readme-sample-getCurrentPolicy
String currentPolicy = client.getAttestationPolicy(AttestationType.OPEN_ENCLAVE);
System.out.printf("Current policy for OpenEnclave is: %s\n", currentPolicy);
```

JOSEObject policyJose = null;
try {
policyJose = JOSEObject.parse(policyDocument);
} catch (ParseException e) {
throw logger.logExceptionAsError(new RuntimeException(e.toString()));
}
assert policyJose != null;
Map<String, Object> jsonObject = policyJose.getPayload().toJSONObject();
if (jsonObject != null) {
assertTrue(jsonObject.containsKey("AttestationPolicy"));
String base64urlPolicy = jsonObject.get("AttestationPolicy").toString();

byte[] attestationPolicyUtf8 = Base64.getUrlDecoder().decode(base64urlPolicy);
String attestationPolicy;
attestationPolicy = new String(attestationPolicyUtf8, StandardCharsets.UTF_8);
// Inspect the retrieved policy.
}
### Set unsigned attestation policy (AAD clients only)
When an attestation instance is in AAD mode, the caller can use a convenience method to set an unsigned attestation
policy on the instance.

```java readme-sample-set-unsigned-policy
// Set the listed policy on an attestation instance. Please note that this particular policy will deny all
// attestation requests and should not be used in production.
PolicyResult policyResult = client.setAttestationPolicy(AttestationType.OPEN_ENCLAVE, "version=1.0; authorizationrules{=> deny();}; issuancerules{};");
System.out.printf("Policy set for OpenEnclave result: %s\n", policyResult.getPolicyResolution());
```

### Set signed attestation policy
For isolated mode attestation instances, the set or reset policy request must be signed using the key which is associated
with the attestation signing certificates which are configured on the attestation instance.
```java readme-sample-set-signed-policy
// Set the listed policy on an attestation instance using a signed policy token.
PolicyResult policyResult = client.setAttestationPolicy(AttestationType.SGX_ENCLAVE,
new AttestationPolicySetOptions()
.setAttestationPolicy("version=1.0; authorizationrules{=> permit();}; issuancerules{};")
.setAttestationSigner(new AttestationSigningKey(certificate, privateKey)));
System.out.printf("Policy set for Sgx result: %s\n", policyResult.getPolicyResolution());
```

### List attestation signing certificates
When an attestation instance is in `Isolated` mode, the policy APIs need additional proof of authorization. This proof is
provided via the `AttestationSigningKey` parameter passed into the set and reset policy APIs.

Each `Isolated` mode instance has a set of certificates, which determine whether a caller has the authority to set an
attestation policy. When an attestation policy is set, the client presents a signed "token" to the service which is signed
by the key in the `AttestationSigningKey`. The signed token, including the certificate in the `AttestationSigningKey` is
sent to the attestation service, which verifies that the token was signed with the private key corresponding to the
public key in the token. The set or reset policy operation will only succeed if the certificate in the token is one of
the policy management tokens. This interaction ensures that the client is in possession of the private key associated with
one of the policy management certificates and is thus authorized to perform the operation.

```java readme-sample-listPolicyCertificates
List<AttestationSigner> signers = client.listPolicyManagementCertificates();
System.out.printf("Instance %s contains %d signers.\n", endpoint, signers.size());
for (AttestationSigner signer : signers) {
System.out.printf("Certificate Subject: %s", signer.getCertificates().get(0).getSubjectDN().toString());
}
```

### Retrieve Token Certificates
### Add attestation signing certificate
Adds a new certificate to the set of policy management certificates. The request to add the policy management certificate
must be signed with the private key associated with one of the existing policy management certificates (this ensures that
the caller is authorized to update the set of policy certificates).

Use `SigningCertificatesClient.get` to retrieve the certificates which can be used to validate the token returned from the attestation service.
Note: Adding the same certificate twice is not considered an error - if the certificate is already present, the addition is
ignored (this possibly surprising behavior is there because retries could cause the addition to be executed multiple times)

<!-- embedme src\samples\com\azure\security\attestation\ReadmeSamples.java#L89-L92 -->
```java
```java readme-sample-addPolicyManagementCertificate
System.out.printf("Adding new certificate %s\n", certificateToAdd.getSubjectDN().toString());
PolicyCertificatesModificationResult modificationResult = client.addPolicyManagementCertificate(
new PolicyManagementCertificateOptions(certificateToAdd, new AttestationSigningKey(isolatedCertificate, isolatedKey)));
System.out.printf("Updated policy certificate, certificate add result: %s\n", modificationResult.getCertificateResolution());
System.out.printf("Added certificate thumbprint: %s\n", modificationResult.getCertificateThumbprint());
```

### Remove attestation signing certificate
Removes a certificate from the set of policy management certificates. The request to remove the policy management certificate
must be signed with the private key associated with one of the existing policy management certificates (this ensures that
the caller is authorized to update the set of policy certificates).

AttestationClientBuilder attestationBuilder = getBuilder(httpClient, clientUri);
Note: Removing a non-existent certificate is not considered an error - if the certificate is not present, the removal is
ignored (this possibly surprising behavior is there because retries could cause the removal to be executed multiple times)

JsonWebKeySet certs = attestationBuilder.buildSigningCertificatesClient().get();
```java readme-sample-removePolicyManagementCertificate
System.out.printf("Removing existing certificate %s\n", certificateToRemove.getSubjectDN().toString());
PolicyCertificatesModificationResult modificationResult = client.removePolicyManagementCertificate(
new PolicyManagementCertificateOptions(certificateToRemove, new AttestationSigningKey(isolatedCertificate, isolatedKey)));
System.out.printf("Updated policy certificate, certificate remove result: %s\n", modificationResult.getCertificateResolution());
System.out.printf("Removed certificate thumbprint: %s\n", modificationResult.getCertificateThumbprint());
```

## Troubleshooting

## Troubleshooting
Troubleshooting information for the MAA service can be found [here](https://docs.microsoft.com/azure/attestation/troubleshoot-guide)

## Next steps
For more information about the Microsoft Azure Attestation service, please see our [documentation page](https://docs.microsoft.com/azure/attestation/).
For more information about the Microsoft Azure Attestation service, please see our [documentation page](https://docs.microsoft.com/azure/attestation/).

## Contributing
This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.microsoft.com.
Expand All @@ -173,7 +258,6 @@ When you submit a pull request, a CLA-bot will automatically determine whether y

This project has adopted the [Microsoft Open Source Code of Conduct][microsoft_code_of_conduct]. For more information see the Code of Conduct FAQ or contact <[email protected]> with any additional questions or comments.


<!-- LINKS -->
[style-guide-msft]: https://docs.microsoft.com/style-guide/capitalization

Expand Down
Loading

0 comments on commit 6527358

Please sign in to comment.