Skip to content

Commit

Permalink
Add new platformWorkloadIdentityIDs manager function
Browse files Browse the repository at this point in the history
  • Loading branch information
tsatam committed Sep 24, 2024
1 parent 692129e commit 5909bb3
Show file tree
Hide file tree
Showing 2 changed files with 251 additions and 0 deletions.
50 changes: 50 additions & 0 deletions pkg/cluster/platformworkloadidentities.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package cluster

// Copyright (c) Microsoft Corporation.
// Licensed under the Apache License 2.0.

import (
"context"
"fmt"

"github.com/Azure/azure-sdk-for-go/sdk/azcore/arm"
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/msi/armmsi"

"github.com/Azure/ARO-RP/pkg/api"
)

func (m *manager) platformWorkloadIdentityIDs(ctx context.Context) error {
var err error
if !m.doc.OpenShiftCluster.UsesWorkloadIdentity() {
return fmt.Errorf("platformWorkloadIdentityIDs called for CSP cluster")
}

identities := m.doc.OpenShiftCluster.Properties.PlatformWorkloadIdentityProfile.PlatformWorkloadIdentities
updatedIdentities := make([]api.PlatformWorkloadIdentity, len(identities))

for i, identity := range identities {
resourceId, err := arm.ParseResourceID(identity.ResourceID)
if err != nil {
return fmt.Errorf("platform workload identity '%s' invalid: %w", identity.OperatorName, err)
}

identityDetails, err := m.userAssignedIdentities.Get(ctx, resourceId.ResourceGroupName, resourceId.Name, &armmsi.UserAssignedIdentitiesClientGetOptions{})
if err != nil {
return fmt.Errorf("error occured when retrieving platform workload identity '%s' details: %w", identity.OperatorName, err)
}

updatedIdentities[i] = api.PlatformWorkloadIdentity{
OperatorName: identity.OperatorName,
ResourceID: identity.ResourceID,
ClientID: *identityDetails.Properties.ClientID,
ObjectID: *identityDetails.Properties.PrincipalID,
}
}

m.doc, err = m.db.PatchWithLease(ctx, m.doc.Key, func(doc *api.OpenShiftClusterDocument) error {
doc.OpenShiftCluster.Properties.PlatformWorkloadIdentityProfile.PlatformWorkloadIdentities = updatedIdentities
return nil
})

return err
}
201 changes: 201 additions & 0 deletions pkg/cluster/platformworkloadidentities_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
package cluster

// Copyright (c) Microsoft Corporation.
// Licensed under the Apache License 2.0.

import (
"context"
"fmt"
"strings"
"testing"

"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/msi/armmsi"
"github.com/golang/mock/gomock"
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"

"github.com/Azure/ARO-RP/pkg/api"
mock_armmsi "github.com/Azure/ARO-RP/pkg/util/mocks/azureclient/azuresdk/armmsi"
testdatabase "github.com/Azure/ARO-RP/test/database"
utilerror "github.com/Azure/ARO-RP/test/util/error"
)

func TestPlatformWorkloadIdentityIDs(t *testing.T) {
subscriptionId := "00000000-0000-0000-0000-000000000000"
clusterRG := "aro-cluster"

clusterName := "aro-cluster"
clusterId := strings.ToLower(fmt.Sprintf("/subscriptions/%s/resourceGroups/%s/providers/Microsoft.RedHatOpenShift/openShiftClusters/%s", subscriptionId, clusterRG, clusterName))

identityFooName := "foo"
identityFooResourceId := fmt.Sprintf("/subscriptions/%s/resourceGroups/%s/providers/Microsoft.ManagedIdentity/userAssignedIdentities/%s", subscriptionId, clusterRG, identityFooName)
identityFooClientId := "0f000f00-0f00-0f00-0f00-0f000f000f00"
identityFooObjectId := "1f001f00-1f00-1f00-1f00-1f001f001f00"

identityBarName := "bar"
identityBarResourceId := fmt.Sprintf("/subscriptions/%s/resourceGroups/%s/providers/Microsoft.ManagedIdentity/userAssignedIdentities/%s", subscriptionId, clusterRG, identityBarName)
identityBarClientId := "0ba40ba4-0ba4-0ba4-0ba4-0ba40ba40ba4"
identityBarObjectId := "1ba41ba4-1ba4-1ba4-1ba4-1ba41ba41ba4"

validWIClusterDoc := &api.OpenShiftClusterDocument{
ID: clusterId,
Key: clusterId,
OpenShiftCluster: &api.OpenShiftCluster{
Properties: api.OpenShiftClusterProperties{
PlatformWorkloadIdentityProfile: &api.PlatformWorkloadIdentityProfile{
PlatformWorkloadIdentities: []api.PlatformWorkloadIdentity{
{
OperatorName: identityFooName,
ResourceID: identityFooResourceId,
},
{
OperatorName: identityBarName,
ResourceID: identityBarResourceId,
},
},
},
},
},
}

ctx := context.Background()
for _, tt := range []struct {
name string
doc *api.OpenShiftClusterDocument
userAssignedIdentitiesClientMocks func(*mock_armmsi.MockUserAssignedIdentitiesClient)
wantErr string
wantIdentities *[]api.PlatformWorkloadIdentity
}{
{
name: "error - CSP cluster",
doc: &api.OpenShiftClusterDocument{
ID: clusterId,
Key: clusterId,
OpenShiftCluster: &api.OpenShiftCluster{
Properties: api.OpenShiftClusterProperties{
ServicePrincipalProfile: &api.ServicePrincipalProfile{
ClientID: "asdf",
ClientSecret: "asdf",
},
},
},
},
wantErr: "platformWorkloadIdentityIDs called for CSP cluster",
},
{
name: "error - platform workload identity has invalid resource id",
doc: &api.OpenShiftClusterDocument{
ID: clusterId,
Key: clusterId,
OpenShiftCluster: &api.OpenShiftCluster{
Properties: api.OpenShiftClusterProperties{
PlatformWorkloadIdentityProfile: &api.PlatformWorkloadIdentityProfile{
PlatformWorkloadIdentities: []api.PlatformWorkloadIdentity{
{

OperatorName: "invalid",
ResourceID: "I am not a resource ID.",
},
},
},
},
},
},
wantErr: "platform workload identity 'invalid' invalid: invalid resource ID: resource id 'I am not a resource ID.' must start with '/'",
},
{
name: "error - unknown error when fetching details from ARM",
doc: &api.OpenShiftClusterDocument{
ID: clusterId,
Key: clusterId,
OpenShiftCluster: &api.OpenShiftCluster{
Properties: api.OpenShiftClusterProperties{
PlatformWorkloadIdentityProfile: &api.PlatformWorkloadIdentityProfile{
PlatformWorkloadIdentities: []api.PlatformWorkloadIdentity{
{
OperatorName: identityFooName,
ResourceID: identityFooResourceId,
},
},
},
},
},
},
userAssignedIdentitiesClientMocks: func(mock *mock_armmsi.MockUserAssignedIdentitiesClient) {
mock.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().
Return(armmsi.UserAssignedIdentitiesClientGetResponse{}, fmt.Errorf("some error occurred"))
},
wantErr: "error occured when retrieving platform workload identity 'foo' details: some error occurred",
},
{
name: "success - all clientIDs and objectIDs updated in clusterdoc",
doc: validWIClusterDoc,
userAssignedIdentitiesClientMocks: func(mock *mock_armmsi.MockUserAssignedIdentitiesClient) {
mock.EXPECT().Get(gomock.Any(), gomock.Eq(clusterRG), gomock.Eq(identityFooName), gomock.Any()).Times(1).
Return(armmsi.UserAssignedIdentitiesClientGetResponse{
Identity: armmsi.Identity{
Properties: &armmsi.UserAssignedIdentityProperties{
ClientID: &identityFooClientId,
PrincipalID: &identityFooObjectId,
},
},
}, nil)

mock.EXPECT().Get(gomock.Any(), gomock.Eq(clusterRG), gomock.Eq(identityBarName), gomock.Any()).Times(1).
Return(armmsi.UserAssignedIdentitiesClientGetResponse{
Identity: armmsi.Identity{
Properties: &armmsi.UserAssignedIdentityProperties{
ClientID: &identityBarClientId,
PrincipalID: &identityBarObjectId,
},
},
}, nil)
},
wantIdentities: &[]api.PlatformWorkloadIdentity{
{
OperatorName: identityFooName,
ResourceID: identityFooResourceId,
ClientID: identityFooClientId,
ObjectID: identityFooObjectId,
},
{
OperatorName: identityBarName,
ResourceID: identityBarResourceId,
ClientID: identityBarClientId,
ObjectID: identityBarObjectId,
},
},
},
} {
t.Run(tt.name, func(t *testing.T) {
controller := gomock.NewController(t)
defer controller.Finish()

mockUserAssignedIdentities := mock_armmsi.NewMockUserAssignedIdentitiesClient(controller)
if tt.userAssignedIdentitiesClientMocks != nil {
tt.userAssignedIdentitiesClientMocks(mockUserAssignedIdentities)
}

openShiftClustersDatabase, _ := testdatabase.NewFakeOpenShiftClusters()
fixture := testdatabase.NewFixture().WithOpenShiftClusters(openShiftClustersDatabase)
fixture.AddOpenShiftClusterDocuments(tt.doc)
if err := fixture.Create(); err != nil {
t.Fatal(err)
}

m := manager{
log: logrus.NewEntry(logrus.StandardLogger()),
doc: tt.doc,
db: openShiftClustersDatabase,
userAssignedIdentities: mockUserAssignedIdentities,
}

err := m.platformWorkloadIdentityIDs(ctx)
utilerror.AssertErrorMessage(t, err, tt.wantErr)

if tt.wantIdentities != nil {
assert.ElementsMatch(t, *tt.wantIdentities, m.doc.OpenShiftCluster.Properties.PlatformWorkloadIdentityProfile.PlatformWorkloadIdentities)
}
})
}
}

0 comments on commit 5909bb3

Please sign in to comment.