This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/keyvault/armkeyvault](https://github.com/Azure/azure-sdk-for-go) | `v1.5.0` → `v2.1.0` |  |  | | [github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armsubscriptions](https://github.com/Azure/azure-sdk-for-go) | `v1.3.0` → `v2.0.0` |  |  | --- ### Release Notes <details> <summary>Azure/azure-sdk-for-go (github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/keyvault/armkeyvault)</summary> ### [`v2.1.0`](https://github.com/Azure/azure-sdk-for-go/releases/tag/sdk/resourcemanager/keyvault/armkeyvault/v2.1.0) #### 2.1.0 (2026-10-06) ##### Features Added - New value `JSONWebKeyTypeOctHSM` added to enum type `JSONWebKeyType` - New value `ManagedHsmSKUNameStandardB10V2`, `ManagedHsmSKUNameStandardB15V2`, `ManagedHsmSKUNameStandardB1V2`, `ManagedHsmSKUNameStandardB20V2`, `ManagedHsmSKUNameStandardB5V2` added to enum type `ManagedHsmSKUName` ### [`v2.0.2`](https://github.com/Azure/azure-sdk-for-go/releases/tag/sdk/resourcemanager/keyvault/armkeyvault/v2.0.2) #### 2.0.2 (2026-03-17) ##### Other Changes - Upgrade to service API version 2026-02-01 ### [`v2.0.1`](https://github.com/Azure/azure-sdk-for-go/releases/tag/sdk/resourcemanager/keyvault/armkeyvault/v2.0.1) #### 2.0.1 (2025-11-05) ##### Breaking Changes - Field `RetryAfter` of struct `SecretsClientCreateOrUpdateResponse` has been removed ### [`v2.0.0`](https://github.com/Azure/azure-sdk-for-go/releases/tag/sdk/resourcemanager/resources/armsubscriptions/v2.0.0) #### 2.0.0 (2026-06-24) ##### Breaking Changes - Struct `ErrorAdditionalInfo` has been removed - Struct `ErrorDetail` has been removed - Struct `ErrorResponse` has been removed - Struct `ErrorResponseAutoGenerated` has been removed - Struct `OperationAutoGenerated` has been removed - Struct `OperationDisplayAutoGenerated` has been removed - Struct `OperationListResultAutoGenerated` has been removed ##### Features Added - New field `NextLink` in struct `LocationListResult` </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about these updates again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate CLI](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xNTQuMSIsInVwZGF0ZWRJblZlciI6IjQ0LjE1NC4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119--> Reviewed-on: #52 Co-authored-by: Renovate Bot <renovate-bot@noreply.git.kebcloud.no>
159 lines
5.0 KiB
Go
159 lines
5.0 KiB
Go
package azure
|
|
|
|
import (
|
|
"fmt"
|
|
"slices"
|
|
"strings"
|
|
|
|
"github.com/Azure/azure-sdk-for-go/sdk/azcore/arm"
|
|
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/keyvault/armkeyvault/v2"
|
|
|
|
"git.kebcloud.no/keb/lazysecrets/internal/provider"
|
|
)
|
|
|
|
// A vault's settings come with the listing, from Resource Graph or the
|
|
// Key Vault management API, with no requests of their own: where it is,
|
|
// how access to it works, and how it's protected.
|
|
|
|
type vaultInfo struct {
|
|
group, location, sku string
|
|
rbac, softDelete, purge *bool
|
|
retention *int32
|
|
publicAccess, defaultAction string
|
|
ipRules, subnets, endpoints int
|
|
policies int
|
|
tags map[string]string
|
|
}
|
|
|
|
// vaultQuery lists vaults with just the settings shown, not their whole
|
|
// properties (access policies can be long).
|
|
const vaultQuery = `resources
|
|
| where type =~ 'microsoft.keyvault/vaults'
|
|
| project id, name, uri = tostring(properties.vaultUri), location, resourceGroup, tags,
|
|
sku = tostring(properties.sku.name), rbac = properties.enableRbacAuthorization,
|
|
softDelete = properties.enableSoftDelete, retention = properties.softDeleteRetentionInDays,
|
|
purge = properties.enablePurgeProtection, publicAccess = tostring(properties.publicNetworkAccess),
|
|
defaultAction = tostring(properties.networkAcls.defaultAction),
|
|
ipRules = array_length(properties.networkAcls.ipRules),
|
|
subnets = array_length(properties.networkAcls.virtualNetworkRules),
|
|
endpoints = array_length(properties.privateEndpointConnections),
|
|
policies = array_length(properties.accessPolicies)`
|
|
|
|
// graphInfo reads a vaultQuery row's settings.
|
|
func graphInfo(m map[string]any) vaultInfo {
|
|
str := func(k string) string { s, _ := m[k].(string); return s }
|
|
num := func(k string) int { f, _ := m[k].(float64); return int(f) }
|
|
flag := func(k string) *bool {
|
|
if b, ok := m[k].(bool); ok {
|
|
return &b
|
|
}
|
|
return nil
|
|
}
|
|
v := vaultInfo{
|
|
group: str("resourceGroup"), location: str("location"), sku: str("sku"),
|
|
rbac: flag("rbac"), softDelete: flag("softDelete"), purge: flag("purge"),
|
|
publicAccess: str("publicAccess"), defaultAction: str("defaultAction"),
|
|
ipRules: num("ipRules"), subnets: num("subnets"), endpoints: num("endpoints"), policies: num("policies"),
|
|
}
|
|
if f, ok := m["retention"].(float64); ok {
|
|
r := int32(f)
|
|
v.retention = &r
|
|
}
|
|
if tags, ok := m["tags"].(map[string]any); ok {
|
|
v.tags = map[string]string{}
|
|
for k, t := range tags {
|
|
v.tags[k] = fmt.Sprint(t)
|
|
}
|
|
}
|
|
return v
|
|
}
|
|
|
|
// armInfo reads a vault's settings from the management API.
|
|
func armInfo(v *armkeyvault.Vault) vaultInfo {
|
|
info := vaultInfo{location: deref(v.Location), tags: map[string]string{}}
|
|
if id, err := arm.ParseResourceID(deref(v.ID)); err == nil {
|
|
info.group = id.ResourceGroupName
|
|
}
|
|
for k, t := range v.Tags {
|
|
info.tags[k] = deref(t)
|
|
}
|
|
pr := v.Properties
|
|
if pr == nil {
|
|
return info
|
|
}
|
|
if pr.SKU != nil && pr.SKU.Name != nil {
|
|
info.sku = string(*pr.SKU.Name)
|
|
}
|
|
info.rbac, info.softDelete, info.purge = pr.EnableRbacAuthorization, pr.EnableSoftDelete, pr.EnablePurgeProtection
|
|
info.retention, info.publicAccess = pr.SoftDeleteRetentionInDays, deref(pr.PublicNetworkAccess)
|
|
if acl := pr.NetworkACLs; acl != nil {
|
|
if acl.DefaultAction != nil {
|
|
info.defaultAction = string(*acl.DefaultAction)
|
|
}
|
|
info.ipRules, info.subnets = len(acl.IPRules), len(acl.VirtualNetworkRules)
|
|
}
|
|
info.endpoints, info.policies = len(pr.PrivateEndpointConnections), len(pr.AccessPolicies)
|
|
return info
|
|
}
|
|
|
|
func (v vaultInfo) attrs() []provider.Attr {
|
|
var out []provider.Attr
|
|
add := func(label, value string) {
|
|
if value != "" {
|
|
out = append(out, provider.Attr{Label: label, Value: value})
|
|
}
|
|
}
|
|
add("group", v.group)
|
|
add("location", v.location)
|
|
add("SKU", v.sku)
|
|
// Who may read secrets is decided by Azure roles or by the vault's
|
|
// own access policies, never both.
|
|
if on(v.rbac, false) {
|
|
add("access", "Azure roles (RBAC)")
|
|
} else {
|
|
add("access", fmt.Sprintf("access policies (%d)", v.policies))
|
|
}
|
|
if on(v.softDelete, true) {
|
|
days := int32(90)
|
|
if v.retention != nil {
|
|
days = *v.retention
|
|
}
|
|
add("soft delete", fmt.Sprintf("on, %d days", days))
|
|
} else {
|
|
add("soft delete", "off")
|
|
}
|
|
add("purge prot.", map[bool]string{true: "on", false: "off"}[on(v.purge, false)])
|
|
switch {
|
|
case strings.EqualFold(v.publicAccess, "disabled"):
|
|
add("network", "private endpoints only")
|
|
case strings.EqualFold(v.defaultAction, "deny"):
|
|
add("network", fmt.Sprintf("selected networks (%d IP ranges, %d subnets)", v.ipRules, v.subnets))
|
|
default:
|
|
add("network", "all networks")
|
|
}
|
|
if v.endpoints > 0 {
|
|
add("private", fmt.Sprintf("%d endpoint%s", v.endpoints, map[bool]string{true: "s"}[v.endpoints > 1]))
|
|
}
|
|
keys := make([]string, 0, len(v.tags))
|
|
for k := range v.tags {
|
|
keys = append(keys, k)
|
|
}
|
|
slices.Sort(keys)
|
|
for i, k := range keys {
|
|
label := ""
|
|
if i == 0 {
|
|
label = "tags"
|
|
}
|
|
out = append(out, provider.Attr{Label: label, Value: k + ": " + v.tags[k]})
|
|
}
|
|
return out
|
|
}
|
|
|
|
// on is *b, or def when it isn't set.
|
|
func on(b *bool, def bool) bool {
|
|
if b == nil {
|
|
return def
|
|
}
|
|
return *b
|
|
}
|