Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
support for managed cluster security profile
Browse files Browse the repository at this point in the history
LochanRn committed Dec 2, 2023
1 parent c0c4670 commit e5ab8f5
Showing 9 changed files with 1,395 additions and 2 deletions.
20 changes: 20 additions & 0 deletions api/v1beta1/azuremanagedcontrolplane_default.go
Original file line number Diff line number Diff line change
@@ -198,3 +198,23 @@ func (m *AzureManagedControlPlane) setDefaultDNSPrefix() {
m.Spec.DNSPrefix = ptr.To(m.Name)
}
}

func (m *AzureManagedControlPlane) setDefaultSecurityProfile() {
if m.Spec.SecurityProfile == nil {
return
}
m.setDefaultAzureKeyVaultKms()
m.setDefaultImageCleaner()
}

func (m *AzureManagedControlPlane) setDefaultAzureKeyVaultKms() {
if m.Spec.SecurityProfile.AzureKeyVaultKms != nil && m.Spec.SecurityProfile.AzureKeyVaultKms.KeyVaultNetworkAccess == nil {
m.Spec.SecurityProfile.AzureKeyVaultKms.KeyVaultNetworkAccess = ptr.To(KeyVaultNetworkAccessTypesPublic)
}
}

func (m *AzureManagedControlPlane) setDefaultImageCleaner() {
if m.Spec.SecurityProfile.ImageCleaner != nil && m.Spec.SecurityProfile.ImageCleaner.IntervalHours == nil {
m.Spec.SecurityProfile.ImageCleaner.IntervalHours = ptr.To(int32(24))
}
}
95 changes: 95 additions & 0 deletions api/v1beta1/azuremanagedcontrolplane_types.go
Original file line number Diff line number Diff line change
@@ -80,6 +80,18 @@ const (
LoadBalancerSKUBasic = "Basic"
)

// KeyVaultNetworkAccessTypes defines the types of network access of key vault.
// The possible values are Public and Private.
type KeyVaultNetworkAccessTypes string

const (
// KeyVaultNetworkAccessTypesPrivate means the key vault disables public access and enables private link. The default value is Public.
KeyVaultNetworkAccessTypesPrivate KeyVaultNetworkAccessTypes = "Private"

// KeyVaultNetworkAccessTypesPublic means the key vault allows public access from all networks.
KeyVaultNetworkAccessTypesPublic KeyVaultNetworkAccessTypes = "Public"
)

// AzureManagedControlPlaneSpec defines the desired state of AzureManagedControlPlane.
type AzureManagedControlPlaneSpec struct {
AzureManagedControlPlaneClassSpec `json:",inline"`
@@ -110,6 +122,89 @@ type AzureManagedControlPlaneSpec struct {
// Immutable.
// +optional
DNSPrefix *string `json:"dnsPrefix,omitempty"`

// SecurityProfile defines the security profile for the container service cluster.
// +optional
SecurityProfile *ManagedClusterSecurityProfile `json:"securityProfile,omitempty"`
}

// ManagedClusterSecurityProfile defines the security profile for the container service cluster.
type ManagedClusterSecurityProfile struct {
// AzureKeyVaultKms defines Azure Key Vault key management service settings for the security profile.
// +optional
AzureKeyVaultKms *AzureKeyVaultKms `json:"azureKeyVaultKms,omitempty"`

// Defender defines Microsoft Defender settings for the security profile.
// +optional
Defender *ManagedClusterSecurityProfileDefender `json:"defender,omitempty"`

// ImageCleaner settings for the security profile.
// +optional
ImageCleaner *ManagedClusterSecurityProfileImageCleaner `json:"imageCleaner,omitempty"`

// Workloadidentity enables Kubernetes applications to access Azure cloud resources securely with Azure AD. Ensure to enable OIDC issuer while enabling Workload Identity
// +optional
WorkloadIdentity *ManagedClusterSecurityProfileWorkloadIdentity `json:"workloadIdentity,omitempty"`
}

// ManagedClusterSecurityProfileDefender defines Microsoft Defender settings for the security profile.
type ManagedClusterSecurityProfileDefender struct {
// LogAnalyticsWorkspaceResourceID is the ID of the Log Analytics workspace that has to be associated with Microsoft Defender.
// When Microsoft Defender is enabled, this field is required and must be a valid workspace resource ID.
// +kubebuilder:validation:Required
LogAnalyticsWorkspaceResourceID string `json:"logAnalyticsWorkspaceResourceID"`

// SecurityMonitoring profile defines the Microsoft Defender threat detection for Cloud settings for the security profile.
// +kubebuilder:validation:Required
SecurityMonitoring ManagedClusterSecurityProfileDefenderSecurityMonitoring `json:"securityMonitoring"`
}

// ManagedClusterSecurityProfileDefenderSecurityMonitoring settings for the security profile threat detection.
type ManagedClusterSecurityProfileDefenderSecurityMonitoring struct {
// Enabled enables Defender threat detection
// +kubebuilder:validation:Required
Enabled bool `json:"enabled"`
}

// ManagedClusterSecurityProfileImageCleaner removes unused images from nodes, freeing up disk space and helping to reduce attack surface area.
type ManagedClusterSecurityProfileImageCleaner struct {
// Enabled enables the Image Cleaner on AKS cluster.
// +kubebuilder:validation:Required
Enabled bool `json:"enabled"`

// IntervalHours defines Image Cleaner scanning interval in hours. Default value is 24 hours.
// +optional
IntervalHours *int32 `json:"intervalHours,omitempty"`
}

// ManagedClusterSecurityProfileWorkloadIdentity settings for the security profile.
type ManagedClusterSecurityProfileWorkloadIdentity struct {
// Enabled enables the workload identity.
// +kubebuilder:validation:Required
Enabled bool `json:"enabled"`
}

// AzureKeyVaultKms service settings for the security profile.
type AzureKeyVaultKms struct {
// Enabled enables the Azure Key Vault key management service. The default is false.
// +kubebuilder:validation:Required
Enabled bool `json:"enabled"`

// KeyID defines the Identifier of Azure Key Vault key.
// When Azure Key Vault key management service is enabled, this field is required and must be a valid key identifier.
// +kubebuilder:validation:Required
KeyID string `json:"keyID"`

// KeyVaultNetworkAccess defines the network access of key vault.
// The possible values are Public and Private.
// Public means the key vault allows public access from all networks.
// Private means the key vault disables public access and enables private link. The default value is Public.
// +optional
KeyVaultNetworkAccess *KeyVaultNetworkAccessTypes `json:"keyVaultNetworkAccess,omitempty"`

// KeyVaultResourceID is the Resource ID of key vault. When keyVaultNetworkAccess is Private, this field is required and must be a valid resource ID.
// +optional
KeyVaultResourceID *string `json:"keyVaultResourceID,omitempty"`
}

// HTTPProxyConfig is the HTTP proxy configuration for the cluster.
179 changes: 177 additions & 2 deletions api/v1beta1/azuremanagedcontrolplane_webhook.go
Original file line number Diff line number Diff line change
@@ -94,6 +94,7 @@ func (mw *azureManagedControlPlaneWebhook) Default(ctx context.Context, obj runt
m.setDefaultSubnet()
m.setDefaultOIDCIssuerProfile()
m.setDefaultDNSPrefix()
m.setDefaultSecurityProfile()

return nil
}
@@ -249,6 +250,10 @@ func (mw *azureManagedControlPlaneWebhook) ValidateUpdate(ctx context.Context, o
allErrs = append(allErrs, errs...)
}

if errs := m.validateSecurityProfileUpdate(old); len(errs) > 0 {
allErrs = append(allErrs, errs...)
}

if len(allErrs) == 0 {
return nil, m.Validate(mw.Client)
}
@@ -271,6 +276,7 @@ func (m *AzureManagedControlPlane) Validate(cli client.Client) error {
m.validateNetworkPluginMode,
m.validateDNSPrefix,
m.validateDisableLocalAccounts,
m.validateSecurityProfile,
}
for _, validator := range validators {
if err := validator(cli); err != nil {
@@ -321,6 +327,79 @@ func (m *AzureManagedControlPlane) validateDNSPrefix(_ client.Client) field.Erro
return allErrs
}

// validateSecurityProfile validates SecurityProfile.
func (m *AzureManagedControlPlane) validateSecurityProfile(_ client.Client) field.ErrorList {
if err := m.validateAzureKeyVaultKms(); err != nil {
return err
}
if err := m.validateWorkloadIdentity(); err != nil {
return err
}
if err := m.validateImageCleaner(); err != nil {
return err
}
return nil
}

// validateAzureKeyVaultKms validates AzureKeyVaultKms.
func (m *AzureManagedControlPlane) validateAzureKeyVaultKms() field.ErrorList {
if m.Spec.SecurityProfile != nil && m.Spec.SecurityProfile.AzureKeyVaultKms != nil {
if !m.IsUserManagedIdentityEnabled() {
allErrs := field.ErrorList{
field.Invalid(field.NewPath("Spec", "SecurityProfile", "AzureKeyVaultKms", "KeyVaultResourceID"),
m.Spec.SecurityProfile.AzureKeyVaultKms.KeyVaultResourceID,
"Spec.SecurityProfile.AzureKeyVaultKms can be set only when Spec.Identity.Type is UserAssigned"),
}
return allErrs
}
keyVaultNetworkAccess := ptr.Deref(m.Spec.SecurityProfile.AzureKeyVaultKms.KeyVaultNetworkAccess, KeyVaultNetworkAccessTypesPublic)
keyVaultResourceID := ptr.Deref(m.Spec.SecurityProfile.AzureKeyVaultKms.KeyVaultResourceID, "")
if keyVaultNetworkAccess == KeyVaultNetworkAccessTypesPrivate && keyVaultResourceID == "" {
allErrs := field.ErrorList{
field.Invalid(field.NewPath("Spec", "SecurityProfile", "AzureKeyVaultKms", "KeyVaultResourceID"),
m.Spec.SecurityProfile.AzureKeyVaultKms.KeyVaultResourceID,
"Spec.SecurityProfile.AzureKeyVaultKms.KeyVaultResourceID cannot be empty when Spec.SecurityProfile.AzureKeyVaultKms.KeyVaultNetworkAccess is Private"),
}
return allErrs
}
if keyVaultNetworkAccess == KeyVaultNetworkAccessTypesPublic && keyVaultResourceID != "" {
allErrs := field.ErrorList{
field.Invalid(field.NewPath("Spec", "SecurityProfile", "AzureKeyVaultKms", "KeyVaultResourceID"), m.Spec.SecurityProfile.AzureKeyVaultKms.KeyVaultResourceID,
"Spec.SecurityProfile.AzureKeyVaultKms.KeyVaultResourceID should be empty when Spec.SecurityProfile.AzureKeyVaultKms.KeyVaultNetworkAccess is Public"),
}
return allErrs
}
}
return nil
}

// validateWorkloadIdentity validates WorkloadIdentity.
func (m *AzureManagedControlPlane) validateWorkloadIdentity() field.ErrorList {
if m.Spec.SecurityProfile != nil && m.Spec.SecurityProfile.WorkloadIdentity != nil && !m.IsOIDCEnabled() {
allErrs := field.ErrorList{
field.Invalid(field.NewPath("Spec", "SecurityProfile", "WorkloadIdentity"), m.Spec.SecurityProfile.WorkloadIdentity,
"Spec.SecurityProfile.WorkloadIdentity cannot be enabled when Spec.OIDCIssuerProfile is disabled"),
}
return allErrs
}
return nil
}

// validateWorkloadIdentity validates WorkloadIdentity.
func (m *AzureManagedControlPlane) validateImageCleaner() field.ErrorList {
if m.Spec.SecurityProfile != nil && m.Spec.SecurityProfile.ImageCleaner != nil {
intervalHours := ptr.Deref(m.Spec.SecurityProfile.ImageCleaner.IntervalHours, 0)
if intervalHours < 24 || intervalHours > 2160 {
allErrs := field.ErrorList{
field.Invalid(field.NewPath("Spec", "SecurityProfile", "ImageCleaner", "IntervalHours"), m.Spec.SecurityProfile.ImageCleaner.IntervalHours,
"Spec.SecurityProfile.ImageCleaner.IntervalHours is out of range [24 - 2160]"),
}
return allErrs
}
}
return nil
}

// validateVersion disabling local accounts for AAD based clusters.
func (m *AzureManagedControlPlane) validateDisableLocalAccounts(_ client.Client) field.ErrorList {
if m.Spec.DisableLocalAccounts != nil && m.Spec.AADProfile == nil {
@@ -657,10 +736,85 @@ func (m *AzureManagedControlPlane) validateAADProfileUpdateAndLocalAccounts(old
return allErrs
}

// validateSecurityProfileUpdate validates an SecurityProfileUpdate.
func (m *AzureManagedControlPlane) validateSecurityProfileUpdate(old *AzureManagedControlPlane) field.ErrorList {
var allErrs field.ErrorList
if old.Spec.SecurityProfile != nil {
if errAzureKeyVaultKms := m.validateAzureKeyVaultKmsUpdate(old); errAzureKeyVaultKms != nil {
allErrs = append(allErrs, errAzureKeyVaultKms...)
}
if errWorkloadIdentity := m.validateWorkloadIdentityUpdate(old); errWorkloadIdentity != nil {
allErrs = append(allErrs, errWorkloadIdentity...)
}
if errWorkloadIdentity := m.validateImageCleanerUpdate(old); errWorkloadIdentity != nil {
allErrs = append(allErrs, errWorkloadIdentity...)
}
if errWorkloadIdentity := m.validateDefender(old); errWorkloadIdentity != nil {
allErrs = append(allErrs, errWorkloadIdentity...)
}
}
return allErrs
}

// validateAzureKeyVaultKmsUpdate validates AzureKeyVaultKmsUpdate profile.
func (m *AzureManagedControlPlane) validateAzureKeyVaultKmsUpdate(old *AzureManagedControlPlane) field.ErrorList {
var allErrs field.ErrorList
if old.Spec.SecurityProfile.AzureKeyVaultKms != nil {
if m.Spec.SecurityProfile == nil || m.Spec.SecurityProfile.AzureKeyVaultKms == nil {
allErrs = append(allErrs, field.Invalid(field.NewPath("Spec", "SecurityProfile", "AzureKeyVaultKms"),
nil, "cannot unset Spec.SecurityProfile.AzureKeyVaultKms profile"))
return allErrs
}
if err := webhookutils.ValidateImmutable(
field.NewPath("Spec", "SecurityProfile", "AzureKeyVaultKms"),
old.Spec.SecurityProfile.AzureKeyVaultKms,
m.Spec.SecurityProfile.AzureKeyVaultKms,
); err != nil {
allErrs = append(allErrs, err)
}
}
return allErrs
}

// validateWorkloadIdentityUpdate validates WorkloadIdentityUpdate profile.
func (m *AzureManagedControlPlane) validateWorkloadIdentityUpdate(old *AzureManagedControlPlane) field.ErrorList {
var allErrs field.ErrorList
if old.Spec.SecurityProfile.WorkloadIdentity != nil {
if m.Spec.SecurityProfile == nil || m.Spec.SecurityProfile.WorkloadIdentity == nil {
allErrs = append(allErrs, field.Invalid(field.NewPath("Spec", "SecurityProfile", "WorkloadIdentity"),
nil, "cannot unset Spec.SecurityProfile.WorkloadIdentity"))
}
}
return allErrs
}

// validateImageCleanerUpdate validates ImageCleanerUpdate profile.
func (m *AzureManagedControlPlane) validateImageCleanerUpdate(old *AzureManagedControlPlane) field.ErrorList {
var allErrs field.ErrorList
if old.Spec.SecurityProfile.ImageCleaner != nil {
if m.Spec.SecurityProfile == nil || m.Spec.SecurityProfile.ImageCleaner == nil {
allErrs = append(allErrs, field.Invalid(field.NewPath("Spec", "SecurityProfile", "WorkloadIdentity"),
nil, "cannot unset Spec.SecurityProfile.validateImageCleaner"))
}
}
return allErrs
}

// validateDefender validates defender profile.
func (m *AzureManagedControlPlane) validateDefender(old *AzureManagedControlPlane) field.ErrorList {
var allErrs field.ErrorList
if old.Spec.SecurityProfile.Defender != nil {
if m.Spec.SecurityProfile == nil || m.Spec.SecurityProfile.Defender == nil {
allErrs = append(allErrs, field.Invalid(field.NewPath("Spec", "SecurityProfile", "WorkloadIdentity"),
nil, "cannot unset Spec.SecurityProfile.validateDefender"))
}
}
return allErrs
}

// validateOIDCIssuerProfile validates an OIDCIssuerProfile.
func (m *AzureManagedControlPlane) validateOIDCIssuerProfileUpdate(old *AzureManagedControlPlane) field.ErrorList {
var allErrs field.ErrorList

if m.Spec.OIDCIssuerProfile != nil && old.Spec.OIDCIssuerProfile != nil {
if m.Spec.OIDCIssuerProfile.Enabled != nil && old.Spec.OIDCIssuerProfile.Enabled != nil &&
!*m.Spec.OIDCIssuerProfile.Enabled && *old.Spec.OIDCIssuerProfile.Enabled {
@@ -672,7 +826,6 @@ func (m *AzureManagedControlPlane) validateOIDCIssuerProfileUpdate(old *AzureMan
)
}
}

return allErrs
}

@@ -865,3 +1018,25 @@ func (m *AzureManagedControlPlane) validateNetworkPluginMode(_ client.Client) fi

return nil
}

// IsOIDCEnabled return true if OIDC issuer is enabled.
func (m *AzureManagedControlPlane) IsOIDCEnabled() bool {
if m.Spec.OIDCIssuerProfile == nil {
return false
}
if m.Spec.OIDCIssuerProfile.Enabled == nil {
return false
}

Check warning on line 1029 in api/v1beta1/azuremanagedcontrolplane_webhook.go

Codecov / codecov/patch

api/v1beta1/azuremanagedcontrolplane_webhook.go#L1028-L1029

Added lines #L1028 - L1029 were not covered by tests
return *m.Spec.OIDCIssuerProfile.Enabled
}

// IsUserManagedIdentityEnabled checks if user assigned identity is set.
func (m *AzureManagedControlPlane) IsUserManagedIdentityEnabled() bool {
if m.Spec.Identity == nil {
return false
}
if m.Spec.Identity.Type != ManagedControlPlaneIdentityTypeUserAssigned {
return false
}

Check warning on line 1040 in api/v1beta1/azuremanagedcontrolplane_webhook.go

Codecov / codecov/patch

api/v1beta1/azuremanagedcontrolplane_webhook.go#L1039-L1040

Added lines #L1039 - L1040 were not covered by tests
return true
}
755 changes: 755 additions & 0 deletions api/v1beta1/azuremanagedcontrolplane_webhook_test.go

Large diffs are not rendered by default.

131 changes: 131 additions & 0 deletions api/v1beta1/zz_generated.deepcopy.go
45 changes: 45 additions & 0 deletions azure/scope/managedcontrolplane.go
Original file line number Diff line number Diff line change
@@ -621,9 +621,54 @@
}
}

if s.ControlPlane.Spec.SecurityProfile != nil {
managedClusterSpec.SecurityProfile = s.GetManagedClusterSecurityProfile()
}

Check warning on line 626 in azure/scope/managedcontrolplane.go

Codecov / codecov/patch

azure/scope/managedcontrolplane.go#L625-L626

Added lines #L625 - L626 were not covered by tests

return &managedClusterSpec
}

// GetManagedClusterSecurityProfile gets the security profile for managed cluster.
func (s *ManagedControlPlaneScope) GetManagedClusterSecurityProfile() *managedclusters.ManagedClusterSecurityProfile {
securityProfile := &managedclusters.ManagedClusterSecurityProfile{}
if s.ControlPlane.Spec.SecurityProfile.AzureKeyVaultKms != nil {
securityProfile.AzureKeyVaultKms = &managedclusters.AzureKeyVaultKms{
Enabled: ptr.To(s.ControlPlane.Spec.SecurityProfile.AzureKeyVaultKms.Enabled),
KeyID: ptr.To(s.ControlPlane.Spec.SecurityProfile.AzureKeyVaultKms.KeyID),
}
if s.ControlPlane.Spec.SecurityProfile.AzureKeyVaultKms.KeyVaultNetworkAccess != nil {
securityProfile.AzureKeyVaultKms.KeyVaultNetworkAccess = s.ControlPlane.Spec.SecurityProfile.AzureKeyVaultKms.KeyVaultNetworkAccess
}
if s.ControlPlane.Spec.SecurityProfile.AzureKeyVaultKms.KeyVaultResourceID != nil {
securityProfile.AzureKeyVaultKms.KeyVaultResourceID = s.ControlPlane.Spec.SecurityProfile.AzureKeyVaultKms.KeyVaultResourceID
}

Check warning on line 644 in azure/scope/managedcontrolplane.go

Codecov / codecov/patch

azure/scope/managedcontrolplane.go#L632-L644

Added lines #L632 - L644 were not covered by tests
}

if s.ControlPlane.Spec.SecurityProfile.Defender != nil {
securityProfile.Defender = &managedclusters.ManagedClusterSecurityProfileDefender{
LogAnalyticsWorkspaceResourceID: ptr.To(s.ControlPlane.Spec.SecurityProfile.Defender.LogAnalyticsWorkspaceResourceID),
SecurityMonitoring: &managedclusters.ManagedClusterSecurityProfileDefenderSecurityMonitoring{
Enabled: ptr.To(s.ControlPlane.Spec.SecurityProfile.Defender.SecurityMonitoring.Enabled),
},
}
}

Check warning on line 654 in azure/scope/managedcontrolplane.go

Codecov / codecov/patch

azure/scope/managedcontrolplane.go#L647-L654

Added lines #L647 - L654 were not covered by tests

if s.ControlPlane.Spec.SecurityProfile.ImageCleaner != nil {
securityProfile.ImageCleaner = &managedclusters.ManagedClusterSecurityProfileImageCleaner{
Enabled: ptr.To(s.ControlPlane.Spec.SecurityProfile.ImageCleaner.Enabled),
IntervalHours: s.ControlPlane.Spec.SecurityProfile.ImageCleaner.IntervalHours,
}
}

Check warning on line 661 in azure/scope/managedcontrolplane.go

Codecov / codecov/patch

azure/scope/managedcontrolplane.go#L656-L661

Added lines #L656 - L661 were not covered by tests

if s.ControlPlane.Spec.SecurityProfile.WorkloadIdentity != nil {
securityProfile.WorkloadIdentity = &managedclusters.ManagedClusterSecurityProfileWorkloadIdentity{
Enabled: ptr.To(s.ControlPlane.Spec.SecurityProfile.WorkloadIdentity.Enabled),
}
}

Check warning on line 667 in azure/scope/managedcontrolplane.go

Codecov / codecov/patch

azure/scope/managedcontrolplane.go#L663-L667

Added lines #L663 - L667 were not covered by tests

return securityProfile

Check warning on line 669 in azure/scope/managedcontrolplane.go

Codecov / codecov/patch

azure/scope/managedcontrolplane.go#L669

Added line #L669 was not covered by tests
}

// GetAllAgentPoolSpecs gets a slice of azure.AgentPoolSpec for the list of agent pools.
func (s *ManagedControlPlaneScope) GetAllAgentPoolSpecs() ([]azure.ASOResourceSpecGetter[*asocontainerservicev1.ManagedClustersAgentPool], error) {
var (
86 changes: 86 additions & 0 deletions azure/services/managedclusters/spec.go
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@
"fmt"
"net"

"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice/v4"
asocontainerservicev1 "github.com/Azure/azure-service-operator/v2/api/containerservice/v1api20230201"
"github.com/Azure/azure-service-operator/v2/pkg/genruntime"
"github.com/pkg/errors"
@@ -130,6 +131,9 @@

// DisableLocalAccounts disables getting static credentials for this cluster when set. Expected to only be used for AAD clusters.
DisableLocalAccounts *bool

// SecurityProfile defines the security profile for the container service cluster.
SecurityProfile *ManagedClusterSecurityProfile
}

// HTTPProxyConfig is the HTTP proxy configuration for the cluster.
@@ -261,6 +265,71 @@
}
}

// ManagedClusterSecurityProfile defines the security profile for the container service cluster.
type ManagedClusterSecurityProfile struct {
// AzureKeyVaultKms defines Azure Key Vault key management service settings for the security profile.
AzureKeyVaultKms *AzureKeyVaultKms

// Defender defines Microsoft Defender settings for the security profile.
Defender *ManagedClusterSecurityProfileDefender

// ImageCleaner settings for the security profile.
ImageCleaner *ManagedClusterSecurityProfileImageCleaner

// Workloadidentity enables Kubernetes applications to access Azure cloud resources securely with Azure AD.
WorkloadIdentity *ManagedClusterSecurityProfileWorkloadIdentity
}

// ManagedClusterSecurityProfileDefender defines Microsoft Defender settings for the security profile.
type ManagedClusterSecurityProfileDefender struct {
// LogAnalyticsWorkspaceResourceID is the ID of the Log Analytics workspace that has to be associated with Microsoft Defender.
// When Microsoft Defender is enabled, this field is required and must be a valid workspace resource ID.
LogAnalyticsWorkspaceResourceID *string

// SecurityMonitoring profile defines the Microsoft Defender threat detection for Cloud settings for the security profile.
SecurityMonitoring *ManagedClusterSecurityProfileDefenderSecurityMonitoring
}

// ManagedClusterSecurityProfileDefenderSecurityMonitoring settings for the security profile threat detection.
type ManagedClusterSecurityProfileDefenderSecurityMonitoring struct {
// Enabled enables Defender threat detection
Enabled *bool
}

// ManagedClusterSecurityProfileImageCleaner removes unused images from nodes, freeing up disk space and helping to reduce attack surface area.
type ManagedClusterSecurityProfileImageCleaner struct {
// Enabled enables Image Cleaner on AKS cluster.
Enabled *bool

// Image Cleaner scanning interval in hours.
IntervalHours *int32
}

// ManagedClusterSecurityProfileWorkloadIdentity defines Workload identity settings for the security profile.
type ManagedClusterSecurityProfileWorkloadIdentity struct {
// Enabled enables workload identity.
Enabled *bool
}

// AzureKeyVaultKms Azure Key Vault key management service settings for the security profile.
type AzureKeyVaultKms struct {
// Enabled enables Azure Key Vault key management service. The default is false.
Enabled *bool

// KeyID defines the Identifier of Azure Key Vault key.
// When Azure Key Vault key management service is enabled, this field is required and must be a valid key identifier.
KeyID *string

// KeyVaultNetworkAccess defines the network access of key vault.
// The possible values are Public and Private.
// Public means the key vault allows public access from all networks.
// Private means the key vault disables public access and enables private link. The default value is Public.
KeyVaultNetworkAccess *infrav1.KeyVaultNetworkAccessTypes

// KeyVaultResourceID is the Resource ID of key vault. When keyVaultNetworkAccess is Private, this field is required and must be a valid resource ID.
KeyVaultResourceID *string
}

// buildAutoScalerProfile builds the AutoScalerProfile for the ManagedClusterProperties.
func buildAutoScalerProfile(autoScalerProfile *AutoScalerProfile) *asocontainerservicev1.ManagedClusterProperties_AutoScalerProfile {
if autoScalerProfile == nil {
@@ -491,6 +560,23 @@
}
}

if s.SecurityProfile != nil {
securityProfile := &armcontainerservice.ManagedClusterSecurityProfile{}
if s.SecurityProfile.AzureKeyVaultKms != nil {
securityProfile.AzureKeyVaultKms = &armcontainerservice.AzureKeyVaultKms{
Enabled: s.SecurityProfile.AzureKeyVaultKms.Enabled,
KeyID: s.SecurityProfile.AzureKeyVaultKms.KeyID,
}
if s.SecurityProfile.AzureKeyVaultKms.KeyVaultNetworkAccess != nil {
keyVaultNetworkAccess := *s.SecurityProfile.AzureKeyVaultKms.KeyVaultNetworkAccess
securityProfile.AzureKeyVaultKms.KeyVaultNetworkAccess = ptr.To(armcontainerservice.KeyVaultNetworkAccessTypes(keyVaultNetworkAccess))
}
if s.SecurityProfile.AzureKeyVaultKms.KeyVaultResourceID != nil {
securityProfile.AzureKeyVaultKms.KeyVaultResourceID = s.SecurityProfile.AzureKeyVaultKms.KeyVaultResourceID
}

Check warning on line 576 in azure/services/managedclusters/spec.go

Codecov / codecov/patch

azure/services/managedclusters/spec.go#L566-L576

Added lines #L566 - L576 were not covered by tests
}
}

// Only include AgentPoolProfiles during initial cluster creation. Agent pools are managed solely by the
// AzureManagedMachinePool controller thereafter.
managedCluster.Spec.AgentPoolProfiles = nil
1 change: 1 addition & 0 deletions azure/services/managedclusters/spec_test.go
Original file line number Diff line number Diff line change
@@ -101,6 +101,7 @@ func TestParameters(t *testing.T) {
},
DNSPrefix: ptr.To("dns prefix"),
DisableLocalAccounts: ptr.To(true),
SecurityProfile: &ManagedClusterSecurityProfile{},
}

expected := &asocontainerservicev1.ManagedCluster{
Original file line number Diff line number Diff line change
@@ -423,6 +423,91 @@ spec:
description: ResourceGroupName is the name of the Azure resource group
for this AKS Cluster. Immutable.
type: string
securityProfile:
description: SecurityProfile defines the security profile for the
container service cluster.
properties:
azureKeyVaultKms:
description: AzureKeyVaultKms defines Azure Key Vault key management
service settings for the security profile.
properties:
enabled:
description: Enabled enables the Azure Key Vault key management
service. The default is false.
type: boolean
keyID:
description: KeyID defines the Identifier of Azure Key Vault
key. When Azure Key Vault key management service is enabled,
this field is required and must be a valid key identifier.
type: string
keyVaultNetworkAccess:
description: KeyVaultNetworkAccess defines the network access
of key vault. The possible values are Public and Private.
Public means the key vault allows public access from all
networks. Private means the key vault disables public access
and enables private link. The default value is Public.
type: string
keyVaultResourceID:
description: KeyVaultResourceID is the Resource ID of key
vault. When keyVaultNetworkAccess is Private, this field
is required and must be a valid resource ID.
type: string
required:
- enabled
- keyID
type: object
defender:
description: Defender defines Microsoft Defender settings for
the security profile.
properties:
logAnalyticsWorkspaceResourceID:
description: LogAnalyticsWorkspaceResourceID is the ID of
the Log Analytics workspace that has to be associated with
Microsoft Defender. When Microsoft Defender is enabled,
this field is required and must be a valid workspace resource
ID.
type: string
securityMonitoring:
description: SecurityMonitoring profile defines the Microsoft
Defender threat detection for Cloud settings for the security
profile.
properties:
enabled:
description: Enabled enables Defender threat detection
type: boolean
required:
- enabled
type: object
required:
- logAnalyticsWorkspaceResourceID
- securityMonitoring
type: object
imageCleaner:
description: ImageCleaner settings for the security profile.
properties:
enabled:
description: Enabled enables the Image Cleaner on AKS cluster.
type: boolean
intervalHours:
description: IntervalHours defines Image Cleaner scanning
interval in hours. Default value is 24 hours.
format: int32
type: integer
required:
- enabled
type: object
workloadIdentity:
description: Workloadidentity enables Kubernetes applications
to access Azure cloud resources securely with Azure AD. Ensure
to enable OIDC issuer while enabling Workload Identity
properties:
enabled:
description: Enabled enables the workload identity.
type: boolean
required:
- enabled
type: object
type: object
sku:
description: SKU is the SKU of the AKS to be provisioned.
properties:

0 comments on commit e5ab8f5

Please sign in to comment.