Managing and Rotating Secrets with Azure Key Vault, Managed Services, and some automation – Part 2

Published 10-26-2020 09:43 AM 3,967 Views

In the previous post I discussed the bigger picture for Harpocrates’ existence and goals. In this post, I will begin by diving into the constructs defined by Harpocrates and how they can be leveraged to achieve the desired configuration for your environment.


As discussed before, Harpocrates addresses the need for a periodic rotation of secrets. And as such, we need a primitive to describe this “period”. To allow for support of other governing constructs in the future, Harpocrates utilizes a concept of a “Policy”. This primitive is meant to enable the system administrator to define a set of time-based rotation intervals that can then be applied to other constructs in the system. At the time of writing of this post, the Policy is used solely to define a rotation interval, though it could be extended to add additional governing properties.


Policies are applied to specific services. This means that a specific storage account can have a “15-day” rotation policy, while another one can have a “90-day” policy applied to it. This enables the administrator to describe how frequently a particular service needs to have its credentials rotated. This brings us to the next primitive: “Service”.


A “Service” primitive is used to describe a specific service you want Harpocrates to manage. For example, you may want to enable Harpocrates to rotate keys for “Storage Account A”, and as such, you would create a “Service” definition for such service. “Service” definition would also provide additional metadata about the given service, such as the type of the service this is (i.e. storage account, cosmosdb account, Redis cache, etc); and lastly, a “Service” will be configured w/ a “connection string” that would describe how this particular service could be managed by the secret management provider. In most cases, this connection string would simply contain a resource group and the service uri. However, it is possible to add additional tokens to this piece of metadata, as long as the syntax used to define it is understood by the respective secret management provided. For example, for Azure Storage Account secret management provider, the connection string looks like this: “AccountEndpoint=;ResourceGroup=myrg;”. If you had extended the secret management provider by adding your own custom provider, the connection string used to configure such service would simply need to match the syntax your customer provider knows how to interpret. At the time of writing of this article, “Service” configuration information is not encrypted, therefore you should avoid storing secrets with its definitions.


Harpocrates uses Azure Key Vault as the secure store for service secrets as well as the eventing mechanism to signal when a specific secret is to be rotated. In Key Vault, secrets are identified by a unique Uri. Here’s an example of a Uri for KV Secret named “my-secret”:{version id}. Since each KV secret has a unique, well defined uri, we can use that Uri to correlate secrets stored in KV to the services we defined in Harpocrates. To do this, we need a third primitive: “Secret”. As you have probably guessed, “Secret” will provide “mapping information”, allowing Harpocrates to “translate” a KV uri to a service we are trying to manage. In addition to this important piece of information, a “Secret” also contains information about the “type” of secret it is, as well as the format in which this secret is to be stored in KV (more on this later). There are currently two types of secrets supported by Harpocrates: Attached & Dependency.


“Attached” secrets represent the entries in KV that store raw values of the downstream service secret. For example, when creating management metadata for “StorageAccountA”, one would create a Key Vault secret named “my-storage-account-a-master-key”. This KV Secret would be associated with a Harpocrates “Secret” “StorageAccountASecret” that would in turn be associated with the “StorageAccountA” service definition and be of type “Attached”. Since “StorageAccountA” service definition is associated with a particular “Policy”, that policies will be used to set the expiration date of the key vault secret named “my-storage-account-a-master-key”, and as such, would cause this secret to expire, firing a KV event that Harpocrates can respond to by rotating the storage account key & updating the associated KV secret. The above described flow is depicted below:



Figure 1 “Attached” secret process flow


“Dependency” secrets represent entries in Key Vault that depend on the value of another secret. This type of a secret would typically be used to define a secret consumed by an application that needs credentials to access one of the services managed by Harpocrates. Most application do not store secrets in plain form but rather use a specific format, such as a connection string. In a typical application, one would likely see a configuration entry in a form of a database connection string, rather than multiple entries each representing the: server name, username, user password, etc. As such, “Dependency” secrets support a concept of a Format Expression. When setting up a “Dependency” secret, a system admin would provide Harpocrates with an expression that matches the expectations of the consuming application and may look something like this: “Server={{server-secret-id}};User={{user-secret-id}};Password={{password-secret-id}}”. The values specified in the “{{“ “}}” are system generated ids of the secrets managed by Harpocrates that can be resolved at time of dependency update, thus allowing the actual KV secret value to be: “Server=myDbServer;User=MyDbUserName;Password=P@ssword@1”.

Now that we have the language to describe a Policy, Service, and Secrete, we need one last construct to simplify the dependency secret resolution: Secret Dependency. This is not as much of a primitive as just a relationship that is defined within the system. When a secret has dependencies and that secret has its associated service keys rotated, the system can schedule updates to all other secrets that depend on it. Since dependencies do not technically require that they depend on “attached” secrets, one could design an extensive cascading secret rotation strategy to be executed by Harpocrates. The above described flow is depicted in the diagram below:



Figure 2 “Dependency” secret process flow


Now that we have the vocabulary required to describe the behavior we want Harpocrates to automate, we can discuss the runtime requirements and assumptions made by Harpocrates. We will do this in the next installment of this blog series. As always, your feedback is welcomed and greatly appreciated.


Version history
Last update:
‎Oct 26 2020 09:43 AM
Updated by: