Skip to content

Commit 955792f

Browse files
committed
Fix addon and msi auth bug
1 parent 16f35a9 commit 955792f

2 files changed

Lines changed: 160 additions & 8 deletions

File tree

src/aks-preview/azext_aks_preview/managed_cluster_decorator.py

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,24 @@ def get_enable_msi_auth_for_monitoring(self) -> Union[bool, None]:
389389
elif enable_azure_monitor_logs:
390390
result = True
391391
elif enable_msi_auth_for_monitoring is False:
392-
result = False
392+
# The base class returns False when service_principal_profile.client_id is not None,
393+
# but MSI-based clusters set client_id to "msi". Check if the monitoring addon
394+
# already has useAADAuth=true, which indicates MSI auth is actually in use.
395+
addon_consts = self.get_addon_consts()
396+
CONST_MONITORING_ADDON_NAME = addon_consts.get("CONST_MONITORING_ADDON_NAME")
397+
CONST_MONITORING_USING_AAD_MSI_AUTH = addon_consts.get("CONST_MONITORING_USING_AAD_MSI_AUTH")
398+
if self.mc and self.mc.addon_profiles:
399+
monitoring_profile = (
400+
self.mc.addon_profiles.get(CONST_MONITORING_ADDON_NAME) or
401+
self.mc.addon_profiles.get(CONST_MONITORING_ADDON_NAME_CAMELCASE)
402+
)
403+
if (monitoring_profile and monitoring_profile.config and
404+
str(monitoring_profile.config.get(CONST_MONITORING_USING_AAD_MSI_AUTH, "")).lower() == "true"):
405+
result = True
406+
else:
407+
result = False
408+
else:
409+
result = False
393410
elif enable_msi_auth_for_monitoring is None and not disable_msi_auth and not enable_msi_auth:
394411
result = True
395412
else:
@@ -5077,9 +5094,14 @@ def postprocessing_after_mc_created(self, cluster: ManagedCluster) -> None:
50775094
)
50785095
addon_consts = self.context.get_addon_consts()
50795096
CONST_MONITORING_ADDON_NAME = addon_consts.get("CONST_MONITORING_ADDON_NAME")
5097+
# The API response may return the addon key as either "omsagent" or "omsAgent"
5098+
monitoring_addon_key = CONST_MONITORING_ADDON_NAME
5099+
if CONST_MONITORING_ADDON_NAME not in cluster.addon_profiles and \
5100+
CONST_MONITORING_ADDON_NAME_CAMELCASE in cluster.addon_profiles:
5101+
monitoring_addon_key = CONST_MONITORING_ADDON_NAME_CAMELCASE
50805102
self.context.external_functions.ensure_container_insights_for_monitoring(
50815103
self.cmd,
5082-
cluster.addon_profiles[CONST_MONITORING_ADDON_NAME],
5104+
cluster.addon_profiles[monitoring_addon_key],
50835105
self.context.get_subscription_id(),
50845106
self.context.get_resource_group_name(),
50855107
self.context.get_name(),
@@ -7673,14 +7695,21 @@ def postprocessing_after_mc_created(self, cluster: ManagedCluster) -> None:
76737695
CONST_MONITORING_ADDON_NAME = addon_consts.get("CONST_MONITORING_ADDON_NAME")
76747696
CONST_MONITORING_USING_AAD_MSI_AUTH = addon_consts.get("CONST_MONITORING_USING_AAD_MSI_AUTH")
76757697

7676-
if (cluster.addon_profiles and
7677-
CONST_MONITORING_ADDON_NAME in cluster.addon_profiles and
7678-
cluster.addon_profiles[CONST_MONITORING_ADDON_NAME].enabled):
7698+
# The API response may return the addon key as either "omsagent" or "omsAgent"
7699+
monitoring_addon_key = None
7700+
if cluster.addon_profiles:
7701+
if CONST_MONITORING_ADDON_NAME in cluster.addon_profiles:
7702+
monitoring_addon_key = CONST_MONITORING_ADDON_NAME
7703+
elif CONST_MONITORING_ADDON_NAME_CAMELCASE in cluster.addon_profiles:
7704+
monitoring_addon_key = CONST_MONITORING_ADDON_NAME_CAMELCASE
7705+
7706+
if (monitoring_addon_key and
7707+
cluster.addon_profiles[monitoring_addon_key].enabled):
76797708

76807709
# Check if MSI auth is enabled
76817710
if (CONST_MONITORING_USING_AAD_MSI_AUTH in
7682-
cluster.addon_profiles[CONST_MONITORING_ADDON_NAME].config and
7683-
str(cluster.addon_profiles[CONST_MONITORING_ADDON_NAME].config[
7711+
cluster.addon_profiles[monitoring_addon_key].config and
7712+
str(cluster.addon_profiles[monitoring_addon_key].config[
76847713
CONST_MONITORING_USING_AAD_MSI_AUTH]).lower() == "true"):
76857714

76867715
# Check parameter sizes to identify what might be causing large headers
@@ -7695,7 +7724,7 @@ def postprocessing_after_mc_created(self, cluster: ManagedCluster) -> None:
76957724

76967725
self.context.external_functions.ensure_container_insights_for_monitoring(
76977726
self.cmd,
7698-
cluster.addon_profiles[CONST_MONITORING_ADDON_NAME],
7727+
cluster.addon_profiles[monitoring_addon_key],
76997728
self.context.get_subscription_id(),
77007729
self.context.get_resource_group_name(),
77017730
self.context.get_name(),

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

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
CONST_MANAGED_GATEWAY_INSTALLATION_DISABLED,
4242
CONST_MANAGED_GATEWAY_INSTALLATION_STANDARD,
4343
CONST_MONITORING_ADDON_NAME,
44+
CONST_MONITORING_ADDON_NAME_CAMELCASE,
4445
CONST_MONITORING_LOG_ANALYTICS_WORKSPACE_RESOURCE_ID,
4546
CONST_MONITORING_USING_AAD_MSI_AUTH,
4647
CONST_NODEPOOL_MODE_SYSTEM,
@@ -5137,6 +5138,36 @@ def test_get_enable_high_log_scale_mode_update_monitoring_camelcase_key(self):
51375138
result = ctx.get_enable_high_log_scale_mode()
51385139
self.assertTrue(result)
51395140

5141+
def test_get_enable_msi_auth_for_monitoring_with_msi_service_principal(self):
5142+
"""Test that MSI auth is correctly detected when service_principal_profile.client_id='msi'.
5143+
5144+
The base class returns False when client_id is not None, but MSI-based clusters set
5145+
client_id to 'msi'. The preview override should check the addon config for useAADAuth.
5146+
"""
5147+
ctx = AKSPreviewManagedClusterContext(
5148+
self.cmd,
5149+
AKSManagedClusterParamDict({}),
5150+
self.models,
5151+
decorator_mode=DecoratorMode.UPDATE,
5152+
)
5153+
mc = self.models.ManagedCluster(
5154+
location="test_location",
5155+
service_principal_profile=self.models.ManagedClusterServicePrincipalProfile(
5156+
client_id="msi",
5157+
),
5158+
addon_profiles={
5159+
"omsagent": self.models.ManagedClusterAddonProfile(
5160+
enabled=True,
5161+
config={
5162+
CONST_MONITORING_USING_AAD_MSI_AUTH: "true",
5163+
}
5164+
)
5165+
},
5166+
)
5167+
ctx.attach_mc(mc)
5168+
result = ctx.get_enable_msi_auth_for_monitoring()
5169+
self.assertTrue(result)
5170+
51405171
def test_get_enable_default_domain(self):
51415172
# default value
51425173
ctx_1 = AKSPreviewManagedClusterContext(
@@ -7910,6 +7941,33 @@ def test_postprocessing_create_dcr_true_when_cnl_and_hlsm_both_set(self):
79107941
_, kwargs = mock_ecifm.call_args
79117942
self.assertTrue(kwargs["create_dcr"])
79127943

7944+
def test_postprocessing_create_dcr_true_with_camelcase_addon_key(self):
7945+
"""create_dcr=True when the API response uses the camelCase 'omsAgent' addon key.
7946+
7947+
The API may return 'omsAgent' instead of 'omsagent'. The postprocessing must
7948+
handle both key variants to ensure the DCR is updated.
7949+
"""
7950+
dec = self._make_postprocessing_decorator(
7951+
{"enable_container_network_logs": True, "enable_high_log_scale_mode": True}
7952+
)
7953+
# Build cluster with camelCase addon key (as the API might return)
7954+
cluster = self.models.ManagedCluster(
7955+
location="test_location",
7956+
addon_profiles={
7957+
CONST_MONITORING_ADDON_NAME_CAMELCASE: self.models.ManagedClusterAddonProfile(enabled=True)
7958+
},
7959+
)
7960+
external_functions = dec.context.external_functions
7961+
with patch.object(
7962+
external_functions, "ensure_container_insights_for_monitoring", return_value=None
7963+
) as mock_ecifm, patch.object(
7964+
dec.context, "get_enable_high_log_scale_mode", return_value=True
7965+
):
7966+
dec.postprocessing_after_mc_created(cluster)
7967+
mock_ecifm.assert_called_once()
7968+
_, kwargs = mock_ecifm.call_args
7969+
self.assertTrue(kwargs["create_dcr"])
7970+
79137971

79147972
class AKSPreviewManagedClusterUpdateDecoratorTestCase(unittest.TestCase):
79157973
def setUp(self):
@@ -13646,6 +13704,71 @@ def test_update_disable_hlsm_standalone_no_postprocessing(self):
1364613704
dec.context.get_intermediate("monitoring_addon_postprocessing_required", default_value=False)
1364713705
)
1364813706

13707+
def test_update_postprocessing_with_camelcase_addon_key(self):
13708+
"""Test that update postprocessing works when the API response uses 'omsAgent' (camelCase).
13709+
13710+
The API may return the monitoring addon as 'omsAgent' instead of 'omsagent'.
13711+
The postprocessing must handle both key variants so the DCR gets updated.
13712+
"""
13713+
dec = AKSPreviewManagedClusterUpdateDecorator(
13714+
self.cmd,
13715+
self.client,
13716+
{
13717+
"enable_container_network_logs": True,
13718+
"enable_high_log_scale_mode": True,
13719+
"name": "test_name",
13720+
"resource_group_name": "test_rg_name",
13721+
"location": "test_location",
13722+
"enable_msi_auth_for_monitoring": True,
13723+
"enable_syslog": False,
13724+
"data_collection_settings": None,
13725+
},
13726+
CUSTOM_MGMT_AKS_PREVIEW,
13727+
)
13728+
mc = self.models.ManagedCluster(
13729+
location="test_location",
13730+
network_profile=self.models.ContainerServiceNetworkProfile(
13731+
advanced_networking=self.models.AdvancedNetworking(
13732+
enabled=True,
13733+
),
13734+
),
13735+
addon_profiles={
13736+
"omsagent": self.models.ManagedClusterAddonProfile(
13737+
enabled=True,
13738+
config={
13739+
CONST_MONITORING_USING_AAD_MSI_AUTH: "true",
13740+
}
13741+
)
13742+
},
13743+
)
13744+
dec.context.attach_mc(mc)
13745+
dec.context.set_intermediate("subscription_id", "test_subscription_id")
13746+
# Simulate profile update setting the postprocessing flag
13747+
dec.update_monitoring_profile_flow_logs(mc)
13748+
self.assertTrue(dec.context.get_intermediate("monitoring_addon_postprocessing_required"))
13749+
13750+
# Build API response cluster with camelCase addon key
13751+
cluster = self.models.ManagedCluster(
13752+
location="test_location",
13753+
addon_profiles={
13754+
CONST_MONITORING_ADDON_NAME_CAMELCASE: self.models.ManagedClusterAddonProfile(
13755+
enabled=True,
13756+
config={
13757+
CONST_MONITORING_USING_AAD_MSI_AUTH: "true",
13758+
}
13759+
)
13760+
},
13761+
)
13762+
external_functions = dec.context.external_functions
13763+
with patch.object(
13764+
external_functions, "ensure_container_insights_for_monitoring", return_value=None
13765+
) as mock_ecifm:
13766+
dec.postprocessing_after_mc_created(cluster)
13767+
mock_ecifm.assert_called_once()
13768+
_, kwargs = mock_ecifm.call_args
13769+
self.assertTrue(kwargs["create_dcr"])
13770+
self.assertTrue(kwargs["enable_high_log_scale_mode"])
13771+
1364913772
def test_update_node_provisioning_profile(self):
1365013773
dec_0 = AKSPreviewManagedClusterUpdateDecorator(
1365113774
self.cmd,

0 commit comments

Comments
 (0)