Skip to content

Commit

Permalink
add azureKeyVaultSecretVersions
Browse files Browse the repository at this point in the history
Signed-off-by: Markus Blaschke <[email protected]>
  • Loading branch information
mblaschke committed Aug 23, 2023
1 parent 3d71897 commit f1d341f
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 6 deletions.
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,11 @@ Arguments:
| `azVirtualNetworkSubnetAddressPrefixes` | `resourceID` (string), `subnetName` (string) | Fetches address prefix (string array) from Azure VirtualNetwork subnet |

### Azure Keyvault functions
| Function | Parameters | Description |
|------------------------|--------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------|
| `azKeyVaultSecret` | `vaultUrl` (string), `secretName` (string), `version` (string, optional) | Fetches secret object from Azure KeyVault |
| `azKeyVaultSecretList` | `vaultUrl` (string), `secretNamePattern` (string, regexp) | Fetche the list of secret objects (without secret value) from Azure KeyVault and filters list by regular expression secretNamePattern |
| Function | Parameters | Description |
|----------------------------|--------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------|
| `azKeyVaultSecret` | `vaultUrl` (string), `secretName` (string), `version` (string, optional) | Fetches secret object from Azure KeyVault |
| `azKeyVaultSecretVersions` | `vaultUrl` (string), `secretName` (string), `count` (integer) | Fetches the list of `count` secret versions (as array, excluding disabled secrets) from Azure KeyVault |
| `azKeyVaultSecretList` | `vaultUrl` (string), `secretNamePattern` (string, regexp) | Fetche the list of secret objects (without secret value) from Azure KeyVault and filters list by regular expression secretNamePattern |

response format:
```json
Expand Down
65 changes: 65 additions & 0 deletions azuretpl/azure.keyvault.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package azuretpl
import (
"fmt"
"regexp"
"sort"
"strconv"
"strings"
"time"

Expand Down Expand Up @@ -108,6 +110,69 @@ func (e *AzureTemplateExecutor) azKeyVaultSecret(vaultUrl string, secretName str
})
}

// azKeyVaultSecretVersions fetches older versions of one secret from Azure KeyVault
func (e *AzureTemplateExecutor) azKeyVaultSecretVersions(vaultUrl string, secretName string, count int) (interface{}, error) {
// azure keyvault url detection
if val, err := e.buildAzKeyVaulUrl(vaultUrl); err == nil {
vaultUrl = val
} else {
return nil, err
}

e.logger.Infof(`fetching Azure KeyVault secret history '%v' -> '%v' with %d versions`, vaultUrl, secretName, count)

if val, enabled := e.lintResult(); enabled {
return val, nil
}
cacheKey := generateCacheKey(`azKeyVaultSecretHistory`, vaultUrl, secretName, strconv.Itoa(count))
return e.cacheResult(cacheKey, func() (interface{}, error) {
secretClient, err := azsecrets.NewClient(vaultUrl, e.azureClient().GetCred(), nil)
if err != nil {
return nil, fmt.Errorf(`failed to create keyvault client for vault "%v": %w`, vaultUrl, err)
}

pager := secretClient.NewListSecretPropertiesVersionsPager(secretName, nil)

ret := []interface{}{}
for pager.More() {
result, err := pager.NextPage(e.ctx)
if err != nil {
e.logger.Panic(err)
}

// sort results
sort.Slice(result.Value, func(i, j int) bool {
return result.Value[i].Attributes.Created.UTC().After(result.Value[j].Attributes.Created.UTC())
})

for _, secretVersion := range result.Value {
if count >= 0 && len(ret) >= count {
break
}

secret, err := secretClient.GetSecret(e.ctx, secretVersion.ID.Name(), secretVersion.ID.Version(), nil)
if err != nil {
return nil, fmt.Errorf(`unable to fetch secret "%[2]v" with version "%[3]v" from vault "%[1]v": %[4]w`, vaultUrl, secretVersion.ID.Name(), secretVersion.ID.Version(), err)
}

if !*secret.Attributes.Enabled {
continue
}

e.handleCicdMaskSecret(to.String(secret.Secret.Value))

if val, err := transformToInterface(secret); err == nil {
ret = append(ret, val)
} else {
return nil, err
}
}
}

return ret, nil
})
}

// azKeyVaultSecretList fetches secrets from Azure KeyVault
func (e *AzureTemplateExecutor) azKeyVaultSecretList(vaultUrl string, secretNamePattern string) (interface{}, error) {
// azure keyvault url detection
Expand Down
5 changes: 3 additions & 2 deletions azuretpl/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,9 @@ func (e *AzureTemplateExecutor) TxtFuncMap(tmpl *template.Template) template.Fun
`azAccountInfo`: e.azAccountInfo,

// azure keyvault
`azKeyVaultSecret`: e.azKeyVaultSecret,
`azKeyVaultSecretList`: e.azKeyVaultSecretList,
`azKeyVaultSecret`: e.azKeyVaultSecret,
`azKeyVaultSecretVersions`: e.azKeyVaultSecretVersions,
`azKeyVaultSecretList`: e.azKeyVaultSecretList,

// azure redis
`azRedisAccessKeys`: e.azRedisAccessKeys,
Expand Down

0 comments on commit f1d341f

Please sign in to comment.