I am using API Management consumption tier and taking an approach to pull a shared secret out of Azure KeyVault and store in a cache to minimise key vault lookups.
The approach I am taking is very similar to the following :
[https://blog.eldert.net/implementing-smart-caching-of-secrets-in-azure-api-management-policies/][1]
Since we are using the consumption tier, I needed to configure API Management to use an external (Azure Redis cache) to avail of caching.
We are already have deployed an Azure Redis cache instance for other non APIM parts of our cloud architecture so that was convenient.
I can shared parts of the APIM ARM template if that helps.
I am providing a snippet of the inbound policy definition that we are using to check the cache, pull a secret from key vault if cache misses.
I've set a long TTL onto the cache entry.
What I am seeing is 2 things.
1. The key doesn't end up as apimSharedSecret in Redis - it is consistently written to cache as 2_apimSharedSecret (checked this via SCAN 0 on the Azure Redis console )
2. The value written to the cache has several non-printable byte/chars before the actual secret as a sort of preamble followed by the value we are putting in via cache-store-value
This is very surprising. I have not attempted to try this on one of the non consumption tiers (using inbuilt cache).
I am working around this now by retrieving the cache value in Azure function app by matching the key lookup as 2_apimSharedSecret.
Also, I am using C# regex to split out the preamble and I've prefixed our actual secret with a distinct anchoring string so that I skip over these bizarre preambly characters in the secret pulled out of Redis.
When running the test on the APIM operation(s) the testing trace log in APIM shows 2_apimSharedSecret as the key in the trace for cache-get-value as well as cache-set-value and in cache-set-value it shows the value being stored to cache as the secret value pulled from the keyvault with no non-printable preamble characters.
I am looking for pointers as to whether what I am seeing is expected in terms of how APIM integrates with Redis or whether I may have possibly mis-configured something in deploying the APIM resource.
Inbound policy snippet given below (the KeyVault URL is fictitious in my example below)
<cache-lookup-value key="apimSecret" variable-name="processedSecret" />
<choose>
<when condition="@(!context.Variables.ContainsKey("processedSecret"))">
<!-- Retrieve secret from Key Vault -->
<send-request mode="new" response-variable-name="cached-secret" timeout="20" ignore-error="false">
<set-url>https://dev-foobar-kv.vault.azure.net/secrets/SharedSecret/?api-version=7.0</set-url>
<set-method>GET</set-method>
<authentication-managed-identity resource="https://vault.azure.net" />
</send-request>
<!-- Store response body in context variable as a string -->
<set-variable name="processedSecret" value="@((string)((IResponse)context.Variables["cached-secret"]).Body.As<JObject>()["value"])" />
<!-- Store result in cache -->
<cache-store-value key="apimSecret" value="@((string)context.Variables["processedSecret"])" duration="1200000" />
</when>
</choose>
<set-header name="Apim-Secret" exists-action="override">
<value>@((string)context.Variables["processedSecret"])</value>
</set-header>