Skip to content

Commit 40f7ca4

Browse files
committed
rotation policy
1 parent aa7bb1f commit 40f7ca4

File tree

4 files changed

+249
-12
lines changed

4 files changed

+249
-12
lines changed

providers/azure/resources/azure.lr

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1851,6 +1851,18 @@ private azure.subscription.keyVaultService.key @defaults("kid keyName") {
18511851
version() string
18521852
// List of key versions
18531853
versions() []azure.subscription.keyVaultService.key
1854+
// Key rotation policy
1855+
rotationPolicy() azure.subscription.keyVaultService.key.rotationPolicyObject
1856+
}
1857+
1858+
// Azure Key Vault key rotation policy
1859+
private azure.subscription.keyVaultService.key.rotationPolicyObject @defaults("enabled") {
1860+
// Lifetime actions for the rotation policy
1861+
lifetimeActions []dict
1862+
// Attributes of the rotation policy (e.g., expiryTime)
1863+
attributes dict
1864+
// Whether automatic key rotation is enabled (true if rotationPolicy exists with Rotate action)
1865+
enabled bool
18541866
}
18551867

18561868
// Azure Key Vault certificate

providers/azure/resources/azure.lr.go

Lines changed: 125 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

providers/azure/resources/azure.lr.manifest.yaml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -916,6 +916,8 @@ resources:
916916
managed: {}
917917
notBefore: {}
918918
recoveryLevel: {}
919+
rotationPolicy:
920+
min_mondoo_version: 9.0.0
919921
tags: {}
920922
updated: {}
921923
version: {}
@@ -937,6 +939,25 @@ resources:
937939
platform:
938940
name:
939941
- azure
942+
azure.subscription.keyVaultService.key.rotationPolicy:
943+
fields:
944+
attributes: {}
945+
enabled: {}
946+
lifetimeActions: {}
947+
min_mondoo_version: 9.0.0
948+
platform:
949+
name:
950+
- azure
951+
azure.subscription.keyVaultService.key.rotationPolicyObject:
952+
fields:
953+
attributes: {}
954+
enabled: {}
955+
lifetimeActions: {}
956+
is_private: true
957+
min_mondoo_version: 9.0.0
958+
platform:
959+
name:
960+
- azure
940961
azure.subscription.keyVaultService.secret:
941962
fields:
942963
contentType: {}

providers/azure/resources/keyvault.go

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"encoding/hex"
99
"errors"
1010
"fmt"
11+
"net/http"
1112
"regexp"
1213

1314
"go.mondoo.com/cnquery/v12/llx"
@@ -16,6 +17,7 @@ import (
1617
"go.mondoo.com/cnquery/v12/providers/azure/connection"
1718
"go.mondoo.com/cnquery/v12/types"
1819

20+
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
1921
"github.com/Azure/azure-sdk-for-go/sdk/azcore/arm"
2022
keyvault "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/keyvault/armkeyvault"
2123
"github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azcertificates"
@@ -438,6 +440,91 @@ func (a *mqlAzureSubscriptionKeyVaultServiceKey) versions() ([]any, error) {
438440
return res, nil
439441
}
440442

443+
func (a *mqlAzureSubscriptionKeyVaultServiceKey) rotationPolicy() (*mqlAzureSubscriptionKeyVaultServiceKeyRotationPolicyObject, error) {
444+
conn := a.MqlRuntime.Connection.(*connection.AzureConnection)
445+
id := a.Kid.Data
446+
kvid, err := parseKeyVaultId(id)
447+
if err != nil {
448+
return nil, err
449+
}
450+
451+
if kvid.Type != "keys" {
452+
return nil, errors.New("only key ids are supported")
453+
}
454+
455+
client, err := azkeys.NewClient(kvid.BaseUrl, conn.Token(), &azkeys.ClientOptions{
456+
ClientOptions: conn.ClientOptions(),
457+
})
458+
if err != nil {
459+
return nil, err
460+
}
461+
462+
ctx := context.Background()
463+
policyResp, err := client.GetKeyRotationPolicy(ctx, kvid.Name, nil)
464+
if err != nil {
465+
// Only treat 404 (not found) as "policy doesn't exist"
466+
// Return actual errors for permissions, network issues, etc.
467+
var respErr *azcore.ResponseError
468+
if errors.As(err, &respErr) && respErr.StatusCode == http.StatusNotFound {
469+
// Rotation policy doesn't exist, return a resource with enabled=false
470+
resource, err := CreateResource(a.MqlRuntime,
471+
ResourceAzureSubscriptionKeyVaultServiceKeyRotationPolicyObject,
472+
map[string]*llx.RawData{
473+
"__id": llx.StringData(id + "/rotationPolicy"),
474+
"lifetimeActions": llx.ArrayData([]any{}, types.Dict),
475+
"attributes": llx.DictData(map[string]any{}),
476+
"enabled": llx.BoolData(false),
477+
},
478+
)
479+
if err != nil {
480+
return nil, err
481+
}
482+
return resource.(*mqlAzureSubscriptionKeyVaultServiceKeyRotationPolicyObject), nil
483+
}
484+
// Return the actual error for non-404 cases
485+
return nil, err
486+
}
487+
488+
lifetimeActions := []any{}
489+
rotationEnabled := false
490+
if policyResp.LifetimeActions != nil {
491+
for _, action := range policyResp.LifetimeActions {
492+
actionDict, err := convert.JsonToDict(action)
493+
if err != nil {
494+
return nil, err
495+
}
496+
lifetimeActions = append(lifetimeActions, actionDict)
497+
498+
if action.Action != nil && string(*action.Action.Type) == "Rotate" {
499+
rotationEnabled = true
500+
}
501+
}
502+
}
503+
504+
attributes := map[string]any{}
505+
if policyResp.Attributes != nil {
506+
attributesDict, err := convert.JsonToDict(policyResp.Attributes)
507+
if err != nil {
508+
return nil, err
509+
}
510+
attributes = attributesDict
511+
}
512+
513+
resource, err := CreateResource(a.MqlRuntime,
514+
ResourceAzureSubscriptionKeyVaultServiceKeyRotationPolicyObject,
515+
map[string]*llx.RawData{
516+
"__id": llx.StringData(id + "/rotationPolicy"),
517+
"lifetimeActions": llx.ArrayData(lifetimeActions, types.Dict),
518+
"attributes": llx.DictData(attributes),
519+
"enabled": llx.BoolData(rotationEnabled),
520+
},
521+
)
522+
if err != nil {
523+
return nil, err
524+
}
525+
return resource.(*mqlAzureSubscriptionKeyVaultServiceKeyRotationPolicyObject), nil
526+
}
527+
441528
func (a *mqlAzureSubscriptionKeyVaultServiceCertificate) certName() (string, error) {
442529
id := a.Id.Data
443530
kvid, err := parseKeyVaultId(id)
@@ -628,3 +715,7 @@ func initAzureSubscriptionKeyVaultServiceVault(runtime *plugin.Runtime, args map
628715

629716
return nil, nil, errors.New("azure key vault does not exist")
630717
}
718+
719+
func (a *mqlAzureSubscriptionKeyVaultServiceKeyRotationPolicyObject) id() (string, error) {
720+
return a.__id, nil
721+
}

0 commit comments

Comments
 (0)