-
Notifications
You must be signed in to change notification settings - Fork 486
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add support for Azure Key Vault secrets (#3112)
- Loading branch information
Showing
9 changed files
with
193 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
15 changes: 15 additions & 0 deletions
15
.../chezmoi.io/docs/reference/templates/azure-key-vault-functions/azureKeyVault.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# `azureKeyVault` *secret name* [*vault-name*] | ||
|
||
`azureKeyVault` returns a secret value retrieved from an | ||
[Azure Key Vault](https://learn.microsoft.com/en-us/azure/key-vault/general/). | ||
|
||
The mandatory `secret name` argument specifies the *name of the secret* to | ||
retrieve. | ||
|
||
The optional `vault name` argument specifies the *name of the vault*, if not set, | ||
the default vault name will be used. | ||
|
||
!!! warning | ||
|
||
The current implementation will always return the latest version of the secret. | ||
Retrieving a specific version of a secret is not supported. |
50 changes: 50 additions & 0 deletions
50
assets/chezmoi.io/docs/user-guide/password-managers/azure-key-vault.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
# Azure Key Vault | ||
|
||
chezmoi includes support for [Azure Key Vault secrets](https://learn.microsoft.com/en-us/azure/key-vault/secrets/about-secrets). | ||
|
||
A default Azure Key Vault name can be set in `~/.config/chezmoi/chezmoi.toml` with | ||
`azureKeyVault.defaultVault`. | ||
|
||
Ensure [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli) is installed and | ||
[log in](https://learn.microsoft.com/en-us/azure/developer/go/azure-sdk-authentication?tabs=bash#azureCLI). | ||
The logged in user must have the `Key Vault Secrets User` RBAC role on the Azure Key Vault resource. | ||
|
||
Alternatively, use alternate [authentication options](https://learn.microsoft.com/en-us/azure/developer/go/azure-sdk-authentication?tabs=bash#2-authenticate-with-azure). | ||
|
||
|
||
```toml title="~/.config/chezmoi/chezmoi.toml" | ||
[azureKeyVault] | ||
defaultVault = "contoso-vault2" | ||
``` | ||
|
||
A secret value can be retrieved with the `azureKeyVault` template function. | ||
|
||
Retrieve the secret `my-secret-name` from the default configured vault. | ||
|
||
``` | ||
exampleSecret = {{ azureKeyVault "my-secret-name" }} | ||
``` | ||
|
||
Retrieve the secret `my-secret-name` from the vault named `contoso-vault2`. | ||
|
||
``` | ||
exampleSecret = {{ azureKeyVault "my-secret-name" "contoso-vault2" }} | ||
``` | ||
|
||
It is also possible to define an alias in the configuration file for an | ||
additional vault. | ||
|
||
```toml title="~/.config/chezmoi/chezmoi.toml" | ||
[data] | ||
vault42 = "contoso-vault42" | ||
|
||
[azureKeyVault] | ||
defaultVault = "contoso-vault2" | ||
``` | ||
|
||
Retrieve the secret `my-secret-name` from the vault named `contoso-vault42` | ||
through the alias. | ||
|
||
``` | ||
exampleSecret = {{ azureKeyVault "my-secret-name" .vault42 }} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
package cmd | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/Azure/azure-sdk-for-go/sdk/azidentity" | ||
"github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets" | ||
) | ||
|
||
type azureKeyVault struct { | ||
client *azsecrets.Client | ||
cache map[string]string | ||
} | ||
|
||
func (v *azureKeyVault) URL(vaultName string) string { | ||
return fmt.Sprintf("https://%s.vault.azure.net/", vaultName) | ||
} | ||
|
||
type azureKeyVaultConfig struct { | ||
DefaultVault string `json:"defaultVault" mapstructure:"defaultVault" yaml:"defaultVault"` | ||
vaults map[string]*azureKeyVault | ||
cred *azidentity.DefaultAzureCredential | ||
} | ||
|
||
func (a *azureKeyVaultConfig) GetSecret(secretName, vaultName string) string { | ||
var err error | ||
|
||
if a.vaults == nil { | ||
a.vaults = make(map[string]*azureKeyVault) | ||
} | ||
|
||
if _, ok := a.vaults[vaultName]; !ok { | ||
a.vaults[vaultName] = &azureKeyVault{} | ||
} | ||
|
||
if secret, ok := a.vaults[vaultName].cache[secretName]; ok { | ||
return secret | ||
} | ||
|
||
if a.cred == nil { | ||
a.cred, err = azidentity.NewDefaultAzureCredential(nil) | ||
if err != nil { | ||
panic(err) | ||
} | ||
} | ||
|
||
if a.vaults[vaultName].client == nil { | ||
a.vaults[vaultName].client, err = azsecrets.NewClient( | ||
a.vaults[vaultName].URL(vaultName), | ||
a.cred, | ||
nil, | ||
) | ||
|
||
if err != nil { | ||
panic(err) | ||
} | ||
} | ||
|
||
resp, err := a.vaults[vaultName].client.GetSecret(context.TODO(), secretName, "", nil) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
if a.vaults[vaultName].cache == nil { | ||
a.vaults[vaultName].cache = make(map[string]string) | ||
} | ||
|
||
a.vaults[vaultName].cache[secretName] = *resp.Value | ||
|
||
return *resp.Value | ||
} | ||
|
||
func (c *Config) azureKeyVaultTemplateFunc(args ...string) string { | ||
var secretName, vaultName string | ||
|
||
switch len(args) { | ||
case 1: | ||
if c.AzureKeyVault.DefaultVault == "" { | ||
panic(fmt.Errorf("no value set in azureKeyVault.defaultVault")) | ||
} | ||
secretName, vaultName = args[0], c.AzureKeyVault.DefaultVault | ||
case 2: | ||
secretName, vaultName = args[0], args[1] | ||
default: | ||
panic(fmt.Errorf("expected 1 or 2 arguments, got %d", len(args))) | ||
} | ||
|
||
return c.AzureKeyVault.GetSecret(secretName, vaultName) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters