Skip to content

Commit 8db86bd

Browse files
authored
Added SDK calls for assignSpRole function (#272)
1 parent 7975039 commit 8db86bd

File tree

7 files changed

+142
-9
lines changed

7 files changed

+142
-9
lines changed

cmd/setup-gh.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77

88
"github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud"
99
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
10+
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization"
1011
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/subscription/armsubscription"
1112
"github.com/Azure/draft/pkg/cred"
1213
"github.com/manifoldco/promptui"
@@ -50,6 +51,13 @@ application and service principle, and will configure that application to trust
5051

5152
sc.AzClient.GraphClient = graphClient
5253

54+
roleAssignmentClient, err := armauthorization.NewRoleAssignmentsClient(sc.SubscriptionID, azCred, nil)
55+
if err != nil {
56+
return fmt.Errorf("getting role assignment client: %w", err)
57+
}
58+
59+
sc.AzClient.RoleAssignClient = roleAssignmentClient
60+
5361
fillSetUpConfig(sc)
5462

5563
s := spinner.CreateSpinner("--> Setting up Github OIDC...")

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ go 1.22.0
55
require (
66
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1
77
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.2
8+
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization v1.0.0
89
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/subscription/armsubscription v1.2.0
910
github.com/briandowns/spinner v1.23.0
1011
github.com/cenkalti/backoff/v4 v4.3.0

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.2 h1:FDif4R1+UUR+00q6wquyX
1717
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.2/go.mod h1:aiYBYui4BJ/BJCAIKs92XiPyQfTaBWqvHujDwKb6CBU=
1818
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.2 h1:LqbJ/WzJUwBf8UiaSzgX7aMclParm9/5Vgp+TY51uBQ=
1919
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.2/go.mod h1:yInRyqWXAuaPrgI7p70+lDDgh3mlBohis29jGMISnmc=
20+
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization v1.0.0 h1:qtRcg5Y7jNJ4jEzPq4GpWLfTspHdNe2ZK6LjwGcjgmU=
21+
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization v1.0.0/go.mod h1:lPneRe3TwsoDRKY4O6YDLXHhEWrD+TIRa8XrV/3/fqw=
2022
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/subscription/armsubscription v1.2.0 h1:UrGzkHueDwAWDdjQxC+QaXHd4tVCkISYE9j7fSSXF8k=
2123
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/subscription/armsubscription v1.2.0/go.mod h1:qskvSQeW+cxEE2bcKYyKimB1/KiQ9xpJ99bcHY0BX6c=
2224
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=

pkg/providers/az-client.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,18 @@ import (
44
"context"
55
"errors"
66
"fmt"
7+
78
"github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
9+
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization"
810
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/subscription/armsubscription"
11+
912
msgraph "github.com/microsoftgraph/msgraph-sdk-go"
1013
)
1114

1215
type AzClient struct {
13-
AzTenantClient azTenantClient
14-
GraphClient GraphClient
16+
AzTenantClient azTenantClient
17+
GraphClient GraphClient
18+
RoleAssignClient RoleAssignClient
1519
}
1620

1721
//go:generate mockgen -source=./az-client.go -destination=./mock/az-client.go .
@@ -43,3 +47,9 @@ func (g *GraphServiceClient) GetApplicationObjectId(ctx context.Context, appId s
4347
}
4448
return *appObjectId, nil
4549
}
50+
51+
type RoleAssignClient interface {
52+
CreateByID(ctx context.Context, roleAssignmentID string, parameters armauthorization.RoleAssignmentCreateParameters, options *armauthorization.RoleAssignmentsClientCreateByIDOptions) (armauthorization.RoleAssignmentsClientCreateByIDResponse, error)
53+
}
54+
55+
var _ RoleAssignClient = &armauthorization.RoleAssignmentsClient{}

pkg/providers/azure.go

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"encoding/json"
66
"errors"
77
"fmt"
8+
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization"
89
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/subscription/armsubscription"
910
"os/exec"
1011
"time"
@@ -61,7 +62,7 @@ func InitiateAzureOIDCFlow(ctx context.Context, sc *SetUpCmd, s spinner.Spinner)
6162
return err
6263
}
6364

64-
if err := sc.assignSpRole(); err != nil {
65+
if err := sc.assignSpRole(ctx); err != nil {
6566
return err
6667
}
6768

@@ -165,14 +166,22 @@ func (sc *SetUpCmd) CreateServicePrincipal() error {
165166
return nil
166167
}
167168

168-
func (sc *SetUpCmd) assignSpRole() error {
169+
func (sc *SetUpCmd) assignSpRole(ctx context.Context) error {
169170
log.Debug("Assigning contributor role to service principal...")
170-
scope := fmt.Sprintf("/subscriptions/%s/resourceGroups/%s", sc.SubscriptionID, sc.ResourceGroupName)
171-
assignSpRoleCmd := exec.Command("az", "role", "assignment", "create", "--role", "contributor", "--subscription", sc.SubscriptionID, "--assignee-object-id", sc.spObjectId, "--assignee-principal-type", "ServicePrincipal", "--scope", scope, "--only-show-errors")
172-
out, err := assignSpRoleCmd.CombinedOutput()
171+
172+
objectID := sc.spObjectId
173+
roleID := "contributor"
174+
175+
parameters := armauthorization.RoleAssignmentCreateParameters{
176+
Properties: &armauthorization.RoleAssignmentProperties{
177+
PrincipalID: &objectID,
178+
RoleDefinitionID: &roleID,
179+
},
180+
}
181+
182+
_, err := sc.AzClient.RoleAssignClient.CreateByID(ctx, roleID, parameters, nil)
173183
if err != nil {
174-
log.Printf("%s\n", out)
175-
return err
184+
return fmt.Errorf("creating role assignment: %w", err)
176185
}
177186

178187
log.Debug("Role assigned successfully!")

pkg/providers/azure_test.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"errors"
66
"github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
77
"github.com/Azure/azure-sdk-for-go/sdk/azcore/tracing"
8+
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization"
89
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/subscription/armsubscription"
910
mock_providers "github.com/Azure/draft/pkg/providers/mock"
1011
"go.uber.org/mock/gomock"
@@ -243,3 +244,66 @@ func TestGetAppObjectId_EmptyAppIdFromGraphClient(t *testing.T) {
243244
t.Errorf("Expected error '%v', got '%v'", expectedError, err)
244245
}
245246
}
247+
248+
var principalId = "mockPrincipalID"
249+
var roleDefId = "mockRoleDefinitionID"
250+
var Id = "mockID"
251+
var name = "mockName"
252+
var Idtype = "mocktype"
253+
254+
func TestAssignSpRole(t *testing.T) {
255+
tests := []struct {
256+
name string
257+
expectedError error
258+
mockResponse armauthorization.RoleAssignmentsClientCreateByIDResponse
259+
}{
260+
{
261+
name: "Success",
262+
expectedError: nil,
263+
mockResponse: armauthorization.RoleAssignmentsClientCreateByIDResponse{
264+
RoleAssignment: armauthorization.RoleAssignment{
265+
Properties: &armauthorization.RoleAssignmentPropertiesWithScope{
266+
PrincipalID: &principalId,
267+
RoleDefinitionID: &roleDefId,
268+
},
269+
ID: &Id,
270+
Name: &name,
271+
Type: &Idtype,
272+
},
273+
},
274+
},
275+
{
276+
name: "Error",
277+
expectedError: errors.New("error"),
278+
mockResponse: armauthorization.RoleAssignmentsClientCreateByIDResponse{},
279+
},
280+
{
281+
name: "ErrorDuringRoleAssignment",
282+
expectedError: errors.New("error during role assignment"),
283+
mockResponse: armauthorization.RoleAssignmentsClientCreateByIDResponse{},
284+
},
285+
}
286+
287+
for _, tt := range tests {
288+
t.Run(tt.name, func(t *testing.T) {
289+
ctrl := gomock.NewController(t)
290+
defer ctrl.Finish()
291+
292+
mockRoleAssignClient := mock_providers.NewMockRoleAssignClient(ctrl)
293+
294+
mockRoleAssignClient.EXPECT().CreateByID(gomock.Any(), "contributor", gomock.Any(), gomock.Any()).Return(tt.mockResponse, tt.expectedError)
295+
296+
sc := &SetUpCmd{
297+
AzClient: AzClient{
298+
RoleAssignClient: mockRoleAssignClient,
299+
},
300+
spObjectId: "testObjectId",
301+
}
302+
303+
err := sc.assignSpRole(context.Background())
304+
if !errors.Is(err, tt.expectedError) {
305+
t.Errorf("Expected error: %v, got: %v", tt.expectedError, err)
306+
}
307+
})
308+
}
309+
}

pkg/providers/mock/az-client.go

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

0 commit comments

Comments
 (0)