Skip to content

Commit 8772d7b

Browse files
committed
[AKS] az aks create: Add new parameter --kms-infrastructure-encryption to enable KMS infrastructure encryption.
1 parent 40ef8c9 commit 8772d7b

File tree

10 files changed

+6782
-1
lines changed

10 files changed

+6782
-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.0b30
16+
+++++++
17+
* `az aks create`: Add new parameter `--kms-infrastructure-encryption` to enable KMS infrastructure encryption.
18+
1519
18.0.0b29
1620
+++++++
1721
* Refactor code to suppress ssh access warning message when creating an automatic cluster.

src/aks-preview/azext_aks_preview/_help.py

Lines changed: 4 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.

src/aks-preview/azext_aks_preview/_params.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,12 @@ def load_arguments(self, _):
693693
"azure_keyvault_kms_key_vault_resource_id",
694694
validator=validate_azure_keyvault_kms_key_vault_resource_id,
695695
)
696+
c.argument(
697+
"kms_infrastructure_encryption",
698+
arg_type=get_enum_type(["Enabled", "Disabled"]),
699+
default="Disabled",
700+
is_preview=True,
701+
)
696702
c.argument("http_proxy_config")
697703
c.argument(
698704
"bootstrap_artifact_source",

src/aks-preview/azext_aks_preview/custom.py

Lines changed: 1 addition & 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,

src/aks-preview/azext_aks_preview/managed_cluster_decorator.py

Lines changed: 35 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

src/aks-preview/azext_aks_preview/tests/latest/recordings/test_aks_create_with_kms_infrastructure_encryption.yaml

Lines changed: 6541 additions & 0 deletions
Large diffs are not rendered by default.

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

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

10322+
@AllowLargeResponse()
10323+
@AKSCustomResourceGroupPreparer(
10324+
random_name_length=17,
10325+
name_prefix="clitest",
10326+
location="eastus2euap",
10327+
)
10328+
def test_aks_create_with_kms_infrastructure_encryption(
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", max_version="1.34.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} "
10348+
"--aks-custom-headers AKSHTTPCustomFeatures=Microsoft.ContainerService/KMSPMKPreview "
10349+
"-o json"
10350+
)
10351+
self.cmd(
10352+
create_cmd,
10353+
checks=[
10354+
self.check("provisioningState", "Succeeded"),
10355+
self.check(
10356+
"securityProfile.kubernetesResourceObjectEncryptionProfile.infrastructureEncryption",
10357+
"Enabled"
10358+
),
10359+
],
10360+
)
10361+
10362+
# delete
10363+
cmd = (
10364+
"aks delete --resource-group={resource_group} --name={name} --yes --no-wait"
10365+
)
10366+
self.cmd(
10367+
cmd,
10368+
checks=[
10369+
self.is_empty(),
10370+
],
10371+
)
10372+
1032210373
@AllowLargeResponse()
1032310374
@AKSCustomResourceGroupPreparer(
1032410375
random_name_length=17,

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

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2272,6 +2272,55 @@ def test_get_azure_keyvault_kms_key_vault_resource_id(self):
22722272
with self.assertRaises(ArgumentUsageError):
22732273
ctx_9.get_azure_keyvault_kms_key_vault_resource_id()
22742274

2275+
def test_get_kms_infrastructure_encryption(self):
2276+
# default
2277+
ctx_0 = AKSPreviewManagedClusterContext(
2278+
self.cmd,
2279+
AKSManagedClusterParamDict({}),
2280+
self.models,
2281+
decorator_mode=DecoratorMode.CREATE,
2282+
)
2283+
self.assertIsNone(ctx_0.get_kms_infrastructure_encryption())
2284+
2285+
# with explicit Disabled value
2286+
ctx_1 = AKSPreviewManagedClusterContext(
2287+
self.cmd,
2288+
AKSManagedClusterParamDict(
2289+
{
2290+
"kms_infrastructure_encryption": "Disabled",
2291+
}
2292+
),
2293+
self.models,
2294+
decorator_mode=DecoratorMode.CREATE,
2295+
)
2296+
self.assertEqual(ctx_1.get_kms_infrastructure_encryption(), "Disabled")
2297+
2298+
# with Enabled value
2299+
ctx_2 = AKSPreviewManagedClusterContext(
2300+
self.cmd,
2301+
AKSManagedClusterParamDict(
2302+
{
2303+
"kms_infrastructure_encryption": "Enabled",
2304+
}
2305+
),
2306+
self.models,
2307+
decorator_mode=DecoratorMode.CREATE,
2308+
)
2309+
self.assertEqual(ctx_2.get_kms_infrastructure_encryption(), "Enabled")
2310+
2311+
# test in update mode
2312+
ctx_3 = AKSPreviewManagedClusterContext(
2313+
self.cmd,
2314+
AKSManagedClusterParamDict(
2315+
{
2316+
"kms_infrastructure_encryption": "Enabled",
2317+
}
2318+
),
2319+
self.models,
2320+
decorator_mode=DecoratorMode.UPDATE,
2321+
)
2322+
self.assertEqual(ctx_3.get_kms_infrastructure_encryption(), "Enabled")
2323+
22752324
def test_get_cluster_snapshot_id(self):
22762325
# default
22772326
ctx_1 = AKSPreviewManagedClusterContext(
@@ -4897,6 +4946,93 @@ def test_set_up_azure_keyvault_kms(self):
48974946

48984947
self.assertEqual(dec_mc_3, ground_truth_mc_3)
48994948

4949+
def test_set_up_kms_infrastructure_encryption(self):
4950+
# test default (no infrastructure encryption)
4951+
dec_1 = AKSPreviewManagedClusterCreateDecorator(
4952+
self.cmd,
4953+
self.client,
4954+
{},
4955+
CUSTOM_MGMT_AKS_PREVIEW,
4956+
)
4957+
mc_1 = self.models.ManagedCluster(location="test_location")
4958+
dec_1.context.attach_mc(mc_1)
4959+
dec_mc_1 = dec_1.set_up_kms_infrastructure_encryption(mc_1)
4960+
# no change expected
4961+
ground_truth_mc_1 = self.models.ManagedCluster(location="test_location")
4962+
self.assertEqual(dec_mc_1, ground_truth_mc_1)
4963+
4964+
# test with Disabled
4965+
dec_2 = AKSPreviewManagedClusterCreateDecorator(
4966+
self.cmd,
4967+
self.client,
4968+
{
4969+
"kms_infrastructure_encryption": "Disabled",
4970+
},
4971+
CUSTOM_MGMT_AKS_PREVIEW,
4972+
)
4973+
mc_2 = self.models.ManagedCluster(location="test_location")
4974+
dec_2.context.attach_mc(mc_2)
4975+
dec_mc_2 = dec_2.set_up_kms_infrastructure_encryption(mc_2)
4976+
# no change expected
4977+
ground_truth_mc_2 = self.models.ManagedCluster(location="test_location")
4978+
self.assertEqual(dec_mc_2, ground_truth_mc_2)
4979+
4980+
# test with Enabled
4981+
dec_3 = AKSPreviewManagedClusterCreateDecorator(
4982+
self.cmd,
4983+
self.client,
4984+
{
4985+
"kms_infrastructure_encryption": "Enabled",
4986+
},
4987+
CUSTOM_MGMT_AKS_PREVIEW,
4988+
)
4989+
mc_3 = self.models.ManagedCluster(location="test_location")
4990+
dec_3.context.attach_mc(mc_3)
4991+
dec_mc_3 = dec_3.set_up_kms_infrastructure_encryption(mc_3)
4992+
4993+
# expected security profile with infrastructure encryption
4994+
ground_truth_kube_resource_encryption_profile_3 = self.models.KubernetesResourceObjectEncryptionProfile(
4995+
infrastructure_encryption="Enabled"
4996+
)
4997+
ground_truth_security_profile_3 = self.models.ManagedClusterSecurityProfile(
4998+
kubernetes_resource_object_encryption_profile=ground_truth_kube_resource_encryption_profile_3,
4999+
)
5000+
ground_truth_mc_3 = self.models.ManagedCluster(
5001+
location="test_location",
5002+
security_profile=ground_truth_security_profile_3,
5003+
)
5004+
self.assertEqual(dec_mc_3, ground_truth_mc_3)
5005+
5006+
# test with existing security profile
5007+
dec_4 = AKSPreviewManagedClusterCreateDecorator(
5008+
self.cmd,
5009+
self.client,
5010+
{
5011+
"kms_infrastructure_encryption": "Enabled",
5012+
},
5013+
CUSTOM_MGMT_AKS_PREVIEW,
5014+
)
5015+
existing_security_profile = self.models.ManagedClusterSecurityProfile()
5016+
mc_4 = self.models.ManagedCluster(
5017+
location="test_location",
5018+
security_profile=existing_security_profile,
5019+
)
5020+
dec_4.context.attach_mc(mc_4)
5021+
dec_mc_4 = dec_4.set_up_kms_infrastructure_encryption(mc_4)
5022+
5023+
# should add to existing security profile
5024+
ground_truth_kube_resource_encryption_profile_4 = self.models.KubernetesResourceObjectEncryptionProfile(
5025+
infrastructure_encryption="Enabled"
5026+
)
5027+
ground_truth_security_profile_4 = self.models.ManagedClusterSecurityProfile(
5028+
kubernetes_resource_object_encryption_profile=ground_truth_kube_resource_encryption_profile_4,
5029+
)
5030+
ground_truth_mc_4 = self.models.ManagedCluster(
5031+
location="test_location",
5032+
security_profile=ground_truth_security_profile_4,
5033+
)
5034+
self.assertEqual(dec_mc_4, ground_truth_mc_4)
5035+
49005036
def test_set_up_creationdata_of_cluster_snapshot(self):
49015037
dec_1 = AKSPreviewManagedClusterCreateDecorator(
49025038
self.cmd,

src/aks-preview/linter_exclusions.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ aks create:
1818
azure_keyvault_kms_key_vault_resource_id:
1919
rule_exclusions:
2020
- option_length_too_long
21+
kms_infrastructure_encryption:
22+
rule_exclusions:
23+
- option_length_too_long
2124
enable_workload_identity:
2225
rule_exclusions:
2326
- option_length_too_long

src/aks-preview/setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
from setuptools import find_packages, setup
1111

12-
VERSION = "18.0.0b29"
12+
VERSION = "18.0.0b30"
1313

1414
CLASSIFIERS = [
1515
"Development Status :: 4 - Beta",

0 commit comments

Comments
 (0)