2022-03-22 11:03:15 -04:00
|
|
|
package client
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"errors"
|
|
|
|
"net/url"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
|
|
|
|
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources"
|
|
|
|
"github.com/Azure/azure-sdk-for-go/services/graphrbac/1.6/graphrbac"
|
|
|
|
"github.com/Azure/go-autorest/autorest"
|
|
|
|
"github.com/Azure/go-autorest/autorest/azure"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"google.golang.org/protobuf/proto"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestCreateServicePrincipal(t *testing.T) {
|
|
|
|
someErr := errors.New("failed")
|
|
|
|
testCases := map[string]struct {
|
|
|
|
applicationsAPI applicationsAPI
|
|
|
|
servicePrincipalsAPI servicePrincipalsAPI
|
|
|
|
roleAssignmentsAPI roleAssignmentsAPI
|
|
|
|
resourceGroupAPI resourceGroupAPI
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr bool
|
2022-03-22 11:03:15 -04:00
|
|
|
}{
|
|
|
|
"successful create": {
|
|
|
|
applicationsAPI: stubApplicationsAPI{},
|
|
|
|
servicePrincipalsAPI: stubServicePrincipalsAPI{},
|
|
|
|
roleAssignmentsAPI: &stubRoleAssignmentsAPI{},
|
|
|
|
resourceGroupAPI: stubResourceGroupAPI{
|
|
|
|
getResourceGroup: armresources.ResourceGroup{
|
|
|
|
ID: to.StringPtr("resource-group-id"),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"failed app create": {
|
|
|
|
applicationsAPI: stubApplicationsAPI{
|
|
|
|
createErr: someErr,
|
|
|
|
},
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr: true,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
"failed service principal create": {
|
|
|
|
applicationsAPI: stubApplicationsAPI{},
|
|
|
|
servicePrincipalsAPI: stubServicePrincipalsAPI{
|
|
|
|
createErr: someErr,
|
|
|
|
},
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr: true,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
"failed role assignment": {
|
|
|
|
applicationsAPI: stubApplicationsAPI{},
|
|
|
|
servicePrincipalsAPI: stubServicePrincipalsAPI{},
|
|
|
|
roleAssignmentsAPI: &stubRoleAssignmentsAPI{
|
|
|
|
createErrors: []error{someErr},
|
|
|
|
},
|
|
|
|
resourceGroupAPI: stubResourceGroupAPI{
|
|
|
|
getResourceGroup: armresources.ResourceGroup{
|
|
|
|
ID: to.StringPtr("resource-group-id"),
|
|
|
|
},
|
|
|
|
},
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr: true,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
"failed update creds": {
|
|
|
|
applicationsAPI: stubApplicationsAPI{
|
|
|
|
updateCredentialsErr: someErr,
|
|
|
|
},
|
|
|
|
servicePrincipalsAPI: stubServicePrincipalsAPI{},
|
|
|
|
roleAssignmentsAPI: &stubRoleAssignmentsAPI{},
|
|
|
|
resourceGroupAPI: stubResourceGroupAPI{
|
|
|
|
getResourceGroup: armresources.ResourceGroup{
|
|
|
|
ID: to.StringPtr("resource-group-id"),
|
|
|
|
},
|
|
|
|
},
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr: true,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
}
|
|
|
|
for name, tc := range testCases {
|
|
|
|
t.Run(name, func(t *testing.T) {
|
|
|
|
assert := assert.New(t)
|
|
|
|
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
client := Client{
|
|
|
|
name: "name",
|
|
|
|
uid: "uid",
|
|
|
|
resourceGroup: "resource-group",
|
|
|
|
applicationsAPI: tc.applicationsAPI,
|
|
|
|
servicePrincipalsAPI: tc.servicePrincipalsAPI,
|
|
|
|
roleAssignmentsAPI: tc.roleAssignmentsAPI,
|
|
|
|
resourceGroupAPI: tc.resourceGroupAPI,
|
|
|
|
adReplicationLagCheckMaxRetries: 2,
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err := client.CreateServicePrincipal(ctx)
|
2022-04-26 10:54:05 -04:00
|
|
|
if tc.wantErr {
|
2022-03-22 11:03:15 -04:00
|
|
|
assert.Error(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
assert.NoError(err)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTerminateServicePrincipal(t *testing.T) {
|
|
|
|
someErr := errors.New("failed")
|
|
|
|
testCases := map[string]struct {
|
|
|
|
appObjectID string
|
|
|
|
applicationsAPI applicationsAPI
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr bool
|
2022-03-22 11:03:15 -04:00
|
|
|
}{
|
|
|
|
"successful terminate": {
|
|
|
|
appObjectID: "object-id",
|
|
|
|
applicationsAPI: stubApplicationsAPI{},
|
|
|
|
},
|
|
|
|
"nothing to terminate": {
|
|
|
|
applicationsAPI: stubApplicationsAPI{},
|
|
|
|
},
|
|
|
|
"failed delete": {
|
|
|
|
appObjectID: "object-id",
|
|
|
|
applicationsAPI: stubApplicationsAPI{
|
|
|
|
deleteErr: someErr,
|
|
|
|
},
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr: true,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
}
|
|
|
|
for name, tc := range testCases {
|
|
|
|
t.Run(name, func(t *testing.T) {
|
|
|
|
assert := assert.New(t)
|
|
|
|
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
client := Client{
|
|
|
|
name: "name",
|
|
|
|
uid: "uid",
|
|
|
|
resourceGroup: "resource-group",
|
|
|
|
adAppObjectID: tc.appObjectID,
|
|
|
|
applicationsAPI: tc.applicationsAPI,
|
|
|
|
}
|
|
|
|
|
|
|
|
err := client.TerminateServicePrincipal(ctx)
|
2022-04-26 10:54:05 -04:00
|
|
|
if tc.wantErr {
|
2022-03-22 11:03:15 -04:00
|
|
|
assert.Error(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
assert.NoError(err)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCreateADApplication(t *testing.T) {
|
|
|
|
someErr := errors.New("failed")
|
|
|
|
testCases := map[string]struct {
|
|
|
|
applicationsAPI applicationsAPI
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr bool
|
2022-03-22 11:03:15 -04:00
|
|
|
}{
|
|
|
|
"successful create": {
|
|
|
|
applicationsAPI: stubApplicationsAPI{},
|
|
|
|
},
|
|
|
|
"failed app create": {
|
|
|
|
applicationsAPI: stubApplicationsAPI{
|
|
|
|
createErr: someErr,
|
|
|
|
},
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr: true,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
"app create returns invalid appid": {
|
|
|
|
applicationsAPI: stubApplicationsAPI{
|
|
|
|
createApplication: &graphrbac.Application{
|
|
|
|
ObjectID: proto.String("00000000-0000-0000-0000-000000000001"),
|
|
|
|
},
|
|
|
|
},
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr: true,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
"app create returns invalid objectid": {
|
|
|
|
applicationsAPI: stubApplicationsAPI{
|
|
|
|
createApplication: &graphrbac.Application{
|
|
|
|
AppID: proto.String("00000000-0000-0000-0000-000000000000"),
|
|
|
|
},
|
|
|
|
},
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr: true,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
}
|
|
|
|
for name, tc := range testCases {
|
|
|
|
t.Run(name, func(t *testing.T) {
|
|
|
|
assert := assert.New(t)
|
|
|
|
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
client := Client{
|
|
|
|
name: "name",
|
|
|
|
uid: "uid",
|
|
|
|
applicationsAPI: tc.applicationsAPI,
|
|
|
|
}
|
|
|
|
|
|
|
|
appCredentials, err := client.createADApplication(ctx)
|
2022-04-26 10:54:05 -04:00
|
|
|
if tc.wantErr {
|
2022-03-22 11:03:15 -04:00
|
|
|
assert.Error(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
assert.NoError(err)
|
|
|
|
assert.NotNil(appCredentials)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCreateAppServicePrincipal(t *testing.T) {
|
|
|
|
someErr := errors.New("failed")
|
|
|
|
testCases := map[string]struct {
|
|
|
|
servicePrincipalsAPI servicePrincipalsAPI
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr bool
|
2022-03-22 11:03:15 -04:00
|
|
|
}{
|
|
|
|
"successful create": {
|
|
|
|
servicePrincipalsAPI: stubServicePrincipalsAPI{},
|
|
|
|
},
|
|
|
|
"failed service principal create": {
|
|
|
|
servicePrincipalsAPI: stubServicePrincipalsAPI{
|
|
|
|
createErr: someErr,
|
|
|
|
},
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr: true,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
"service principal create returns invalid objectid": {
|
|
|
|
servicePrincipalsAPI: stubServicePrincipalsAPI{
|
|
|
|
createServicePrincipal: &graphrbac.ServicePrincipal{},
|
|
|
|
},
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr: true,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
}
|
|
|
|
for name, tc := range testCases {
|
|
|
|
t.Run(name, func(t *testing.T) {
|
|
|
|
assert := assert.New(t)
|
|
|
|
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
client := Client{
|
|
|
|
name: "name",
|
|
|
|
uid: "uid",
|
|
|
|
servicePrincipalsAPI: tc.servicePrincipalsAPI,
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err := client.createAppServicePrincipal(ctx, "app-id")
|
2022-04-26 10:54:05 -04:00
|
|
|
if tc.wantErr {
|
2022-03-22 11:03:15 -04:00
|
|
|
assert.Error(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
assert.NoError(err)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestAssignOwnerOfResourceGroup(t *testing.T) {
|
|
|
|
someErr := errors.New("failed")
|
|
|
|
testCases := map[string]struct {
|
|
|
|
roleAssignmentsAPI roleAssignmentsAPI
|
|
|
|
resourceGroupAPI resourceGroupAPI
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr bool
|
2022-03-22 11:03:15 -04:00
|
|
|
}{
|
|
|
|
"successful assign": {
|
|
|
|
roleAssignmentsAPI: &stubRoleAssignmentsAPI{},
|
|
|
|
resourceGroupAPI: stubResourceGroupAPI{
|
|
|
|
getResourceGroup: armresources.ResourceGroup{
|
|
|
|
ID: to.StringPtr("resource-group-id"),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"failed role assignment": {
|
|
|
|
roleAssignmentsAPI: &stubRoleAssignmentsAPI{
|
|
|
|
createErrors: []error{someErr},
|
|
|
|
},
|
|
|
|
resourceGroupAPI: stubResourceGroupAPI{
|
|
|
|
getResourceGroup: armresources.ResourceGroup{
|
|
|
|
ID: to.StringPtr("resource-group-id"),
|
|
|
|
},
|
|
|
|
},
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr: true,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
"failed resource group get": {
|
|
|
|
roleAssignmentsAPI: &stubRoleAssignmentsAPI{},
|
|
|
|
resourceGroupAPI: stubResourceGroupAPI{
|
|
|
|
getErr: someErr,
|
|
|
|
},
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr: true,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
"resource group get returns invalid id": {
|
|
|
|
roleAssignmentsAPI: &stubRoleAssignmentsAPI{},
|
|
|
|
resourceGroupAPI: stubResourceGroupAPI{
|
|
|
|
getResourceGroup: armresources.ResourceGroup{},
|
|
|
|
},
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr: true,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
"create returns PrincipalNotFound the first time": {
|
|
|
|
roleAssignmentsAPI: &stubRoleAssignmentsAPI{
|
|
|
|
createErrors: []error{
|
|
|
|
autorest.DetailedError{Original: &azure.RequestError{
|
|
|
|
ServiceError: &azure.ServiceError{
|
|
|
|
Code: "PrincipalNotFound",
|
|
|
|
},
|
|
|
|
}},
|
|
|
|
nil,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
resourceGroupAPI: stubResourceGroupAPI{
|
|
|
|
getResourceGroup: armresources.ResourceGroup{
|
|
|
|
ID: to.StringPtr("resource-group-id"),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"create does not return request error": {
|
|
|
|
roleAssignmentsAPI: &stubRoleAssignmentsAPI{
|
|
|
|
createErrors: []error{autorest.DetailedError{Original: someErr}},
|
|
|
|
},
|
|
|
|
resourceGroupAPI: stubResourceGroupAPI{
|
|
|
|
getResourceGroup: armresources.ResourceGroup{
|
|
|
|
ID: to.StringPtr("resource-group-id"),
|
|
|
|
},
|
|
|
|
},
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr: true,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
"create service error code is unknown": {
|
|
|
|
roleAssignmentsAPI: &stubRoleAssignmentsAPI{
|
|
|
|
createErrors: []error{
|
|
|
|
autorest.DetailedError{Original: &azure.RequestError{
|
|
|
|
ServiceError: &azure.ServiceError{
|
|
|
|
Code: "some-unknown-error-code",
|
|
|
|
},
|
|
|
|
}},
|
|
|
|
nil,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
resourceGroupAPI: stubResourceGroupAPI{
|
|
|
|
getResourceGroup: armresources.ResourceGroup{
|
|
|
|
ID: to.StringPtr("resource-group-id"),
|
|
|
|
},
|
|
|
|
},
|
2022-04-26 10:54:05 -04:00
|
|
|
wantErr: true,
|
2022-03-22 11:03:15 -04:00
|
|
|
},
|
|
|
|
}
|
|
|
|
for name, tc := range testCases {
|
|
|
|
t.Run(name, func(t *testing.T) {
|
|
|
|
assert := assert.New(t)
|
|
|
|
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
client := Client{
|
|
|
|
name: "name",
|
|
|
|
uid: "uid",
|
|
|
|
resourceGroup: "resource-group",
|
|
|
|
roleAssignmentsAPI: tc.roleAssignmentsAPI,
|
|
|
|
resourceGroupAPI: tc.resourceGroupAPI,
|
|
|
|
adReplicationLagCheckMaxRetries: 2,
|
|
|
|
}
|
|
|
|
|
|
|
|
err := client.assignResourceGroupRole(ctx, "principal-id", "role-definition-id")
|
2022-04-26 10:54:05 -04:00
|
|
|
if tc.wantErr {
|
2022-03-22 11:03:15 -04:00
|
|
|
assert.Error(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
assert.NoError(err)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestConvertToCloudServiceAccountURI(t *testing.T) {
|
|
|
|
assert := assert.New(t)
|
|
|
|
require := require.New(t)
|
|
|
|
key := ApplicationCredentials{
|
2022-03-28 06:24:41 -04:00
|
|
|
TenantID: "tenant-id",
|
2022-03-22 11:03:15 -04:00
|
|
|
ClientID: "client-id",
|
|
|
|
ClientSecret: "client-secret",
|
2022-03-29 11:31:18 -04:00
|
|
|
Location: "location",
|
2022-03-22 11:03:15 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
cloudServiceAccountURI := key.ConvertToCloudServiceAccountURI()
|
|
|
|
uri, err := url.Parse(cloudServiceAccountURI)
|
|
|
|
require.NoError(err)
|
|
|
|
query := uri.Query()
|
|
|
|
assert.Equal("serviceaccount", uri.Scheme)
|
|
|
|
assert.Equal("azure", uri.Host)
|
|
|
|
assert.Equal(url.Values{
|
2022-03-28 06:24:41 -04:00
|
|
|
"tenant_id": []string{"tenant-id"},
|
2022-03-22 11:03:15 -04:00
|
|
|
"client_id": []string{"client-id"},
|
|
|
|
"client_secret": []string{"client-secret"},
|
2022-03-29 11:31:18 -04:00
|
|
|
"location": []string{"location"},
|
2022-03-22 11:03:15 -04:00
|
|
|
}, query)
|
|
|
|
}
|