Skip to content

Commit e9c1ac9

Browse files
Copilotmatthchr
andauthored
Add shared keys secret exports for Microsoft.OperationalInsights/workspaces (#5011)
* Initial plan * Add shared keys secret exports for operationalinsights/workspaces - Added $azureGeneratedSecrets configuration to azure-arm.yaml - Created workspace_extension.go with secret handler - Added Azure SDK dependency for operationalinsights - Updated test to verify secret export functionality Co-authored-by: matthchr <[email protected]> * Update generated files and dependencies - Generated DeepCopy methods for WorkspaceOperatorSecrets - Updated asoctl dependencies Co-authored-by: matthchr <[email protected]> * Fix go.mod: Move dependency to main require block - Moved operationalinsights SDK to main require block in alphabetical order - Removed separate require statement for better organization Co-authored-by: matthchr <[email protected]> * Record test --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: matthchr <[email protected]> Co-authored-by: Matthew Christopher <[email protected]>
1 parent eb7e719 commit e9c1ac9

18 files changed

+1551
-371
lines changed
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/*
2+
* Copyright (c) Microsoft Corporation.
3+
* Licensed under the MIT license.
4+
*/
5+
6+
package customizations
7+
8+
import (
9+
"context"
10+
11+
. "github.com/Azure/azure-service-operator/v2/internal/logging"
12+
13+
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/operationalinsights/armoperationalinsights"
14+
"github.com/go-logr/logr"
15+
"github.com/rotisserie/eris"
16+
v1 "k8s.io/api/core/v1"
17+
"sigs.k8s.io/controller-runtime/pkg/conversion"
18+
19+
"github.com/Azure/azure-service-operator/v2/api/operationalinsights/v1api20210601/storage"
20+
"github.com/Azure/azure-service-operator/v2/internal/genericarmclient"
21+
"github.com/Azure/azure-service-operator/v2/internal/set"
22+
"github.com/Azure/azure-service-operator/v2/internal/util/to"
23+
"github.com/Azure/azure-service-operator/v2/pkg/genruntime"
24+
"github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets"
25+
)
26+
27+
const (
28+
primarySharedKey = "primarySharedKey"
29+
secondarySharedKey = "secondarySharedKey"
30+
)
31+
32+
var _ genruntime.KubernetesSecretExporter = &WorkspaceExtension{}
33+
34+
func (ext *WorkspaceExtension) ExportKubernetesSecrets(
35+
ctx context.Context,
36+
obj genruntime.MetaObject,
37+
additionalSecrets set.Set[string],
38+
armClient *genericarmclient.GenericClient,
39+
log logr.Logger,
40+
) (*genruntime.KubernetesSecretExportResult, error) {
41+
// This has to be the current hub storage version. It will need to be updated
42+
// if the hub storage version changes.
43+
typedObj, ok := obj.(*storage.Workspace)
44+
if !ok {
45+
return nil, eris.Errorf("cannot run on unknown resource type %T, expected *storage.Workspace", obj)
46+
}
47+
48+
// Type assert that we are the hub type. This will fail to compile if
49+
// the hub type has been changed but this extension has not
50+
var _ conversion.Hub = typedObj
51+
52+
primarySecrets := secretsSpecified(typedObj)
53+
requestedSecrets := set.Union(primarySecrets, additionalSecrets)
54+
55+
if len(requestedSecrets) == 0 {
56+
log.V(Debug).Info("No secrets retrieval to perform as operatorSpec is empty")
57+
return nil, nil
58+
}
59+
60+
id, err := genruntime.GetAndParseResourceID(typedObj)
61+
if err != nil {
62+
return nil, err
63+
}
64+
65+
subscription := id.SubscriptionID
66+
// Using armClient.ClientOptions() here ensures we share the same HTTP connection, so this is not opening a new
67+
// connection each time through
68+
var sharedKeysClient *armoperationalinsights.SharedKeysClient
69+
sharedKeysClient, err = armoperationalinsights.NewSharedKeysClient(subscription, armClient.Creds(), armClient.ClientOptions())
70+
if err != nil {
71+
return nil, eris.Wrapf(err, "failed to create new SharedKeysClient")
72+
}
73+
74+
var resp armoperationalinsights.SharedKeysClientGetSharedKeysResponse
75+
resp, err = sharedKeysClient.GetSharedKeys(ctx, id.ResourceGroupName, typedObj.AzureName(), nil)
76+
if err != nil {
77+
return nil, eris.Wrapf(err, "failed getting shared keys")
78+
}
79+
80+
secretSlice, err := secretsToWrite(typedObj, resp)
81+
if err != nil {
82+
return nil, err
83+
}
84+
85+
resolvedSecrets := map[string]string{}
86+
if to.Value(resp.PrimarySharedKey) != "" {
87+
resolvedSecrets[primarySharedKey] = to.Value(resp.PrimarySharedKey)
88+
}
89+
if to.Value(resp.SecondarySharedKey) != "" {
90+
resolvedSecrets[secondarySharedKey] = to.Value(resp.SecondarySharedKey)
91+
}
92+
93+
return &genruntime.KubernetesSecretExportResult{
94+
Objs: secrets.SliceToClientObjectSlice(secretSlice),
95+
RawSecrets: secrets.SelectSecrets(additionalSecrets, resolvedSecrets),
96+
}, nil
97+
}
98+
99+
func secretsSpecified(obj *storage.Workspace) set.Set[string] {
100+
if obj.Spec.OperatorSpec == nil || obj.Spec.OperatorSpec.Secrets == nil {
101+
return nil
102+
}
103+
104+
secrets := obj.Spec.OperatorSpec.Secrets
105+
result := make(set.Set[string])
106+
if secrets.PrimarySharedKey != nil {
107+
result.Add(primarySharedKey)
108+
}
109+
if secrets.SecondarySharedKey != nil {
110+
result.Add(secondarySharedKey)
111+
}
112+
113+
return result
114+
}
115+
116+
func secretsToWrite(obj *storage.Workspace, keys armoperationalinsights.SharedKeysClientGetSharedKeysResponse) ([]*v1.Secret, error) {
117+
operatorSpecSecrets := obj.Spec.OperatorSpec.Secrets
118+
if operatorSpecSecrets == nil {
119+
return nil, nil
120+
}
121+
122+
collector := secrets.NewCollector(obj.Namespace)
123+
collector.AddValue(operatorSpecSecrets.PrimarySharedKey, to.Value(keys.PrimarySharedKey))
124+
collector.AddValue(operatorSpecSecrets.SecondarySharedKey, to.Value(keys.SecondarySharedKey))
125+
126+
return collector.Values()
127+
}

v2/api/operationalinsights/v1api20210601/storage/structure.txt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,14 @@ Workspace: Resource
1818
│ │ └── PropertyBag: genruntime.PropertyBag
1919
│ ├── ForceCmkForQuery: *bool
2020
│ ├── Location: *string
21-
│ ├── OperatorSpec: *Object (3 properties)
21+
│ ├── OperatorSpec: *Object (4 properties)
2222
│ │ ├── ConfigMapExpressions: *core.DestinationExpression[]
2323
│ │ ├── PropertyBag: genruntime.PropertyBag
24-
│ │ └── SecretExpressions: *core.DestinationExpression[]
24+
│ │ ├── SecretExpressions: *core.DestinationExpression[]
25+
│ │ └── Secrets: *Object (3 properties)
26+
│ │ ├── PrimarySharedKey: *genruntime.SecretDestination
27+
│ │ ├── PropertyBag: genruntime.PropertyBag
28+
│ │ └── SecondarySharedKey: *genruntime.SecretDestination
2529
│ ├── OriginalVersion: string
2630
│ ├── Owner: *genruntime.KnownResourceReference
2731
│ ├── PropertyBag: genruntime.PropertyBag

v2/api/operationalinsights/v1api20210601/storage/workspace_types_gen.go

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

v2/api/operationalinsights/v1api20210601/storage/workspace_types_gen_test.go

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

v2/api/operationalinsights/v1api20210601/storage/zz_generated.deepcopy.go

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

v2/api/operationalinsights/v1api20210601/structure.txt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,12 @@ Workspace: Resource
2020
│ │ └── ImmediatePurgeDataOn30Days: *bool
2121
│ ├── ForceCmkForQuery: *bool
2222
│ ├── Location: *string
23-
│ ├── OperatorSpec: *Object (2 properties)
23+
│ ├── OperatorSpec: *Object (3 properties)
2424
│ │ ├── ConfigMapExpressions: *core.DestinationExpression[]
25-
│ │ └── SecretExpressions: *core.DestinationExpression[]
25+
│ │ ├── SecretExpressions: *core.DestinationExpression[]
26+
│ │ └── Secrets: *Object (2 properties)
27+
│ │ ├── PrimarySharedKey: *genruntime.SecretDestination
28+
│ │ └── SecondarySharedKey: *genruntime.SecretDestination
2629
│ ├── Owner: *genruntime.KnownResourceReference
2730
│ ├── ProvisioningState: *Enum (7 values)
2831
│ │ ├── "Canceled"

v2/api/operationalinsights/v1api20210601/webhook/workspace_types_gen.go

Lines changed: 8 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)