public void GetUrl_GeneratesIdentifiableSystemSecret() { string secretValue = string.Empty; var webHookProvider = CreateDefaultScriptWebHookProvider(out Mock <ISecretManager> mockSecretManager, out HostSecretsInfo hostSecrets); mockSecretManager.Setup(p => p.GetHostSecretsAsync()).ReturnsAsync(hostSecrets); mockSecretManager.Setup(p => p.AddOrUpdateFunctionSecretAsync( "testextension_extension", It.IsAny <string>(), HostKeyScopes.SystemKeys, ScriptSecretsType.Host)) .Callback <string, string, string, ScriptSecretsType>((key, secret, scope, type) => secretValue = secret) .Returns(() => Task.FromResult(new KeyOperationResult(secretValue, OperationResult.Created))); // When an extension has no existing secret, one should be generated using // the Azure Functions system key seed and standard fixed signature. var configProvider = new TestExtensionConfigProvider(); var url = webHookProvider.GetUrl(configProvider); Assert.Equal($"{TestUrlRoot}{secretValue}", url.ToString()); Assert.True(IdentifiableSecrets.ValidateBase64Key(secretValue, SecretGenerator.SystemKeySeed, SecretGenerator.AzureFunctionsSignature, encodeForUrl: true)); }
internal static void ValidateSecret(string secret, ulong seed) { Assert.True(IdentifiableSecrets.ValidateBase64Key(secret, seed, SecretGenerator.AzureFunctionsSignature, encodeForUrl: true)); // Strictly speaking, these tests shouldn't be required, failure // would indicate a bug in the Microsoft.Security.Utilities API itself // Still, this is a new dependency, so we'll do some sanity checking. // Azure Function secrets are base64-encoded using a URL friendly character set. // These tokens therefore never include the '+' or '/' characters. Assert.False(secret.Contains('+')); Assert.False(secret.Contains('/')); // All Azure function keys are 40 bytes in length, 56 base64-encoded chars. Assert.True(secret.Length == 56); Assert.True(Base64UrlEncoder.DecodeBytes(secret).Length == 40); ulong[] testSeeds = new[] { uint.MinValue, uint.MaxValue, SecretGenerator.SystemKeySeed, SecretGenerator.MasterKeySeed, SecretGenerator.FunctionKeySeed, }; // Verify that validation fails for incorrect seed values. foreach (ulong testSeed in testSeeds) { if (testSeed == seed) { // We looked at this one already. continue; } Assert.False(IdentifiableSecrets.ValidateBase64Key(secret, testSeed, SecretGenerator.AzureFunctionsSignature, encodeForUrl: true)); } // Validate that validation fails for an incorrect signature. Assert.False(IdentifiableSecrets.ValidateBase64Key(secret, seed, "XXXX", encodeForUrl: true)); }