Example #1
0
        /// <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(&lt;Customer provided signing key&gt;, &lt;Customer provided certificate&gt;)
        /// 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>
        /// 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(&lt;Customer provided signing key&gt;, &lt;Customer provided certificate&gt;)
        /// 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 UnsecuredAttestationToken(new StoredAttestationPolicy { AttestationPolicy = disallowDebugging });
        /// disallowDebuggingHash = shaHasher.ComputeHash(Encoding.UTF8.GetBytes(policySetToken.ToString()));
        /// </code>
        /// </remarks>
        public virtual AttestationResponse <PolicyResult> SetPolicy(
            AttestationType attestationType,
            string policyToSet,
            TokenSigningKey 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(
                    new StoredAttestationPolicy {
                    AttestationPolicy = policyToSet,
                },
                    signingKey);

                var result = _policyClient.Set(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;
            }
        }
Example #3
0
        /// <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.
        ///
        /// 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/>
        /// 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 AttestationResponse <PolicyResult> SetPolicy(
            AttestationType attestationType,
            string policyToSet,
            AsymmetricAlgorithm signingKey      = default,
            X509Certificate2 signingCertificate = default,
            CancellationToken cancellationToken = default)
        {
            Argument.AssertNotNullOrWhiteSpace(policyToSet, 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 = _policyClient.Set(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;
            }
        }
Example #4
0
 /// <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 AttestationResponse <PolicyResult> SetPolicy(AttestationType attestationType, AttestationToken policyToSet, CancellationToken cancellationToken = default)
 {
     using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(AttestationAdministrationClient)}.{nameof(SetPolicy)}");
     scope.Start();
     try
     {
         var result = _policyClient.Set(attestationType, policyToSet.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;
     }
 }