-
Notifications
You must be signed in to change notification settings - Fork 169
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Dynamic validation of subscription level registrations at the RP
- Loading branch information
Showing
40 changed files
with
3,393 additions
and
60 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
package frontend | ||
|
||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the Apache License 2.0. | ||
|
||
import ( | ||
"context" | ||
"testing" | ||
|
||
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armfeatures" | ||
"github.com/golang/mock/gomock" | ||
|
||
"github.com/Azure/ARO-RP/pkg/api" | ||
mock_features "github.com/Azure/ARO-RP/pkg/util/mocks/azureclient/mgmt/features" | ||
utilerror "github.com/Azure/ARO-RP/test/util/error" | ||
) | ||
|
||
func TestValidateEncryptionAtHost(t *testing.T) { | ||
EncryptionAtHostEnabledOrDisabled := func(MasterProfile api.MasterProfile, WorkerProfiles []api.WorkerProfile) *api.OpenShiftCluster { | ||
return &api.OpenShiftCluster{ | ||
Properties: api.OpenShiftClusterProperties{ | ||
MasterProfile: MasterProfile, | ||
WorkerProfiles: WorkerProfiles, | ||
}, | ||
} | ||
} | ||
|
||
EncryptionAtHostFeatureEnabledOrDisabled := func(state armfeatures.SubscriptionFeatureRegistrationState) *armfeatures.SubscriptionFeatureRegistrationsClientGetResponse { | ||
return &armfeatures.SubscriptionFeatureRegistrationsClientGetResponse{ | ||
SubscriptionFeatureRegistration: armfeatures.SubscriptionFeatureRegistration{ | ||
Properties: &armfeatures.SubscriptionFeatureRegistrationProperties{ | ||
State: &state, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
for _, tt := range []struct { | ||
name string | ||
oc *api.OpenShiftCluster | ||
mockResponse *armfeatures.SubscriptionFeatureRegistrationsClientGetResponse | ||
mockErr error | ||
wantErr string | ||
}{ | ||
{ | ||
name: "encryption at host disabled - feature isn't registered", | ||
oc: EncryptionAtHostEnabledOrDisabled(api.MasterProfile{EncryptionAtHost: api.EncryptionAtHostDisabled}, []api.WorkerProfile{{EncryptionAtHost: api.EncryptionAtHostDisabled}}), | ||
mockResponse: EncryptionAtHostFeatureEnabledOrDisabled(armfeatures.SubscriptionFeatureRegistrationStateNotRegistered), | ||
}, | ||
{ | ||
name: "encryption at host disabled - feature is registered", | ||
oc: EncryptionAtHostEnabledOrDisabled(api.MasterProfile{EncryptionAtHost: api.EncryptionAtHostDisabled}, []api.WorkerProfile{{EncryptionAtHost: api.EncryptionAtHostDisabled}}), | ||
mockResponse: EncryptionAtHostFeatureEnabledOrDisabled(armfeatures.SubscriptionFeatureRegistrationStateRegistered), | ||
}, | ||
{ | ||
name: "encryption at host enabled - feature is registered", | ||
oc: EncryptionAtHostEnabledOrDisabled(api.MasterProfile{EncryptionAtHost: api.EncryptionAtHostEnabled}, []api.WorkerProfile{{EncryptionAtHost: api.EncryptionAtHostEnabled}}), | ||
mockResponse: EncryptionAtHostFeatureEnabledOrDisabled(armfeatures.SubscriptionFeatureRegistrationStateRegistered), | ||
}, | ||
{ | ||
name: "encryption at host enabled - feature isn't registered", | ||
oc: EncryptionAtHostEnabledOrDisabled(api.MasterProfile{EncryptionAtHost: api.EncryptionAtHostEnabled}, []api.WorkerProfile{{EncryptionAtHost: api.EncryptionAtHostEnabled}}), | ||
mockResponse: EncryptionAtHostFeatureEnabledOrDisabled(armfeatures.SubscriptionFeatureRegistrationStateNotRegistered), | ||
wantErr: "400: InvalidParameter: armfeatures.SubscriptionFeatureRegistrationProperties: Microsoft.Compute/EncryptionAtHost feature is not enabled for this subscription. Register the feature using 'az feature register --namespace Microsoft.Compute --name EncryptionAtHost'", | ||
}, | ||
{ | ||
name: "MasterProfile encryption at host enabled - feature isn't registered", | ||
oc: EncryptionAtHostEnabledOrDisabled(api.MasterProfile{EncryptionAtHost: api.EncryptionAtHostEnabled}, []api.WorkerProfile{{EncryptionAtHost: api.EncryptionAtHostDisabled}}), | ||
mockResponse: EncryptionAtHostFeatureEnabledOrDisabled(armfeatures.SubscriptionFeatureRegistrationStateNotRegistered), | ||
wantErr: "400: InvalidParameter: armfeatures.SubscriptionFeatureRegistrationProperties: Microsoft.Compute/EncryptionAtHost feature is not enabled for this subscription. Register the feature using 'az feature register --namespace Microsoft.Compute --name EncryptionAtHost'", | ||
}, | ||
{ | ||
name: "WorkerProfile encryption at host enabled - feature isn't registered", | ||
oc: EncryptionAtHostEnabledOrDisabled(api.MasterProfile{EncryptionAtHost: api.EncryptionAtHostDisabled}, []api.WorkerProfile{{EncryptionAtHost: api.EncryptionAtHostEnabled}}), | ||
mockResponse: EncryptionAtHostFeatureEnabledOrDisabled(armfeatures.SubscriptionFeatureRegistrationStateNotRegistered), | ||
wantErr: "400: InvalidParameter: armfeatures.SubscriptionFeatureRegistrationProperties: Microsoft.Compute/EncryptionAtHost feature is not enabled for this subscription. Register the feature using 'az feature register --namespace Microsoft.Compute --name EncryptionAtHost'", | ||
}, | ||
} { | ||
t.Run(tt.name, func(t *testing.T) { | ||
controller := gomock.NewController(t) | ||
defer controller.Finish() | ||
|
||
subFeatureRegistrationsClient := mock_features.NewMockSubscriptionFeatureRegistrationsClient(controller) | ||
subFeatureRegistrationsClient.EXPECT().Get(gomock.Any(), "Microsoft.Compute", "EncryptionAtHost", gomock.Any()).Return(*tt.mockResponse, tt.mockErr).AnyTimes() | ||
|
||
err := validateEncryptionAtHost(context.Background(), subFeatureRegistrationsClient, tt.oc) | ||
utilerror.AssertErrorMessage(t, err, tt.wantErr) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
package frontend | ||
|
||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the Apache License 2.0. | ||
|
||
import ( | ||
"context" | ||
"net/http" | ||
|
||
"github.com/Azure/azure-sdk-for-go/sdk/azidentity" | ||
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armfeatures" | ||
|
||
"github.com/Azure/ARO-RP/pkg/api" | ||
"github.com/Azure/ARO-RP/pkg/util/azureclient/mgmt/features" | ||
) | ||
|
||
type EncryptionAtHostValidator interface { | ||
ValidateEncryptionAtHost(ctx context.Context, subscriptionID string, oc *api.OpenShiftCluster) error | ||
} | ||
|
||
type encryptionAtHostValidator struct{} | ||
|
||
func (e encryptionAtHostValidator) ValidateEncryptionAtHost(ctx context.Context, subscriptionID string, oc *api.OpenShiftCluster) error { | ||
credential, err := azidentity.NewDefaultAzureCredential(nil) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
subFeatureRegistrationsClient, err := armfeatures.NewSubscriptionFeatureRegistrationsClient(subscriptionID, credential, nil) | ||
if err != nil { | ||
return err | ||
} | ||
return validateEncryptionAtHost(ctx, subFeatureRegistrationsClient, oc) | ||
} | ||
|
||
func validateEncryptionAtHost(ctx context.Context, subFeatureRegistrationsClient features.SubscriptionFeatureRegistrationsClient, oc *api.OpenShiftCluster) error { | ||
encryptionSettings := make(map[api.EncryptionAtHost]bool) | ||
|
||
encryptionSettings[oc.Properties.MasterProfile.EncryptionAtHost] = true | ||
|
||
for _, wp := range oc.Properties.WorkerProfiles { | ||
encryptionSettings[wp.EncryptionAtHost] = true | ||
} | ||
|
||
for setting := range encryptionSettings { | ||
if setting == api.EncryptionAtHostEnabled { | ||
if err := IsRegisteredForEncryptionAtHostFeature(ctx, subFeatureRegistrationsClient); err != nil { | ||
return err | ||
} | ||
|
||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func IsRegisteredForEncryptionAtHostFeature(ctx context.Context, subFeatureRegistrationsClient features.SubscriptionFeatureRegistrationsClient) error { | ||
response, err := subFeatureRegistrationsClient.Get(ctx, "Microsoft.Compute", "EncryptionAtHost", nil) | ||
if err != nil { | ||
return err | ||
} | ||
if *response.Properties.State == armfeatures.SubscriptionFeatureRegistrationStateRegistered { | ||
return nil | ||
} | ||
return &api.CloudError{ | ||
StatusCode: http.StatusBadRequest, | ||
CloudErrorBody: &api.CloudErrorBody{ | ||
Code: api.CloudErrorCodeInvalidParameter, | ||
Message: "Microsoft.Compute/EncryptionAtHost feature is not enabled for this subscription. Register the feature using 'az feature register --namespace Microsoft.Compute --name EncryptionAtHost'", | ||
Target: "armfeatures.SubscriptionFeatureRegistrationProperties", | ||
}, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
15 changes: 15 additions & 0 deletions
15
pkg/util/azureclient/mgmt/features/subscriptionfeatureregistrations.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package features | ||
|
||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the Apache License 2.0. | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armfeatures" | ||
) | ||
|
||
// SubscriptionFeatureRegistrationsClient is a minimal interface for azure SubscriptionFeatureRegistrationsClient | ||
type SubscriptionFeatureRegistrationsClient interface { | ||
Get(ctx context.Context, providerNamespace string, featureName string, options *armfeatures.SubscriptionFeatureRegistrationsClientGetOptions) (armfeatures.SubscriptionFeatureRegistrationsClientGetResponse, error) | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.