Azure / Azure/azure-functions-host
Function Key Management API is not case-sensitive , causing 404 as well as previous key overridden
- Dominant language
- C#
- Stars
- 2k
- Forks
- 482
- Avg merge
- 2d 10h
- Merged PRs (30d)
- 36
Description
When using the Functions App Management API to get and set Function Keys ( https://[FunctionAppName].azurewebsites.net/admin/functions/[FunctionName]/keys/[KeyName] ) the In- and Output is caseSensitive, but the keys are overwritten if a key with the same name (not caseSensitive) already exists.
For example, if we want to look at two Function Keys: TestKey & testKey
See if key exists:
> GET https://[FunctionAppName].azurewebsites.net/admin/functions/[FunctionName]/keys/TestKey
--> Response: 404
Create key with captial 'T':
> POST https://[FunctionAppName].azurewebsites.net/admin/functions/[FunctionName]/keys/TestKey
--> Response: {..... TestKey}
See if Key exists now:
> GET https://[FunctionAppName].azurewebsites.net/admin/functions/[FunctionName]/keys/TestKey
--> Response: {..... TestKey}
See if Key with small 't' exists:
> GET https://[FunctionAppName].azurewebsites.net/admin/functions/[FunctionName]/keys/testKey
--> Response: 404
Create Key with small 't':
> POST https://[FunctionAppName].azurewebsites.net/admin/functions/[FunctionName]/keys/testKey
--> Response: {..... testKey}
See if both keys exist:
> GET https://[FunctionAppName].azurewebsites.net/admin/functions/[FunctionName]/keys/TestKey
--> Response: 404
> GET https://[FunctionAppName].azurewebsites.net/admin/functions/[FunctionName]/keys/testKey
--> Response: {... testKey}
_**Point to Note : if we create keys from Azure portal , then angular UI already takes care of that and doesn't allow to create duplicate keys irrespective of case/Ordinal.**_
#### Investigative information
-- POST mykey1
{"name":"mykey1","value":"jZMEduaHRZDDxC7P90MaYNGNmKjdMuq8ANaTd/UH7UVVB/5ZHAKMkQ==","links":[{"rel":"self","href":"https://fnzipdeploye.azurewebsites.net/admin/functions/HttpTriggerCSharp1/keys/mykey1"}]}
-- GET mykey1
{"name":"mykey1","value":"jZMEduaHRZDDxC7P90MaYNGNmKjdMuq8ANaTd/UH7UVVB/5ZHAKMkQ==","links":[{"rel":"self","href":"https://fnzipdeploye.azurewebsites.net/admin/functions/HttpTriggerCSharp1/keys/mykey1"}]}
-- GET KEYS
{"keys":[{"name":"abc","value":"/CMCsDahlK0dHTEjX12O4jqXbdx7llK0H0MgXhK55sy6a6X3H85vuw=="},
{"name":"my2","value":"rUPEOrpfH8LKhLRKVAAtb58aT0VP4egaGkST09j6TFbsMCjfDc1/VQ=="},
{"name":"my1","value":"G3xrlTWQy3NRMRYi7nVze5CALCuqdfcq1wesHxrPJPaM90ysRPTfZw=="},
{"name":"mykey1","value":"jZMEduaHRZDDxC7P90MaYNGNmKjdMuq8ANaTd/UH7UVVB/5ZHAKMkQ=="}],
"links":[{"rel":"self","href":"https://fnzipdeploye.azurewebsites.net/admin/functions/HttpTriggerCSharp1/keys/"}]}
-- POST Mykey1
{"name":"Mykey1","value":"Ii0ReLaxsdp4mNw7ooV4ENSb71e0NCZP85EhNe2vDhyzVtTUJoVs1A==","links":[{"rel":"self","href":"https://fnzipdeploye.azurewebsites.net/admin/functions/HttpTriggerCSharp1/keys/Mykey1"}]}
-- GET Mykey1
{"name":"Mykey1","value":"Ii0ReLaxsdp4mNw7ooV4ENSb71e0NCZP85EhNe2vDhyzVtTUJoVs1A==","links":[{"rel":"self","href":"https://fnzipdeploye.azurewebsites.net/admin/functions/HttpTriggerCSharp1/keys/Mykey1"}]}
-- GET KEYS
{"keys":[{"name":"abc","value":"/CMCsDahlK0dHTEjX12O4jqXbdx7llK0H0MgXhK55sy6a6X3H85vuw=="},
{"name":"my2","value":"rUPEOrpfH8LKhLRKVAAtb58aT0VP4egaGkST09j6TFbsMCjfDc1/VQ=="},
{"name":"my1","value":"G3xrlTWQy3NRMRYi7nVze5CALCuqdfcq1wesHxrPJPaM90ysRPTfZw=="},
{"name":"Mykey1","value":"Ii0ReLaxsdp4mNw7ooV4ENSb71e0NCZP85EhNe2vDhyzVtTUJoVs1A=="}],"links":[{"rel":"self","href":"https://fnzipdeploye.azurewebsites.net/admin/functions/HttpTriggerCSharp1/keys"}]}
-- GET mykey1
returns 404.
#### Expected behavior
1) Either should say that Key already exist and doesn't let create key using POST.
2)OR , if we want to maintain both keys , then it should not remove previous key from collection.
#### Related information in source Code
`[HttpPost]
[Route("admin/functions/{name}/keys/{keyName}")]
public Task Post(string name, string keyName) => AddOrUpdateSecretAsync(keyName, null, name, ScriptSecretsType.Function);`
**this internally calls , which is actually creating this new Key with case changed , but at the same time seems to be deleting old key.**
```
private async Task AddOrUpdateSecretAsync(ScriptSecretsType secretsType, string keyScope, string secretName, string secret, Func secretsFactory)
{
OperationResult result = OperationResult.NotFound;
secret = secret ?? GenerateSecret();
await ModifyFunctionSecretsAsync(secretsType, keyScope, secrets =>
{
Key key = secrets.GetFunctionKey(secretName, keyScope);
var createAndUpdateKey = new Action((o) =>
{
var newKey = CreateKey(secretName, secret);
secrets.AddKey(newKey, keyScope);
result = o;
});
if (key == null)
{
createAndUpdateKey(OperationResult.Created);
}
else if (secrets.RemoveKey(key, keyScope))
{
createAndUpdateKey(OperationResult.Updated);
}
return secrets;
}, secretsFactory);
return new KeyOperationResult(secret, result);
}
````
**Expectation :**
1) If we want to keep this thing case sensitive, then both key should exist.
2) we don’t want it to be case sensitive, then do not delete previous key from keys collection & then irrespective of key cases, the key should be retrieved and should not throw 404.
Contributor guide
Assessment
This issue has not been assessed yet.