Пример #1
0
        public void ToObjectThrowsExceptionOnIncompatibleType()
        {
            TestModel payload = new TestModel {
                A = "value", B = 5, C = true
            };
            BinaryData data = BinaryData.FromObjectAsJson(payload);

            Assert.ThrowsAny <Exception>(() => data.ToObjectFromJson <string>());
            Assert.ThrowsAny <Exception>(() => data.ToObjectFromJson <MismatchedTestModel>(jsonTypeInfo: MismatchedTestModelJsonContext.Default.MismatchedTestModel));
        }
        public async Task GetUnsecuredAttestationToken()
        {
            object tokenBody = new StoredAttestationPolicy {
                AttestationPolicy = "Foo",
            };

            var    token           = new AttestationToken(BinaryData.FromObjectAsJson(tokenBody));
            string serializedToken = token.Serialize();

            await ValidateSerializedToken(serializedToken, tokenBody);
        }
 public void Send(string methodName, string argument)
 {
     sender.SendMessageAsync(new ServiceBusMessage(BinaryData.FromObjectAsJson(new AzureInvalidationMessage
     {
         CreationDate          = DateTime.UtcNow,
         OriginMachineName     = Environment.MachineName,
         OriginApplicationName = Schema.Current.ApplicationName,
         MethodName            = methodName,
         Argument = argument,
     }, EntityJsonContext.FullJsonSerializerOptions))).Wait();
 }
Пример #4
0
        public async Task SettingAttestationPolicy()
        {
            var endpoint = TestEnvironment.AadAttestationUrl;

            #region Snippet:GetPolicy
            var client = new AttestationAdministrationClient(new Uri(endpoint), new DefaultAzureCredential());

            AttestationResponse <string> policyResult = await client.GetPolicyAsync(AttestationType.SgxEnclave);

            string result = policyResult.Value;
            #endregion

            #region Snippet:SetPolicy
            string attestationPolicy = "version=1.0; authorizationrules{=> permit();}; issuancerules{};";

            //@@ X509Certificate2 policyTokenCertificate = new X509Certificate2(<Attestation Policy Signing Certificate>);
            //@@ AsymmetricAlgorithm policyTokenKey = <Attestation Policy Signing Key>;
            /*@@*/ var policyTokenCertificate = TestEnvironment.PolicyCertificate0;
            /*@@*/ var policyTokenKey         = TestEnvironment.PolicySigningKey0;

            var setResult = client.SetPolicy(AttestationType.SgxEnclave, attestationPolicy, new AttestationTokenSigningKey(policyTokenKey, policyTokenCertificate));
            #endregion

            #region 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>)
            /*@@*/ AttestationTokenSigningKey signingKey = new AttestationTokenSigningKey(policyTokenKey, policyTokenCertificate);
            var policySetToken = new AttestationToken(
                BinaryData.FromObjectAsJson(new StoredAttestationPolicy {
                AttestationPolicy = attestationPolicy
            }),
                signingKey);

            using var shaHasher = SHA256.Create();
            byte[] attestationPolicyHash = shaHasher.ComputeHash(Encoding.UTF8.GetBytes(policySetToken.Serialize()));

            Debug.Assert(attestationPolicyHash.SequenceEqual(setResult.Value.PolicyTokenHash.ToArray()));
            #endregion
            var resetResult = client.ResetPolicy(AttestationType.SgxEnclave);

            // When the attestation instance is in Isolated mode, the ResetPolicy API requires using a signing key/certificate to authorize the user.
            var resetResult2 = client.ResetPolicy(
                AttestationType.SgxEnclave,
                new AttestationTokenSigningKey(TestEnvironment.PolicySigningKey0, policyTokenCertificate));
            return;
        }
Пример #5
0
        public void ToFromCustomType()
        {
            #region Snippet:BinaryDataToFromCustomModel
            var model = new CustomModel
            {
                A = "some text",
                B = 5,
                C = true
            };

            var data = BinaryData.FromObjectAsJson(model);
            model = data.ToObjectFromJson <CustomModel>();
            #endregion
        }
        public async Task GetSecuredAttestationToken()
        {
            X509Certificate2    fullCertificate = TestEnvironment.PolicyManagementCertificate;
            AsymmetricAlgorithm privateKey      = TestEnvironment.PolicyManagementKey;

            object tokenBody = new StoredAttestationPolicy {
                AttestationPolicy = "Foo",
            };

            var    token           = new AttestationToken(BinaryData.FromObjectAsJson(tokenBody), new AttestationTokenSigningKey(privateKey, fullCertificate));
            string serializedToken = token.Serialize();

            await ValidateSerializedToken(serializedToken, tokenBody);
        }
Пример #7
0
        public async Task SetPolicyUnsecuredAad()
        {
            var adminclient = TestEnvironment.GetAadAdministrationClient(this);

            // Reset the current attestation policy to a known state. Necessary if there were previous runs that failed.
            await ResetAttestationPolicy(adminclient, AttestationType.OpenEnclave, false, false);

            string originalPolicy;

            {
                originalPolicy = await adminclient.GetPolicyAsync(AttestationType.OpenEnclave);
            }

            byte[] disallowDebuggingHash;
            {
                var policySetResult = await adminclient.SetPolicyAsync(AttestationType.OpenEnclave, disallowDebugging);

                // The SetPolicyAsync API will create an UnsecuredAttestationToken to transmit the policy.
                var shaHasher      = SHA256.Create();
                var policySetToken = new AttestationToken(BinaryData.FromObjectAsJson(new StoredAttestationPolicy {
                    AttestationPolicy = disallowDebugging
                }));

                disallowDebuggingHash = shaHasher.ComputeHash(Encoding.UTF8.GetBytes(policySetToken.Serialize()));

                Assert.AreEqual(200, policySetResult.GetRawResponse().Status);
                Assert.AreEqual(PolicyModification.Updated, policySetResult.Value.PolicyResolution);
                CollectionAssert.AreEqual(disallowDebuggingHash, policySetResult.Value.PolicyTokenHash.ToArray());
            }

            {
                string policyResult = await adminclient.GetPolicyAsync(AttestationType.OpenEnclave);

                Assert.AreEqual(disallowDebugging, policyResult);
            }
            {
                var policySetResult = await adminclient.ResetPolicyAsync(AttestationType.OpenEnclave);

                Assert.AreEqual(200, policySetResult.GetRawResponse().Status);
                Assert.AreEqual(PolicyModification.Removed, policySetResult.Value.PolicyResolution);
            }

            {
                var policyResult = await adminclient.GetPolicyAsync(AttestationType.OpenEnclave);

                // And when we're done, policy should be reset to the original value.
                Assert.AreEqual(originalPolicy, policyResult.Value);
            }
        }
Пример #8
0
        protected static GenericResourceData ConstructGenericAvailabilitySet()
        {
            var data = new GenericResourceData(AzureLocation.WestUS2);

            data.Sku = new ResourcesSku()
            {
                Name = "Aligned"
            };
            var propertyBag = new Dictionary <string, object>();

            propertyBag.Add("platformUpdateDomainCount", 5);
            propertyBag.Add("platformFaultDomainCount", 2);
            data.Properties = BinaryData.FromObjectAsJson(propertyBag);
            return(data);
        }
Пример #9
0
        protected static ArmDeploymentProperties CreateDeploymentProperties()
        {
            ArmDeploymentProperties tmpDeploymentProperties = new ArmDeploymentProperties(ArmDeploymentMode.Incremental);

            tmpDeploymentProperties.TemplateLink     = new ArmDeploymentTemplateLink();
            tmpDeploymentProperties.TemplateLink.Uri = new Uri("https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/quickstarts/microsoft.storage/storage-account-create/azuredeploy.json");
            tmpDeploymentProperties.Parameters       = BinaryData.FromObjectAsJson(new JsonObject()
            {
                { "storageAccountType", new JsonObject()
                  {
                      { "value", "Standard_GRS" }
                  } }
            });
            return(tmpDeploymentProperties);
        }
 public WebPubSubConnectionContext(WebPubSubEventType eventType, string eventName, string hub, string connectionId, string userId, string signature, string origin, IReadOnlyDictionary <string, object> states, IReadOnlyDictionary <string, string[]> headers)
     : this(
         eventType,
         eventName,
         hub,
         connectionId,
         userId,
         signature,
         origin,
         states?.ToDictionary(
             p => p.Key,
             p => p.Value as BinaryData ?? BinaryData.FromObjectAsJson(p.Value)),
         headers)
 {
 }
Пример #11
0
        public BinaryData GeneratePayload()
        {
            double currentTemperature = minTemperature + Random.Shared.NextDouble() * 15;
            double currentHumidity    = minHumidity + Random.Shared.NextDouble() * 20;

            object telemetryDataPoint = new
            {
                createdAt   = DateTime.UtcNow,
                deviceId    = "EventHubDevice" + Random.Shared.Next(1, 300000),
                temperature = currentTemperature,
                humidity    = currentHumidity,
            };

            return(BinaryData.FromObjectAsJson(telemetryDataPoint));
        }
        public async Task TestStateChanges()
        {
            _adaptor.RegisterHub <TestHub>();
            var initState = new Dictionary <string, BinaryData>
            {
                { "counter", BinaryData.FromObjectAsJson(2) }
            };
            var context = PrepareHttpContext(httpMethod: HttpMethods.Post, type: WebPubSubEventType.User, eventName: "message", body: "1", connectionState: initState);

            // 1 to update counter to 10.
            await _adaptor.HandleRequest(context);

            context.Response.Headers.TryGetValue(Constants.Headers.CloudEvents.State, out var states);
            Assert.NotNull(states);
            var updated = states[0].DecodeConnectionStates();

            Assert.AreEqual(1, updated.Count);
            Assert.AreEqual(10, updated["counter"].ToObjectFromJson <int>());

            // 2 to add a new state.
            context = PrepareHttpContext(httpMethod: HttpMethods.Post, type: WebPubSubEventType.User, eventName: "message", body: "2", connectionState: initState);
            _adaptor.RegisterHub <TestHub>();
            await _adaptor.HandleRequest(context);

            context.Response.Headers.TryGetValue(Constants.Headers.CloudEvents.State, out states);
            Assert.NotNull(states);
            updated = states[0].DecodeConnectionStates();
            Assert.AreEqual(2, updated.Count);
            Assert.AreEqual("new", updated["new"].ToObjectFromJson <string>());

            // 3 to clear states
            context = PrepareHttpContext(httpMethod: HttpMethods.Post, type: WebPubSubEventType.User, eventName: "message", body: "3", connectionState: initState);
            await _adaptor.HandleRequest(context);

            var exist = context.Response.Headers.TryGetValue(Constants.Headers.CloudEvents.State, out _);

            Assert.False(exist);

            // 4 clar and add
            context = PrepareHttpContext(httpMethod: HttpMethods.Post, type: WebPubSubEventType.User, eventName: "message", body: "4", connectionState: initState);
            await _adaptor.HandleRequest(context);

            context.Response.Headers.TryGetValue(Constants.Headers.CloudEvents.State, out states);
            Assert.NotNull(states);
            updated = states[0].DecodeConnectionStates();
            Assert.AreEqual(2, updated.Count);
            Assert.AreEqual("new1", updated["new1"].ToObjectFromJson <string>());
        }
        public async Task GetSecuredAttestationTokenWithPrivateKey()
        {
            X509Certificate2 fullCertificate = TestEnvironment.PolicyManagementCertificate;

            fullCertificate.PrivateKey = TestEnvironment.PolicyManagementKey;

            // The body of attestation token MUST be a JSON object.
            TestBody body = new TestBody {
                StringField = "Foo",
            };

            var    token           = new AttestationToken(BinaryData.FromObjectAsJson(body), new AttestationTokenSigningKey(fullCertificate));
            string serializedToken = token.Serialize();

            await ValidateSerializedToken(serializedToken, body);
        }
        public void TestEncodeAndDecodeState()
        {
            var state = new Dictionary <string, BinaryData>
            {
                { "aaa", BinaryData.FromObjectAsJson("aaa") },
                { "bbb", BinaryData.FromObjectAsJson("bbb") }
            };

            var encoded = state.EncodeConnectionStates();

            var decoded = encoded.DecodeConnectionStates();

            CollectionAssert.AreEquivalent(
                state.Values.Select(d => d.ToObjectFromJson <string>()),
                decoded.Values.Select(d => d.ToObjectFromJson <string>()));
        }
Пример #15
0
 protected static ArmApplicationData CreateApplicationData(ResourceIdentifier applicationDefinitionId, ResourceIdentifier managedResourceGroupId, string storageAccountPrefix) => new ArmApplicationData(AzureLocation.WestUS2, "ServiceCatalog")
 {
     ApplicationDefinitionId = applicationDefinitionId,
     ManagedResourceGroupId  = managedResourceGroupId,
     Parameters = BinaryData.FromObjectAsJson(new JsonObject()
     {
         { "storageAccountNamePrefix", new JsonObject()
           {
               { "value", storageAccountPrefix }
           } },
         { "storageAccountType", new JsonObject()
           {
               { "value", "Standard_LRS" }
           } }
     })
 };
Пример #16
0
 public void CreateVmExtension()
 {
     #region Snippet:Changelog_CreateVMExtension
     var vmExtension = new VirtualMachineExtensionData(AzureLocation.WestUS)
     {
         Tags = { { "extensionTag1", "1" }, { "extensionTag2", "2" } },
         Publisher = "Microsoft.Compute",
         ExtensionType = "VMAccessAgent",
         TypeHandlerVersion = "2.0",
         AutoUpgradeMinorVersion = true,
         ForceUpdateTag = "RerunExtension",
         Settings = BinaryData.FromObjectAsJson(new { }),
         ProtectedSettings = BinaryData.FromObjectAsJson(new { })
     };
     #endregion
 }
        public async Task ValidateJustExpiredAttestationToken()
        {
            // Create a JWT whose body has just expired.
            object tokenBody = new JwtTestBody {
                StringField = "Foo",
                ExpiresAt   = DateTimeOffset.Now.Subtract(TimeSpan.FromSeconds(5)).ToUnixTimeSeconds(),
            };

            var    token           = new AttestationToken(BinaryData.FromObjectAsJson(tokenBody));
            string serializedToken = token.Serialize();

            // This check should fail since the token expired 5 seconds ago.
            Assert.ThrowsAsync(typeof(Exception), async() => await ValidateSerializedToken(serializedToken, tokenBody));

            // This check should succeed since the token slack is greater than the 5 second expiration time.
            await ValidateSerializedToken(serializedToken, tokenBody, new AttestationTokenValidationOptions { TimeValidationSlack = 10 });
        }
Пример #18
0
        public async Task WriteToBlob(
            BlobContainerClient client,
            string blobName,
            object content)
        {
            var blob = client.GetBlobClient(blobName);

            if (_useCompression)
            {
                var serializedContent = AvroConvert.Serialize(content);
                await blob.UploadAsync(new BinaryData(serializedContent));
            }
            else
            {
                await blob.UploadAsync(BinaryData.FromObjectAsJson(content));
            }
        }
        // WEIRD: second level resources cannot use GenericResourceCollection to create.
        // Exception thrown: System.InvalidOperationException : An invalid resource id was given /subscriptions/db1ab6f0-4769-4b27-930e-01e2ef9c123c/resourceGroups/testRG-4544/providers/Microsoft.Network/virtualNetworks/testVNet-9796/subnets/testSubnet-1786
        private async Task <GenericResource> CreateSubnet(ResourceIdentifier vnetId)
        {
            var subnetName = Recording.GenerateAssetName("testSubnet-");
            ResourceIdentifier subnetId = new ResourceIdentifier($"{vnetId}/subnets/{subnetName}");
            var input = new GenericResourceData(DefaultLocation)
            {
                Properties = BinaryData.FromObjectAsJson(new Dictionary <string, object>()
                {
                    { "addressPrefixes", new List <string>()
                      {
                          "10.0.2.0/24"
                      } }
                })
            };
            var operation = await _genericResourceCollection.CreateOrUpdateAsync(WaitUntil.Completed, subnetId, input);

            return(operation.Value);
        }
Пример #20
0
        protected static ArmDeploymentProperties CreateDeploymentPropertiesAtSub()
        {
            ArmDeploymentProperties tmpDeploymentProperties = new ArmDeploymentProperties(ArmDeploymentMode.Incremental);

            tmpDeploymentProperties.TemplateLink     = new ArmDeploymentTemplateLink();
            tmpDeploymentProperties.TemplateLink.Uri = new Uri("https://raw.githubusercontent.com/Azure/azure-docs-json-samples/master/azure-resource-manager/emptyrg.json");
            tmpDeploymentProperties.Parameters       = BinaryData.FromObjectAsJson(new JsonObject()
            {
                { "rgName", new JsonObject()
                  {
                      { "value", "testDeployAtSub" }
                  } },
                { "rgLocation", new JsonObject()
                  {
                      { "value", $"{AzureLocation.CentralUS}" }
                  } },
            });
            return(tmpDeploymentProperties);
        }
Пример #21
0
        public void SerailizeUsingDictStringObject()
        {
            var expected = File.ReadAllText(GetFileName("JsonFormattedString.json")).TrimEnd();

            var payload = new ModelWithBinaryData {
                A = "a.value"
            };
            var properties      = new Dictionary <string, object>();
            var innerProperties = new Dictionary <string, object>();

            properties.Add("a", "properties.a.value");
            innerProperties.Add("a", "properties.innerProperties.a.value");
            properties.Add("innerProperties", innerProperties);
            payload.Properties = BinaryData.FromObjectAsJson(properties);

            string actual = GetSerializedString(payload);

            Assert.AreEqual(expected, actual);
        }
Пример #22
0
        private GenericResourceData ConstructGenericVirtualNetworkData()
        {
            var properties = new JsonObject()
            {
                { "addressSpace", new JsonObject()
                  {
                      { "addressPrefixes", new List <string>()
                        {
                            "10.0.0.0/16"
                        } }
                  } }
            };
            var virtualNetwork = new GenericResourceData(AzureLocation.WestUS2)
            {
                Properties = BinaryData.FromObjectAsJson(properties),
            };

            return(virtualNetwork);
        }
        public void TestConnectionStatesConverter_SystemText()
        {
            var jsonOption = new SystemJson.JsonSerializerOptions();

            jsonOption.Converters.Add(new ConnectionStatesConverter());
            IReadOnlyDictionary <string, BinaryData> input =
                new Dictionary <string, BinaryData>
            {
                { "aKey", BinaryData.FromString("aValue") },
                { "bKey", BinaryData.FromObjectAsJson(123) },
                { "cKey", BinaryData.FromObjectAsJson(new StateTestClass()) }
            };
            var serialized   = SystemJson.JsonSerializer.Serialize(input, jsonOption);
            var deserialized = SystemJson.JsonSerializer.Deserialize <IReadOnlyDictionary <string, BinaryData> >(serialized, jsonOption);

            Assert.AreEqual(3, deserialized.Count);
            Assert.AreEqual("aValue", deserialized["aKey"].ToString());
            Assert.AreEqual(123, deserialized["bKey"].ToObjectFromJson <int>());
        }
Пример #24
0
        public static async Task <IActionResult> RunAsync(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = Constants.Routes.EventConfigs)] HttpRequest req,
            ILogger log,
            CancellationToken cancellationToken)
        {
            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            var    entity      = JsonConvert.DeserializeObject <PseudoEvent>(requestBody);

            if (entity == null)
            {
                return(new BadRequestResult());
            }

            var timestamp = entity.EventTimestamp.AddMinutes(-entity.LeadTimeInMinutes);

            if (timestamp < DateTimeOffset.UtcNow)
            {
                return(new NoContentResult());
            }

            var payload = new EventDispatchTrigger
            {
                DispatchedAt = DateTimeOffset.UtcNow,
                Payload      = entity,
                PayloadType  = nameof(PseudoEvent),
                EntityId     = entity.Id.ToString(),
                EntityTag    = DateTimeOffset.UtcNow.ToString("O") // For Cosmos DB entities this could be the ETag value
            };

            var message = new ServiceBusMessage
            {
                Subject       = nameof(EventDispatchTrigger),
                MessageId     = entity.Id.ToString(),
                Body          = BinaryData.FromObjectAsJson(payload),
                ContentType   = "application/json",
                CorrelationId = Guid.NewGuid().ToString()
            };

            await FunctionHelper.ScheduleTrigger(message, timestamp, log, cancellationToken);

            return(new OkResult());
        }
Пример #25
0
 private static PolicyDefinitionData ConstructPolicyDefinitionData(string displayName) => new PolicyDefinitionData
 {
     DisplayName = $"Test ${displayName}",
     PolicyRule  = BinaryData.FromObjectAsJson(new Dictionary <string, object>
     {
         {
             "if", new Dictionary <string, object>
             {
                 { "source", "action" },
                 { "equals", "ResourceProviderTestHost/TestResourceType/TestResourceTypeNestedOne/write" }
             }
         },
         {
             "then", new Dictionary <string, object>
             {
                 { "effect", "deny" }
             }
         }
     })
 };
        public void CanSerializeNullData()
        {
            BinaryData data = new BinaryData(jsonSerializable: null);

            Assert.Null(data.ToObjectFromJson <object>());
            data = BinaryData.FromObjectAsJson <object>(null);
            Assert.Null(data.ToObjectFromJson <object>());

            data = new BinaryData(jsonSerializable: null, type: typeof(TestModel));
            Assert.Null(data.ToObjectFromJson <TestModel>());

            data = new BinaryData(jsonSerializable: null);
            Assert.Null(data.ToObjectFromJson <TestModel>());

            data = new BinaryData(jsonSerializable: null, type: null);
            Assert.Null(data.ToObjectFromJson <TestModel>());

            data = BinaryData.FromObjectAsJson <TestModel>(null);
            Assert.Null(data.ToObjectFromJson <TestModel>());
        }
        public void CanSerializeBaseType()
        {
            DerivedModel payload = new DerivedModel {
                A = "value", B = 5, C = true, D = null, E = "derived property"
            };

            BinaryData data = new BinaryData(jsonSerializable: payload, type: typeof(TestModel));

            Assert.Null(data.ToObjectFromJson <DerivedModel>().E);

            data = new BinaryData(jsonSerializable: payload, type: typeof(DerivedModel));
            Assert.Equal("derived property", data.ToObjectFromJson <DerivedModel>().E);

            data = new BinaryData(jsonSerializable: payload);
            Assert.Equal("derived property", data.ToObjectFromJson <DerivedModel>().E);

            data = BinaryData.FromObjectAsJson <TestModel>(payload);
            Assert.Null(data.ToObjectFromJson <DerivedModel>().E);

            data = BinaryData.FromObjectAsJson <DerivedModel>(payload);
            Assert.Equal("derived property", data.ToObjectFromJson <DerivedModel>().E);
        }
        public void TestConnectionStatesEncodeDecode()
        {
            var testTime = DateTime.Parse("2021-11-10 4:23:55");
            var input    =
                new Dictionary <string, object>
            {
                { "aKey", BinaryData.FromString("aValue") },
                { "bKey", BinaryData.FromObjectAsJson(123) },
                { "cKey", BinaryData.FromObjectAsJson(new StateTestClass()) },
                { "dKey", JObject.FromObject(new StateTestClass()) },
                { "eKey", BinaryData.FromObjectAsJson(testTime) }
            };
            var encoded = input.EncodeConnectionStates();
            var decoded = encoded.DecodeConnectionStates();

            Assert.AreEqual(5, decoded.Count);
            Assert.AreEqual("aValue", decoded["aKey"].ToString());
            Assert.AreEqual(123, ((BinaryData)decoded["bKey"]).ToObjectFromJson <int>());
            Assert.NotNull(((BinaryData)decoded["cKey"]).ToObjectFromJson <StateTestClass>());
            Assert.NotNull(((BinaryData)decoded["dKey"]).ToObjectFromJson <StateTestClass>());
            Assert.AreEqual(testTime, ((BinaryData)decoded["eKey"]).ToObjectFromJson <DateTime>());
        }
Пример #29
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 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;
            }
        }
        public async Task ValidateTooEarlyAttestationToken()
        {
            // Create a JWT whose body will become valid 5 seconds from now.
            object tokenBody = new JwtTestBody
            {
                StringField = "Foo",
                NotBefore   = DateTimeOffset.Now.AddSeconds(5).ToUnixTimeSeconds(),
                ExpiresAt   = DateTimeOffset.Now.AddSeconds(60).ToUnixTimeSeconds(),
            };

            X509Certificate2    fullCertificate = TestEnvironment.PolicyManagementCertificate;
            AsymmetricAlgorithm privateKey      = TestEnvironment.PolicyManagementKey;

            var    token           = new AttestationToken(BinaryData.FromObjectAsJson(tokenBody), new AttestationTokenSigningKey(privateKey, fullCertificate));
            string serializedToken = token.Serialize();

            // This check should fail since the token won't be valid for another 5 seconds.
            Assert.ThrowsAsync(typeof(Exception), async() => await ValidateSerializedToken(serializedToken, tokenBody));

            // This check should succeed since the token slack is greater than the 10 seconds before it becomes valid.
            await ValidateSerializedToken(serializedToken, tokenBody, new AttestationTokenValidationOptions { TimeValidationSlack = 10 });
        }