Skip to content

Commit 0268c93

Browse files
committed
[AKS] az aks create/update: Add new parameter --kms-infrastructure-encryption to enable KMS infrastructure encryption.
1 parent 1973d2a commit 0268c93

File tree

8 files changed

+499
-1
lines changed

8 files changed

+499
-1
lines changed

src/aks-preview/HISTORY.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ To release a new version, please select a new version number (usually plus 1 to
1212
Pending
1313
+++++++
1414

15+
18.0.0b28
16+
+++++++
17+
* `az aks create/update`: Add new parameter `--kms-infrastructure-encryption` to enable KMS infrastructure encryption.
18+
1519
18.0.0b27
1620
+++++++
1721
* Add framework for interactive AI-powered debugging tool.

src/aks-preview/azext_aks_preview/_help.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,10 @@
495495
- name: --azure-keyvault-kms-key-vault-resource-id
496496
type: string
497497
short-summary: Resource ID of Azure Key Vault.
498+
- name: --kms-infrastructure-encryption
499+
type: string
500+
short-summary: Enable encryption at rest of Kubernetes resource objects using service-managed keys.
501+
long-summary: Enable infrastructure encryption for Kubernetes resource objects. This feature provides encryption at rest for cluster secrets and configuration using service-managed keys. For more information see https://aka.ms/aks/kubernetesResourceObjectEncryption.
498502
- name: --enable-image-cleaner
499503
type: bool
500504
short-summary: Enable ImageCleaner Service.
@@ -1103,6 +1107,10 @@
11031107
- name: --azure-keyvault-kms-key-vault-resource-id
11041108
type: string
11051109
short-summary: Resource ID of Azure Key Vault.
1110+
- name: --kms-infrastructure-encryption
1111+
type: string
1112+
short-summary: Enable encryption at rest of Kubernetes resource objects using service-managed keys.
1113+
long-summary: Enable infrastructure encryption for Kubernetes resource objects. This feature provides encryption at rest for cluster secrets and configuration using service-managed keys. For more information see https://aka.ms/aks/kubernetesResourceObjectEncryption.
11061114
- name: --enable-image-cleaner
11071115
type: bool
11081116
short-summary: Enable ImageCleaner Service.

src/aks-preview/azext_aks_preview/_params.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,11 @@ def load_arguments(self, _):
692692
"azure_keyvault_kms_key_vault_resource_id",
693693
validator=validate_azure_keyvault_kms_key_vault_resource_id,
694694
)
695+
c.argument("kms_infrastructure_encryption",
696+
arg_type=get_enum_type(["Enabled", "Disabled"]),
697+
default="Disabled",
698+
is_preview=True,
699+
)
695700
c.argument("http_proxy_config")
696701
c.argument(
697702
"bootstrap_artifact_source",
@@ -1212,6 +1217,11 @@ def load_arguments(self, _):
12121217
"azure_keyvault_kms_key_vault_resource_id",
12131218
validator=validate_azure_keyvault_kms_key_vault_resource_id,
12141219
)
1220+
c.argument("kms_infrastructure_encryption",
1221+
arg_type=get_enum_type(["Enabled", "Disabled"]),
1222+
default="Disabled",
1223+
is_preview=True,
1224+
)
12151225
c.argument("http_proxy_config")
12161226
c.argument(
12171227
"bootstrap_artifact_source",

src/aks-preview/azext_aks_preview/custom.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,7 @@ def aks_create(
610610
azure_keyvault_kms_key_id=None,
611611
azure_keyvault_kms_key_vault_network_access=None,
612612
azure_keyvault_kms_key_vault_resource_id=None,
613+
kms_infrastructure_encryption="Disabled",
613614
http_proxy_config=None,
614615
bootstrap_artifact_source=CONST_ARTIFACT_SOURCE_DIRECT,
615616
bootstrap_container_registry_resource_id=None,
@@ -856,6 +857,7 @@ def aks_update(
856857
azure_keyvault_kms_key_id=None,
857858
azure_keyvault_kms_key_vault_network_access=None,
858859
azure_keyvault_kms_key_vault_resource_id=None,
860+
kms_infrastructure_encryption="Disabled",
859861
http_proxy_config=None,
860862
disable_http_proxy=False,
861863
enable_http_proxy=False,

src/aks-preview/azext_aks_preview/managed_cluster_decorator.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1231,6 +1231,16 @@ def get_disable_image_integrity(self) -> bool:
12311231

12321232
return disable_image_integrity
12331233

1234+
def get_kms_infrastructure_encryption(self) -> str:
1235+
"""Obtain the value of kms_infrastructure_encryption.
1236+
1237+
:return: str
1238+
"""
1239+
# read the original value passed by the command
1240+
kms_infrastructure_encryption = self.raw_param.get("kms_infrastructure_encryption")
1241+
1242+
return kms_infrastructure_encryption
1243+
12341244
def get_cluster_snapshot_id(self) -> Union[str, None]:
12351245
"""Obtain the values of cluster_snapshot_id.
12361246
@@ -3250,6 +3260,29 @@ def set_up_image_integrity(self, mc: ManagedCluster) -> ManagedCluster:
32503260

32513261
return mc
32523262

3263+
def set_up_kms_infrastructure_encryption(self, mc: ManagedCluster) -> ManagedCluster:
3264+
"""Set up security profile KubernetesResourceObjectEncryptionProfile for the ManagedCluster object.
3265+
3266+
:return: the ManagedCluster object
3267+
"""
3268+
self._ensure_mc(mc)
3269+
3270+
kms_infrastructure_encryption = self.context.get_kms_infrastructure_encryption()
3271+
if kms_infrastructure_encryption and kms_infrastructure_encryption != "Disabled":
3272+
if mc.security_profile is None:
3273+
mc.security_profile = self.models.ManagedClusterSecurityProfile() # pylint: disable=no-member
3274+
3275+
# Set or update the kubernetes resource object encryption profile
3276+
if mc.security_profile.kubernetes_resource_object_encryption_profile is None:
3277+
mc.security_profile.kubernetes_resource_object_encryption_profile = (
3278+
self.models.KubernetesResourceObjectEncryptionProfile() # pylint: disable=no-member
3279+
)
3280+
3281+
# Set infrastructure encryption
3282+
mc.security_profile.kubernetes_resource_object_encryption_profile.infrastructure_encryption = kms_infrastructure_encryption
3283+
3284+
return mc
3285+
32533286
def set_up_creationdata_of_cluster_snapshot(self, mc: ManagedCluster) -> ManagedCluster:
32543287
"""Set up creationData of cluster snapshot for the ManagedCluster object.
32553288
@@ -3784,6 +3817,8 @@ def construct_mc_profile_preview(self, bypass_restore_defaults: bool = False) ->
37843817
mc = self.set_up_image_cleaner(mc)
37853818
# set up image integrity
37863819
mc = self.set_up_image_integrity(mc)
3820+
# set up KMS infrastructure encryption
3821+
mc = self.set_up_kms_infrastructure_encryption(mc)
37873822
# set up cluster snapshot
37883823
mc = self.set_up_creationdata_of_cluster_snapshot(mc)
37893824
# set up app routing profile
@@ -4810,6 +4845,33 @@ def update_image_integrity(self, mc: ManagedCluster) -> ManagedCluster:
48104845

48114846
return mc
48124847

4848+
def update_kms_infrastructure_encryption(self, mc: ManagedCluster) -> ManagedCluster:
4849+
"""Update security profile KubernetesResourceObjectEncryptionProfile for the ManagedCluster object.
4850+
4851+
:return: the ManagedCluster object
4852+
"""
4853+
self._ensure_mc(mc)
4854+
4855+
kms_infrastructure_encryption = self.context.get_kms_infrastructure_encryption()
4856+
4857+
# no infrastructure encryption related changes
4858+
if not kms_infrastructure_encryption or kms_infrastructure_encryption == "Disabled":
4859+
return mc
4860+
4861+
if mc.security_profile is None:
4862+
mc.security_profile = self.models.ManagedClusterSecurityProfile() # pylint: disable=no-member
4863+
4864+
# Set or update the kubernetes resource object encryption profile
4865+
if mc.security_profile.kubernetes_resource_object_encryption_profile is None:
4866+
mc.security_profile.kubernetes_resource_object_encryption_profile = (
4867+
self.models.KubernetesResourceObjectEncryptionProfile() # pylint: disable=no-member
4868+
)
4869+
4870+
# Set infrastructure encryption
4871+
mc.security_profile.kubernetes_resource_object_encryption_profile.infrastructure_encryption = kms_infrastructure_encryption
4872+
4873+
return mc
4874+
48134875
def update_storage_profile(self, mc: ManagedCluster) -> ManagedCluster:
48144876
"""Update storage profile for the ManagedCluster object.
48154877
@@ -5638,6 +5700,8 @@ def update_mc_profile_preview(self) -> ManagedCluster:
56385700
mc = self.update_image_cleaner(mc)
56395701
# update image integrity
56405702
mc = self.update_image_integrity(mc)
5703+
# update KMS infrastructure encryption
5704+
mc = self.update_kms_infrastructure_encryption(mc)
56415705
# update workload auto scaler profile
56425706
mc = self.update_workload_auto_scaler_profile(mc)
56435707
# update azure monitor metrics profile

src/aks-preview/azext_aks_preview/tests/latest/test_aks_commands.py

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10319,6 +10319,160 @@ def test_aks_disable_azurekeyvaultkms(
1031910319
],
1032010320
)
1032110321

10322+
@AllowLargeResponse()
10323+
@AKSCustomResourceGroupPreparer(
10324+
random_name_length=17,
10325+
name_prefix="clitest",
10326+
location="westcentralus",
10327+
)
10328+
def test_aks_create_with_kms_infrastructure_encryption_enabled(
10329+
self, resource_group, resource_group_location
10330+
):
10331+
aks_name = self.create_random_name("cliakstest", 16)
10332+
k8s_version = self._get_version_in_range(location=resource_group_location, min_version="1.33.0")
10333+
self.kwargs.update(
10334+
{
10335+
"resource_group": resource_group,
10336+
"name": aks_name,
10337+
"ssh_key_value": self.generate_ssh_keys(),
10338+
"k8s_version": k8s_version,
10339+
}
10340+
)
10341+
10342+
# create cluster with infrastructure encryption enabled
10343+
create_cmd = (
10344+
"aks create --resource-group={resource_group} --name={name} "
10345+
"--kms-infrastructure-encryption Enabled "
10346+
"--kubernetes-version={k8s_version} "
10347+
"--ssh-key-value={ssh_key_value} -o json"
10348+
)
10349+
self.cmd(
10350+
create_cmd,
10351+
checks=[
10352+
self.check("provisioningState", "Succeeded"),
10353+
self.check(
10354+
"securityProfile.kubernetesResourceObjectEncryptionProfile.infrastructureEncryption",
10355+
"Enabled"
10356+
),
10357+
],
10358+
)
10359+
10360+
# delete
10361+
cmd = (
10362+
"aks delete --resource-group={resource_group} --name={name} --yes --no-wait"
10363+
)
10364+
self.cmd(
10365+
cmd,
10366+
checks=[
10367+
self.is_empty(),
10368+
],
10369+
)
10370+
10371+
@AllowLargeResponse()
10372+
@AKSCustomResourceGroupPreparer(
10373+
random_name_length=17,
10374+
name_prefix="clitest",
10375+
location="westcentralus",
10376+
)
10377+
def test_aks_create_with_kms_infrastructure_encryption_disabled(
10378+
self, resource_group, resource_group_location
10379+
):
10380+
aks_name = self.create_random_name("cliakstest", 16)
10381+
self.kwargs.update(
10382+
{
10383+
"resource_group": resource_group,
10384+
"name": aks_name,
10385+
"ssh_key_value": self.generate_ssh_keys(),
10386+
}
10387+
)
10388+
10389+
# create cluster with infrastructure encryption disabled (explicit)
10390+
create_cmd = (
10391+
"aks create --resource-group={resource_group} --name={name} "
10392+
"--kms-infrastructure-encryption Disabled "
10393+
"--ssh-key-value={ssh_key_value} -o json"
10394+
)
10395+
self.cmd(
10396+
create_cmd,
10397+
checks=[
10398+
self.check("provisioningState", "Succeeded"),
10399+
self.not_exists("securityProfile.kubernetesResourceObjectEncryptionProfile"),
10400+
],
10401+
)
10402+
10403+
# delete
10404+
cmd = (
10405+
"aks delete --resource-group={resource_group} --name={name} --yes --no-wait"
10406+
)
10407+
self.cmd(
10408+
cmd,
10409+
checks=[
10410+
self.is_empty(),
10411+
],
10412+
)
10413+
10414+
@AllowLargeResponse()
10415+
@AKSCustomResourceGroupPreparer(
10416+
random_name_length=17,
10417+
name_prefix="clitest",
10418+
location="westcentralus",
10419+
)
10420+
def test_aks_update_with_kms_infrastructure_encryption(
10421+
self, resource_group, resource_group_location
10422+
):
10423+
aks_name = self.create_random_name("cliakstest", 16)
10424+
k8s_version = self._get_version_in_range(location=resource_group_location, min_version="1.33.0")
10425+
self.kwargs.update(
10426+
{
10427+
"resource_group": resource_group,
10428+
"name": aks_name,
10429+
"ssh_key_value": self.generate_ssh_keys(),
10430+
"k8s_version": k8s_version,
10431+
}
10432+
)
10433+
10434+
# create cluster without infrastructure encryption
10435+
create_cmd = (
10436+
"aks create --resource-group={resource_group} --name={name} "
10437+
"--kubernetes-version={k8s_version} "
10438+
"--ssh-key-value={ssh_key_value} -o json"
10439+
)
10440+
self.cmd(
10441+
create_cmd,
10442+
checks=[
10443+
self.check("provisioningState", "Succeeded"),
10444+
self.not_exists("securityProfile.kubernetesResourceObjectEncryptionProfile"),
10445+
],
10446+
)
10447+
10448+
# update cluster to enable infrastructure encryption
10449+
update_cmd = (
10450+
"aks update --resource-group={resource_group} --name={name} "
10451+
"--kms-infrastructure-encryption Enabled "
10452+
"-o json"
10453+
)
10454+
self.cmd(
10455+
update_cmd,
10456+
checks=[
10457+
self.check("provisioningState", "Succeeded"),
10458+
self.check(
10459+
"securityProfile.kubernetesResourceObjectEncryptionProfile.infrastructureEncryption",
10460+
"Enabled"
10461+
),
10462+
],
10463+
)
10464+
10465+
# delete
10466+
cmd = (
10467+
"aks delete --resource-group={resource_group} --name={name} --yes --no-wait"
10468+
)
10469+
self.cmd(
10470+
cmd,
10471+
checks=[
10472+
self.is_empty(),
10473+
],
10474+
)
10475+
1032210476
@AllowLargeResponse()
1032310477
@AKSCustomResourceGroupPreparer(
1032410478
random_name_length=17,

0 commit comments

Comments
 (0)