/// <summary> /// Resets the policy for the specified <see cref="AttestationType"/> to the default value. /// </summary> /// <param name="attestationType"><see cref="AttestationType"/> whose policy should be reset.</param> /// <param name="signingKey">If provided, specifies the signing key used to sign the request to the attestation service.</param> /// <param name="cancellationToken">Cancellation token used to cancel this operation.</param> /// <returns>An <see cref="AttestationResponse{PolicyResult}"/> with the policy for the specified attestation type.</returns> /// <remarks> /// If the <paramref name="signingKey"/> parameter is not provided, then the policy document sent to the /// attestation service will be unsigned. Unsigned attestation policies are only allowed when the attestation instance is running in AAD mode - if the /// attestation instance is running in Isolated mode, then a signing key and signing certificate MUST be provided to ensure that the caller of the API is authorized to change policy. /// The <see cref="AttestationTokenSigningKey.Certificate"/> parameter MUST be one of the certificates returned by the <see cref="GetPolicyManagementCertificates(CancellationToken)"/> API. /// <para/> /// </remarks> public virtual async Task <AttestationResponse <PolicyModificationResult> > ResetPolicyAsync( AttestationType attestationType, AttestationTokenSigningKey signingKey = default, CancellationToken cancellationToken = default) { using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(AttestationAdministrationClient)}.{nameof(ResetPolicy)}"); scope.Start(); try { AttestationToken tokenToSet = new AttestationToken(null, signingKey); var result = await _policyClient.ResetAsync(attestationType, tokenToSet.Serialize(), cancellationToken).ConfigureAwait(false); var token = AttestationToken.Deserialize(result.Value.Token, _clientDiagnostics); if (_options.TokenOptions.ValidateToken) { var signers = await GetSignersAsync(true, cancellationToken).ConfigureAwait(false); if (!await token.ValidateTokenAsync(_options.TokenOptions, signers, cancellationToken).ConfigureAwait(false)) { AttestationTokenValidationFailedException.ThrowFailure(signers, token); } } return(new AttestationResponse <PolicyModificationResult>(result.GetRawResponse(), token)); } catch (Exception ex) { scope.Failed(ex); throw; } }
/// <summary> /// Retrieves the attesttion policy for the specified <see cref="AttestationType"/>. /// </summary> /// <param name="attestationType">Attestation Type to retrive.</param> /// <param name="cancellationToken">Cancellation token used to cancel this operation.</param> /// <returns>An <see cref="AttestationResponse{String}"/> with the policy for the specified attestation type.</returns> /// <remarks> /// This API returns the underlying attestation policy object stored in the attestation service for this <paramref name="attestationType"/>. /// /// The actual service response to the API is an RFC 7519 JSON Web Token. This token can be retrieved from <see cref="AttestationResponse{T}.Token"/>. /// For the GetPolicyAsync API, the body of the <see cref="AttestationResponse{T}.Token"/> is a <see cref="StoredAttestationPolicy"/> object, NOT a string. /// </remarks> public virtual async Task <AttestationResponse <string> > GetPolicyAsync(AttestationType attestationType, CancellationToken cancellationToken = default) { using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(AttestationAdministrationClient)}.{nameof(GetPolicy)}"); scope.Start(); try { var result = await _policyClient.GetAsync(attestationType, cancellationToken).ConfigureAwait(false); var token = new AttestationToken(result.Value.Token); if (_options.ValidateAttestationTokens) { token.ValidateToken(GetSigners(), _options.ValidationCallback); } using var document = JsonDocument.Parse(token.TokenBody); PolicyResult policyResult = PolicyResult.DeserializePolicyResult(document.RootElement); var response = new AttestationResponse <StoredAttestationPolicy>(result.GetRawResponse(), policyResult.PolicyToken); return(new AttestationResponse <string>(result.GetRawResponse(), policyResult.PolicyToken, response.Value.AttestationPolicy)); } catch (Exception ex) { scope.Failed(ex); throw; } }
/// <summary> /// Sets the attesttion policy for the specified <see cref="AttestationType"/>. /// </summary> /// <param name="attestationType"><see cref="AttestationType"/> whose policy should be set.</param> /// <param name="policyToSet">Specifies the attestation policy to set.</param> /// <param name="signingKey">If provided, specifies the signing key used to sign the request to the attestation service.</param> /// <param name="cancellationToken">Cancellation token used to cancel this operation.</param> /// <returns>An <see cref="AttestationResponse{PolicyResult}"/> with the policy for the specified attestation type.</returns> /// <remarks> /// If the <paramref name="signingKey"/> parameter is not provided, then the policy document sent to the /// attestation service will be unsigned. Unsigned attestation policies are only allowed when the attestation instance is running in AAD mode - if the /// attestation instance is running in Isolated mode, then a signing key and signing certificate MUST be provided to ensure that the caller of the API is authorized to change policy. /// The <see cref="AttestationTokenSigningKey.Certificate"/> field MUST be one of the certificates returned by the <see cref="GetPolicyManagementCertificates(CancellationToken)"/> API. /// <para/> /// 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. /// There are two properties provided in the [PolicyResult][attestation_policy_result] that can be used to verify that the service received the policy document: /// <list type="bullet"> /// <item> /// <description><see cref="PolicyModificationResult.PolicySigner"/> - if the <see cref="SetPolicy(AttestationType, string, AttestationTokenSigningKey, CancellationToken)"/> 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. </description> /// </item> /// <item> /// <description><see cref="PolicyModificationResult.PolicyTokenHash"/> - this is the hash of the [JSON Web Token][json_web_token] sent to the service</description> /// </item> /// </list> /// To verify the hash, clients can generate an attestation token and verify the hash generated from that token: /// <code snippet="Snippet:VerifySigningHash"> /// // The SetPolicyAsync API will create an AttestationToken signed with the TokenSigningKey to transmit the policy. /// // To verify that the policy specified by the caller was received by the service inside the enclave, we /// // verify that the hash of the policy document returned from the Attestation Service matches the hash /// // of an attestation token created locally. /// TokenSigningKey signingKey = new TokenSigningKey(<Customer provided signing key>, <Customer provided certificate>) /// var policySetToken = new AttestationToken( /// BinaryData.FromObjectAsJson(new StoredAttestationPolicy { AttestationPolicy = attestationPolicy }), /// signingKey); /// /// using var shaHasher = SHA256Managed.Create(); /// byte[] attestationPolicyHash = shaHasher.ComputeHash(Encoding.UTF8.GetBytes(policySetToken.Serialize())); /// /// Debug.Assert(attestationPolicyHash.SequenceEqual(setResult.Value.PolicyTokenHash.ToArray())); /// </code> /// /// If the signing key and certificate are not provided, then the SetPolicyAsync API will create an unsecured attestation token /// wrapping the attestation policy. To validate the <see cref="PolicyModificationResult.PolicyTokenHash"/> return value, a developer /// can create their own <see cref="AttestationToken"/> and create the hash of that. /// <code> /// using var shaHasher = SHA256Managed.Create(); /// var policySetToken = new UnsecuredAttestationToken(new StoredAttestationPolicy { AttestationPolicy = disallowDebugging }); /// disallowDebuggingHash = shaHasher.ComputeHash(Encoding.UTF8.GetBytes(policySetToken.Serialize())); /// </code> /// </remarks> public virtual AttestationResponse <PolicyModificationResult> SetPolicy( AttestationType attestationType, string policyToSet, AttestationTokenSigningKey signingKey = default, CancellationToken cancellationToken = default) { Argument.AssertNotNullOrWhiteSpace(policyToSet, nameof(policyToSet)); using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(AttestationAdministrationClient)}.{nameof(SetPolicy)}"); scope.Start(); try { AttestationToken tokenToSet = new AttestationToken( BinaryData.FromObjectAsJson(new StoredAttestationPolicy { AttestationPolicy = policyToSet, }), signingKey); var result = _policyClient.Set(attestationType, tokenToSet.Serialize(), cancellationToken); var token = AttestationToken.Deserialize(result.Value.Token); if (_options.TokenOptions.ValidateToken) { var signers = GetSignersAsync(false, cancellationToken).EnsureCompleted(); if (!token.ValidateToken(_options.TokenOptions, signers, cancellationToken)) { AttestationTokenValidationFailedException.ThrowFailure(signers, token); } } return(new AttestationResponse <PolicyModificationResult>(result.GetRawResponse(), token)); } catch (Exception ex) { scope.Failed(ex); throw; } }
/// <summary> /// Resets the policy for the specified <see cref="AttestationType"/> to the default value. /// </summary> /// <param name="attestationType"><see cref="AttestationType"/> whose policy should be reset.</param> /// <param name="signingKey">If provided, specifies the signing key and certificate used to sign the request to the attestation service.</param> /// <param name="cancellationToken">Cancellation token used to cancel this operation.</param> /// <returns>An <see cref="AttestationResponse{PolicyResult}"/> with the policy for the specified attestation type.</returns> /// <remarks> /// If the <paramref name="signingKey"/> parameter is not provided, then the policy document sent to the /// attestation service will be unsigned. Unsigned attestation policies are only allowed when the attestation instance is running in AAD mode - if the /// attestation instance is running in Isolated mode, then a signing key and signing certificate MUST be provided to ensure that the caller of the API is authorized to change policy. /// The <see cref="TokenSigningKey.Certificate"/> fieldMUST be one of the certificates returned by the <see cref="GetPolicyManagementCertificates(CancellationToken)"/> API. /// <para/> /// </remarks> /// public virtual AttestationResponse <PolicyResult> ResetPolicy( AttestationType attestationType, TokenSigningKey signingKey = default, CancellationToken cancellationToken = default) { using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(AttestationAdministrationClient)}.{nameof(ResetPolicy)}"); scope.Start(); try { AttestationToken tokenToSet = new AttestationToken(null, signingKey); var result = _policyClient.Reset(attestationType, tokenToSet.ToString(), cancellationToken); var token = new AttestationToken(result.Value.Token); if (_options.TokenOptions.ValidateToken) { token.ValidateToken(_options.TokenOptions, GetSigners(cancellationToken), cancellationToken); } return(new AttestationResponse <PolicyResult>(result.GetRawResponse(), token)); } catch (Exception ex) { scope.Failed(ex); throw; } }
/// <summary> /// Sets the attesttion policy for the specified <see cref="AttestationType"/>. /// </summary> /// <param name="attestationType"><see cref="AttestationType"/> whose policy should be set.</param> /// <param name="policyToSet">Specifies the attestation policy to set.</param> /// <param name="signingKey">If provided, specifies the signing key used to sign the request to the attestation service.</param> /// <param name="cancellationToken">Cancellation token used to cancel this operation.</param> /// <returns>An <see cref="AttestationResponse{PolicyResult}"/> with the policy for the specified attestation type.</returns> /// <remarks> /// If the <paramref name="signingKey"/> parameter is not provided, then the policy document sent to the /// attestation service will be unsigned. Unsigned attestation policies are only allowed when the attestation instance is running in AAD mode - if the /// attestation instance is running in Isolated mode, then a signing key and signing certificate MUST be provided to ensure that the caller of the API is authorized to change policy. /// The <see cref="TokenSigningKey.Certificate"/> field MUST be one of the certificates returned by the <see cref="GetPolicyManagementCertificates(CancellationToken)"/> API. /// <para/> /// 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. /// There are two properties provided in the [PolicyResult][attestation_policy_result] that can be used to verify that the service received the policy document: /// <list type="bullet"> /// <item> /// <description><see cref="PolicyResult.PolicySigner"/> - if the <see cref="SetPolicy(AttestationType, string, TokenSigningKey, CancellationToken)"/> 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. </description> /// </item> /// <item> /// <description><see cref="PolicyResult.PolicyTokenHash"/> - this is the hash of the [JSON Web Token][json_web_token] sent to the service</description> /// </item> /// </list> /// To verify the hash, clients can generate an attestation token and verify the hash generated from that token: /// <code snippet="Snippet:VerifySigningHash"> /// // The SetPolicyAsync API will create an AttestationToken signed with the TokenSigningKey to transmit the policy. /// // To verify that the policy specified by the caller was received by the service inside the enclave, we /// // verify that the hash of the policy document returned from the Attestation Service matches the hash /// // of an attestation token created locally. /// TokenSigningKey signingKey = new TokenSigningKey(<Customer provided signing key>, <Customer provided certificate>) /// var policySetToken = new AttestationToken( /// new StoredAttestationPolicy { AttestationPolicy = attestationPolicy }, /// signingKey); /// /// using var shaHasher = SHA256Managed.Create(); /// var attestationPolicyHash = shaHasher.ComputeHash(Encoding.UTF8.GetBytes(policySetToken.ToString())); /// /// Debug.Assert(attestationPolicyHash.SequenceEqual(setResult.Value.PolicyTokenHash)); /// </code> /// /// If the signing key and certificate are not provided, then the SetPolicyAsync API will create an unsecured attestation token /// wrapping the attestation policy. To validate the <see cref="PolicyResult.PolicyTokenHash"/> return value, a developer /// can create their own <see cref="AttestationToken"/> and create the hash of that. /// <code> /// using var shaHasher = SHA256Managed.Create(); /// var policySetToken = new AttestationToken(new StoredAttestationPolicy { AttestationPolicy = disallowDebugging }); /// disallowDebuggingHash = shaHasher.ComputeHash(Encoding.UTF8.GetBytes(policySetToken.ToString())); /// </code> /// </remarks> public virtual async Task <AttestationResponse <PolicyResult> > SetPolicyAsync( AttestationType attestationType, string policyToSet, TokenSigningKey signingKey = default, CancellationToken cancellationToken = default) { if (string.IsNullOrEmpty(policyToSet)) { throw new ArgumentException($"'{nameof(policyToSet)}' cannot be null or empty.", nameof(policyToSet)); } using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(AttestationAdministrationClient)}.{nameof(SetPolicy)}"); scope.Start(); try { AttestationToken tokenToSet = new AttestationToken(new StoredAttestationPolicy { AttestationPolicy = policyToSet, }, signingKey); var result = await _policyClient.SetAsync(attestationType, tokenToSet.ToString(), cancellationToken).ConfigureAwait(false); var token = new AttestationToken(result.Value.Token); if (_options.TokenOptions.ValidateToken) { await token.ValidateTokenAsync(_options.TokenOptions, await GetSignersAsync(cancellationToken).ConfigureAwait(false), cancellationToken).ConfigureAwait(false); } return(new AttestationResponse <PolicyResult>(result.GetRawResponse(), token)); } catch (Exception ex) { scope.Failed(ex); throw; } }
/// <summary> /// Sets the attesttion policy for the specified <see cref="AttestationType"/>. /// </summary> /// <param name="attestationType"><see cref="AttestationType"/> whose policy should be set.</param> /// <param name="policyToSet">Specifies the attestation policy to set.</param> /// <param name="signingKey">If provided, specifies the signing key used to sign the request to the attestation service.</param> /// <param name="signingCertificate">If provided, specifies the X.509 certificate which will be used to validate the request with the attestation service.</param> /// <param name="cancellationToken">Cancellation token used to cancel this operation.</param> /// <returns>An <see cref="AttestationResponse{PolicyResult}"/> with the policy for the specified attestation type.</returns> /// <remarks> /// The <paramref name="signingKey"/> and <paramref name="signingCertificate"/> parameters are optional, but if one is provided the other must also be provided. /// <para/> /// If the <paramref name="signingKey"/> and <paramref name="signingCertificate"/> parameters are not provided, then the policy document sent to the /// attestation service will be unsigned. Unsigned attestation policies are only allowed when the attestation instance is running in AAD mode - if the /// attestation instance is running in Isolated mode, then a signing key and signing certificate MUST be provided to ensure that the caller of the API is authorized to change policy. /// The <paramref name="signingCertificate"/> parameter MUST be one of the certificates returned by the <see cref="GetPolicyManagementCertificates(CancellationToken)"/> API. /// <para/> /// <para/> /// 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. /// There are two properties provided in the [PolicyResult][attestation_policy_result] that can be used to verify that the service received the policy document: /// <list type="bullet"> /// <item> /// <description><see cref="PolicyResult.PolicySigner"/> - if the <see cref="SetPolicy(AttestationType, string, AsymmetricAlgorithm, X509Certificate2, CancellationToken)"/> 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. </description> /// </item> /// <item> /// <description><see cref="PolicyResult.PolicyTokenHash"/> - this is the hash of the [JSON Web Token][json_web_token] sent to the service</description> /// </item> /// </list> /// To verify the hash, clients can generate an attestation token and verify the hash generated from that token: /// <code snippet="Snippet:VerifySigningHash"> /// // The SetPolicyAsync API will create a SecuredAttestationToken to transmit the policy. /// var policySetToken = new SecuredAttestationToken(new StoredAttestationPolicy { AttestationPolicy = attestationPolicy }, TestEnvironment.PolicySigningKey0, policyTokenSigner); /// /// var shaHasher = SHA256Managed.Create(); /// var attestationPolicyHash = shaHasher.ComputeHash(Encoding.UTF8.GetBytes(policySetToken.ToString())); /// /// CollectionAssert.AreEqual(attestationPolicyHash, setResult.Value.PolicyTokenHash); /// </code> /// /// If the signing key and certificate are not provided, then the SetPolicyAsync API will create an unsecured attestation token /// wrapping the attestation policy. To validate the <see cref="PolicyResult.PolicyTokenHash"/> return value, a developer /// can create their own <see cref="UnsecuredAttestationToken"/> and create the hash of that. /// <code> /// var shaHasher = SHA256Managed.Create(); /// var policySetToken = new UnsecuredAttestationToken(new StoredAttestationPolicy { AttestationPolicy = disallowDebugging }); /// disallowDebuggingHash = shaHasher.ComputeHash(Encoding.UTF8.GetBytes(policySetToken.ToString())); /// </code> /// </remarks> public virtual async Task <AttestationResponse <PolicyResult> > SetPolicyAsync( AttestationType attestationType, string policyToSet, AsymmetricAlgorithm signingKey = default, X509Certificate2 signingCertificate = default, CancellationToken cancellationToken = default) { if (string.IsNullOrEmpty(policyToSet)) { throw new ArgumentException($"'{nameof(policyToSet)}' cannot be null or empty.", nameof(policyToSet)); } if (signingKey is null && signingCertificate is not null || signingCertificate is null && signingKey is not null) { throw new ArgumentException($"If you specify '{nameof(signingKey)}' or '{nameof(signingCertificate)}', you must also specify '{nameof(signingCertificate)}' or '{nameof(signingKey)}'."); } using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(AttestationAdministrationClient)}.{nameof(SetPolicy)}"); scope.Start(); try { AttestationToken tokenToSet; if (signingKey is null) { tokenToSet = new UnsecuredAttestationToken(new StoredAttestationPolicy { AttestationPolicy = policyToSet, }); } else { tokenToSet = new SecuredAttestationToken(new StoredAttestationPolicy { AttestationPolicy = policyToSet, }, signingKey, signingCertificate); } var result = await _policyClient.SetAsync(attestationType, tokenToSet.ToString(), cancellationToken).ConfigureAwait(false); var token = new AttestationToken(result.Value.Token); if (_options.ValidateAttestationTokens) { token.ValidateToken(GetSigners(), _options.ValidationCallback); } return(new AttestationResponse <PolicyResult>(result.GetRawResponse(), token)); } catch (Exception ex) { scope.Failed(ex); throw; } }
public async Task <Response <PolicyResponse> > GetAsync(AttestationType attestationType, CancellationToken cancellationToken = default) { using var message = CreateGetRequest(attestationType); await _pipeline.SendAsync(message, cancellationToken).ConfigureAwait(false); switch (message.Response.Status) { case 200: { PolicyResponse value = default; using var document = await JsonDocument.ParseAsync(message.Response.ContentStream, default, cancellationToken).ConfigureAwait(false); value = PolicyResponse.DeserializePolicyResponse(document.RootElement); return(Response.FromValue(value, message.Response)); }
internal HttpMessage CreateGetRequest(AttestationType attestationType) { var message = _pipeline.CreateMessage(); var request = message.Request; request.Method = RequestMethod.Get; var uri = new RawRequestUriBuilder(); uri.AppendRaw(_instanceUrl, false); uri.AppendPath("/policies/", false); uri.AppendPath(attestationType.ToString(), true); uri.AppendQuery("api-version", _apiVersion, true); request.Uri = uri; request.Headers.Add("Accept", "application/json"); return(message); }
/// <summary> /// Resets the policy for the specified <see cref="AttestationType"/> to the default value. /// </summary> /// <param name="attestationType"><see cref="AttestationType"/> whose policy should be reset.</param> /// <param name="authorizationToken">Signed JSON Web Token signed by one of the policy management certificates used to verify the caller is authorized to reset policy to the default value..</param> /// <param name="cancellationToken"></param> /// <returns>An <see cref="AttestationResponse{PolicyResult}"/> with the policy for the specified attestation type.</returns> public virtual AttestationResponse <PolicyResult> ResetPolicy(AttestationType attestationType, AttestationToken authorizationToken = default, CancellationToken cancellationToken = default) { using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(AttestationAdministrationClient)}.{nameof(ResetPolicy)}"); scope.Start(); try { var result = _policyClient.Reset(attestationType, authorizationToken.ToString(), cancellationToken); var token = new AttestationToken(result.Value.Token); if (_options.ValidateAttestationTokens) { token.ValidateToken(GetSigners(), _options.ValidationCallback); } return(new AttestationResponse <PolicyResult>(result.GetRawResponse(), token)); } catch (Exception ex) { scope.Failed(ex); throw; } }
/// <summary> /// Resets the policy for the specified <see cref="AttestationType"/> to the default value. /// </summary> /// <param name="attestationType"><see cref="AttestationType"/> whose policy should be reset.</param> /// <param name="signingKey">If provided, specifies the signing key used to sign the request to the attestation service.</param> /// <param name="signingCertificate">If provided, specifies the X.509 certificate which will be used to validate the request with the attestation service.</param> /// <param name="cancellationToken">Cancellation token used to cancel this operation.</param> /// <returns>An <see cref="AttestationResponse{PolicyResult}"/> with the policy for the specified attestation type.</returns> /// <remarks> /// The <paramref name="signingKey"/> and <paramref name="signingCertificate"/> parameters are optional, but if one is provided the other must also be provided. /// <para/> /// If the <paramref name="signingKey"/> and <paramref name="signingCertificate"/> parameters are not provided, then the policy document sent to the /// attestation service will be unsigned. Unsigned attestation policies are only allowed when the attestation instance is running in AAD mode - if the /// attestation instance is running in Isolated mode, then a signing key and signing certificate MUST be provided to ensure that the caller of the API is authorized to change policy. /// The <paramref name="signingCertificate"/> parameter MUST be one of the certificates returned by the <see cref="GetPolicyManagementCertificates(CancellationToken)"/> API. /// <para/> /// </remarks> /// public virtual AttestationResponse <PolicyResult> ResetPolicy( AttestationType attestationType, AsymmetricAlgorithm signingKey = default, X509Certificate2 signingCertificate = default, CancellationToken cancellationToken = default) { if (signingKey is null && signingCertificate is not null || signingCertificate is null && signingKey is not null) { throw new ArgumentException($"If you specify '{nameof(signingKey)}' or '{nameof(signingCertificate)}', you must also specify '{nameof(signingCertificate)}' or '{nameof(signingKey)}'."); } using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(AttestationAdministrationClient)}.{nameof(ResetPolicy)}"); scope.Start(); try { AttestationToken tokenToSet; if (signingKey is null) { tokenToSet = new UnsecuredAttestationToken(); } else { tokenToSet = new SecuredAttestationToken(signingKey, signingCertificate); } var result = _policyClient.Reset(attestationType, tokenToSet.ToString(), cancellationToken); var token = new AttestationToken(result.Value.Token); if (_options.ValidateAttestationTokens) { token.ValidateToken(GetSigners(), _options.ValidationCallback); } return(new AttestationResponse <PolicyResult>(result.GetRawResponse(), token)); } catch (Exception ex) { scope.Failed(ex); throw; } }
/// <summary> /// Sets the attesttion policy for the specified <see cref="AttestationType"/>. /// </summary> /// <param name="attestationType"><see cref="AttestationType"/> whose policy should be set.</param> /// <param name="policyToSet">Specifies the attestation policy to set.</param> /// <param name="signingKey">If provided, specifies the signing key used to sign the request to the attestation service.</param> /// <param name="cancellationToken">Cancellation token used to cancel this operation.</param> /// <returns>An <see cref="AttestationResponse{PolicyResult}"/> with the policy for the specified attestation type.</returns> /// <remarks> /// If the <paramref name="signingKey"/> parameter is not provided, then the policy document sent to the /// attestation service will be unsigned. Unsigned attestation policies are only allowed when the attestation instance is running in AAD mode - if the /// attestation instance is running in Isolated mode, then a signing key and signing certificate MUST be provided to ensure that the caller of the API is authorized to change policy. /// The <see cref="AttestationTokenSigningKey.Certificate"/> field MUST be one of the certificates returned by the <see cref="GetPolicyManagementCertificates(CancellationToken)"/> API. /// <para/> /// 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. /// There are two properties provided in the [PolicyResult][attestation_policy_result] that can be used to verify that the service received the policy document: /// <list type="bullet"> /// <item> /// <description><see cref="PolicyModificationResult.PolicySigner"/> - if the <see cref="SetPolicy(AttestationType, string, AttestationTokenSigningKey, CancellationToken)"/> 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. </description> /// </item> /// <item> /// <description><see cref="PolicyModificationResult.PolicyTokenHash"/> - this is the hash of the [JSON Web Token][json_web_token] sent to the service</description> /// </item> /// </list> /// To verify the hash, clients can generate an attestation token and verify the hash generated from that token: /// <code snippet="Snippet:VerifySigningHash"> /// // The SetPolicyAsync API will create an AttestationToken signed with the TokenSigningKey to transmit the policy. /// // To verify that the policy specified by the caller was received by the service inside the enclave, we /// // verify that the hash of the policy document returned from the Attestation Service matches the hash /// // of an attestation token created locally. /// TokenSigningKey signingKey = new TokenSigningKey(<Customer provided signing key>, <Customer provided certificate>) /// var policySetToken = new AttestationToken( /// BinaryData.FromObjectAsJson(new StoredAttestationPolicy { AttestationPolicy = attestationPolicy }), /// signingKey); /// /// using var shaHasher = SHA256Managed.Create(); /// byte[] attestationPolicyHash = shaHasher.ComputeHash(Encoding.UTF8.GetBytes(policySetToken.Serialize())); /// /// Debug.Assert(attestationPolicyHash.SequenceEqual(setResult.Value.PolicyTokenHash.ToArray())); /// </code> /// /// If the signing key and certificate are not provided, then the SetPolicyAsync API will create an unsecured attestation token /// wrapping the attestation policy. To validate the <see cref="PolicyModificationResult.PolicyTokenHash"/> return value, a developer /// can create their own <see cref="AttestationToken"/> and create the hash of that. /// <code> /// using var shaHasher = SHA256Managed.Create(); /// var policySetToken = new AttestationToken(new StoredAttestationPolicy { AttestationPolicy = disallowDebugging }); /// disallowDebuggingHash = shaHasher.ComputeHash(Encoding.UTF8.GetBytes(policySetToken.ToString())); /// </code> /// </remarks> public virtual async Task <AttestationResponse <PolicyModificationResult> > SetPolicyAsync( AttestationType attestationType, string policyToSet, AttestationTokenSigningKey signingKey = default, CancellationToken cancellationToken = default) { if (string.IsNullOrEmpty(policyToSet)) { throw new ArgumentException($"'{nameof(policyToSet)}' cannot be null or empty.", nameof(policyToSet)); } using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(AttestationAdministrationClient)}.{nameof(SetPolicy)}"); scope.Start(); try { AttestationToken tokenToSet = new AttestationToken(BinaryData.FromObjectAsJson(new StoredAttestationPolicy { AttestationPolicy = policyToSet, }), signingKey); var result = await _policyClient.SetAsync(attestationType, tokenToSet.Serialize(), cancellationToken).ConfigureAwait(false); var token = AttestationToken.Deserialize(result.Value.Token, _clientDiagnostics); if (_options.TokenOptions.ValidateToken) { var signers = await GetSignersAsync(true, cancellationToken).ConfigureAwait(false); if (!await token.ValidateTokenAsync(_options.TokenOptions, signers, cancellationToken).ConfigureAwait(false)) { AttestationTokenValidationFailedException.ThrowFailure(signers, token); } } return(new AttestationResponse <PolicyModificationResult>(result.GetRawResponse(), token)); } catch (Exception ex) { scope.Failed(ex); throw; } }
/// <summary> /// Retrieves the attesttion policy for the specified <see cref="AttestationType"/>. /// </summary> /// <param name="attestationType"><see cref="AttestationType"/> to retrive.</param> /// <param name="cancellationToken">Cancellation token used to cancel this operation.</param> /// <param name="async">True if the call should be asynchronous.</param> /// <returns>An <see cref="AttestationResponse{String}"/> with the policy for the specified attestation type.</returns> /// <remarks> /// This API returns the underlying attestation policy object stored in the attestation service for this <paramref name="attestationType"/>. /// /// The actual service response to the API is an RFC 7519 JSON Web Token (see https://tools.ietf.org/html/rfc7519"). This token can be retrieved from <see cref="AttestationResponse{T}.Token"/>. /// For the GetPolicy API, the body of the <see cref="AttestationResponse{T}.Token"/> is a <see cref="StoredAttestationPolicy"/> object, NOT a string. /// </remarks> private async Task <AttestationResponse <string> > GetPolicyInternalAsync(AttestationType attestationType, bool async, CancellationToken cancellationToken = default) { using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(AttestationAdministrationClient)}.{nameof(GetPolicy)}"); scope.Start(); try { Response <PolicyResponse> result; if (async) { result = await _policyClient.GetAsync(attestationType, cancellationToken).ConfigureAwait(false); } else { result = _policyClient.Get(attestationType, cancellationToken); } var token = AttestationToken.Deserialize(result.Value.Token, _clientDiagnostics); if (_options.TokenOptions.ValidateToken) { var signers = await GetSignersAsync(async, cancellationToken).ConfigureAwait(false); if (!await token.ValidateTokenInternal(_options.TokenOptions, signers, async, cancellationToken).ConfigureAwait(false)) { AttestationTokenValidationFailedException.ThrowFailure(signers, token); } } PolicyModificationResult policyResult = token.GetBody <PolicyModificationResult>(); var response = new AttestationResponse <StoredAttestationPolicy>(result.GetRawResponse(), policyResult.PolicyToken); return(new AttestationResponse <string>(result.GetRawResponse(), token, response.Value.AttestationPolicy)); } catch (Exception ex) { scope.Failed(ex); throw; } }
/// <summary> /// Sets the attesttion policy for the specified <see cref="AttestationType"/>. /// </summary> /// <param name="attestationType"><see cref="AttestationType"/> whose policy should be set.</param> /// <param name="policyToSet"><see cref="AttestationToken"/> specifying the new stored attestation policy.</param> /// <param name="cancellationToken"></param> /// <returns>An <see cref="AttestationResponse{PolicyResult}"/> with the policy for the specified attestation type.</returns> public virtual async Task <AttestationResponse <PolicyResult> > SetPolicyAsync(AttestationType attestationType, AttestationToken policyToSet, CancellationToken cancellationToken = default) { using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(AttestationAdministrationClient)}.{nameof(SetPolicy)}"); scope.Start(); try { var result = await _policyClient.SetAsync(attestationType, policyToSet.ToString(), cancellationToken).ConfigureAwait(false); var token = new AttestationToken(result.Value.Token); if (_options.ValidateAttestationTokens) { token.ValidateToken(GetSigners(), _options.ValidationCallback); } return(new AttestationResponse <PolicyResult>(result.GetRawResponse(), token)); } catch (Exception ex) { scope.Failed(ex); throw; } }
/// <summary> /// Retrieves the attesttion policy for the specified <see cref="AttestationType"/>. /// </summary> /// <param name="attestationType">Attestation Type to retrive.</param> /// <param name="cancellationToken">Cancellation token used to cancel this operation.</param> /// <returns>An <see cref="AttestationResponse{String}"/> with the policy for the specified attestation type.</returns> /// <remarks> /// This API returns the underlying attestation policy object stored in the attestation service for this <paramref name="attestationType"/>. /// /// The actual service response to the API is an RFC 7519 JSON Web Token(see https://tools.ietf.org/html/rfc7519"). This token can be retrieved from <see cref="AttestationResponse{T}.Token"/>. /// For the GetPolicyAsync API, the body of the <see cref="AttestationResponse{T}.Token"/> is a <see cref="StoredAttestationPolicy"/> object, NOT a string. /// </remarks> public virtual async Task <AttestationResponse <string> > GetPolicyAsync(AttestationType attestationType, CancellationToken cancellationToken = default) => await GetPolicyInternalAsync(attestationType, true, cancellationToken).ConfigureAwait(false);
/// <summary> /// Retrieves the attesttion policy for the specified <see cref="AttestationType"/>. /// </summary> /// <param name="attestationType"><see cref="AttestationType"/> to retrive.</param> /// <param name="cancellationToken">Cancellation token used to cancel this operation.</param> /// <returns>An <see cref="AttestationResponse{String}"/> with the policy for the specified attestation type.</returns> /// <remarks> /// This API returns the underlying attestation policy object stored in the attestation service for this <paramref name="attestationType"/>. /// /// The actual service response to the API is an RFC 7519 JSON Web Token(see https://tools.ietf.org/html/rfc7519"). This token can be retrieved from <see cref="AttestationResponse{T}.Token"/>. /// For the GetPolicy API, the body of the <see cref="AttestationResponse{T}.Token"/> is a <see cref="StoredAttestationPolicy"/> object, NOT a string. /// </remarks> public virtual AttestationResponse <string> GetPolicy(AttestationType attestationType, CancellationToken cancellationToken = default) => GetPolicyInternalAsync(attestationType, false, cancellationToken).EnsureCompleted();