Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[AKS] Fix for 'approuting update' command #7197

Merged
merged 26 commits into from
Jan 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/aks-preview/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ Pending
+++++++
* Deprecate the alias "-r" of parameter --source-resource-id in `az aks trustedaccess rolebinding create`

1.0.0b4
bosesuneha marked this conversation as resolved.
Show resolved Hide resolved
+++++++
* Fix for `az aks approuting update` command not working when `monitoring` addon is enabled.

1.0.0b3
+++++++
* Change the format for az aks machine commands to separate the ipv4, ipv6 columns
Expand Down
71 changes: 2 additions & 69 deletions src/aks-preview/azext_aks_preview/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -3150,76 +3150,9 @@ def _aks_approuting_update(
)

try:
mc = aks_update_decorator.update_mc_profile_preview()
mc = aks_update_decorator.fetch_mc()
mc = aks_update_decorator.update_app_routing_profile(mc)
except DecoratorEarlyExitException:
return None

poller = aks_update_decorator.update_mc(mc)
if keyvault_id:
return _keyvault_update(poller, cmd, keyvault_id=keyvault_id)
return poller


def _keyvault_update(
poller,
cmd,
keyvault_id=None
):

from msrestazure.tools import is_valid_resource_id, parse_resource_id
from azure.cli.command_modules.keyvault.custom import set_policy
from azext_aks_preview._client_factory import get_keyvault_client
from azext_aks_preview._roleassignments import add_role_assignment

while not poller.done():
poller.wait()

# Get the final result
mc = poller.result()

# check keyvault authorization sytem
if keyvault_id:
if not is_valid_resource_id(keyvault_id):
raise InvalidArgumentValueError("Please provide a valid keyvault ID")

if mc.ingress_profile and mc.ingress_profile.web_app_routing and mc.ingress_profile.web_app_routing.enabled:
cmd.command_kwargs['operation_group'] = 'vaults'
keyvault_params = parse_resource_id(keyvault_id)
keyvault_subscription = keyvault_params['subscription']
keyvault_name = keyvault_params['name']
keyvault_rg = keyvault_params['resource_group']
keyvault_client = get_keyvault_client(cmd.cli_ctx, subscription_id=keyvault_subscription)
keyvault = keyvault_client.get(resource_group_name=keyvault_rg, vault_name=keyvault_name)
managed_identity_object_id = mc.ingress_profile.web_app_routing.identity.object_id
is_service_principal = False

try:
if keyvault.properties.enable_rbac_authorization:
if not add_role_assignment(
cmd,
"Key Vault Secrets User",
managed_identity_object_id,
is_service_principal,
scope=keyvault_id,
):
logger.warning(
"Could not create a role assignment for App Routing. "
"Are you an Owner on this subscription?"
)
else:
keyvault = set_policy(
cmd,
keyvault_client,
keyvault_rg,
keyvault_name,
object_id=managed_identity_object_id,
secret_permissions=["Get"],
certificate_permissions=["Get"],
)
except Exception as ex:
raise CLIError('Error in granting keyvault permissions to managed identity.\n') from ex
else:
raise CLIError('App Routing is not enabled.\n')

return mc
return aks_update_decorator.update_mc(mc)
bosesuneha marked this conversation as resolved.
Show resolved Hide resolved
227 changes: 157 additions & 70 deletions src/aks-preview/azext_aks_preview/managed_cluster_decorator.py
Original file line number Diff line number Diff line change
Expand Up @@ -4331,11 +4331,7 @@ def update_app_routing_profile(self, mc: ManagedCluster) -> ManagedCluster:
# get parameters from context
enable_app_routing = self.context.get_enable_app_routing()
enable_keyvault_secret_provider = self.context.get_enable_kv()
attach_zones = self.context.get_attach_zones()
dns_zone_resource_ids = self.context.get_dns_zone_resource_ids_from_input()
add_dns_zone = self.context.get_add_dns_zone()
delete_dns_zone = self.context.get_delete_dns_zone()
update_dns_zone = self.context.get_update_dns_zone()

# update ManagedCluster object with app routing settings
mc.ingress_profile = (
Expand All @@ -4355,77 +4351,101 @@ def update_app_routing_profile(self, mc: ManagedCluster) -> ManagedCluster:
)
raise CLIError(error_message)
mc.ingress_profile.web_app_routing.enabled = enable_app_routing
# update ManagedCluster object with keyvault-secret-provider settings

# enable keyvault secret provider addon
if enable_keyvault_secret_provider:
mc.addon_profiles = mc.addon_profiles or {}
if not mc.addon_profiles.get(CONST_AZURE_KEYVAULT_SECRETS_PROVIDER_ADDON_NAME):
mc.addon_profiles[
CONST_AZURE_KEYVAULT_SECRETS_PROVIDER_ADDON_NAME
] = self.models.ManagedClusterAddonProfile( # pylint: disable=no-member
enabled=True,
config={
CONST_SECRET_ROTATION_ENABLED: "false",
CONST_ROTATION_POLL_INTERVAL: "2m",
},
)
elif not mc.addon_profiles[CONST_AZURE_KEYVAULT_SECRETS_PROVIDER_ADDON_NAME].enabled:
mc.addon_profiles[CONST_AZURE_KEYVAULT_SECRETS_PROVIDER_ADDON_NAME].enabled = True
self._enable_keyvault_secret_provider_addon(mc)

# modify DNS zone resource IDs
# pylint: disable=too-many-nested-blocks
if dns_zone_resource_ids:
if mc.ingress_profile and mc.ingress_profile.web_app_routing and mc.ingress_profile.web_app_routing.enabled:
if add_dns_zone:
if mc.ingress_profile.web_app_routing.dns_zone_resource_ids is None:
mc.ingress_profile.web_app_routing.dns_zone_resource_ids = []
mc.ingress_profile.web_app_routing.dns_zone_resource_ids.extend(dns_zone_resource_ids)
if attach_zones:
try:
for dns_zone in dns_zone_resource_ids:
if not add_role_assignment(
self.cmd,
"DNS Zone Contributor",
mc.ingress_profile.web_app_routing.identity.object_id,
False,
scope=dns_zone
):
logger.warning(
'Could not create a role assignment for App Routing. '
'Are you an Owner on this subscription?')
except Exception as ex:
raise CLIError('Error in granting dns zone permisions to managed identity.\n') from ex
elif delete_dns_zone:
if mc.ingress_profile.web_app_routing.dns_zone_resource_ids:
dns_zone_resource_ids = [
x
for x in mc.ingress_profile.web_app_routing.dns_zone_resource_ids
if x not in dns_zone_resource_ids
]
mc.ingress_profile.web_app_routing.dns_zone_resource_ids = dns_zone_resource_ids
else:
raise CLIError('No DNS zone is used by App Routing.\n')
elif update_dns_zone:
mc.ingress_profile.web_app_routing.dns_zone_resource_ids = dns_zone_resource_ids
if attach_zones:
try:
for dns_zone in dns_zone_resource_ids:
if not add_role_assignment(
self.cmd,
"DNS Zone Contributor",
mc.ingress_profile.web_app_routing.identity.object_id,
False,
scope=dns_zone,
):
logger.warning(
'Could not create a role assignment for App Routing. '
'Are you an Owner on this subscription?')
except Exception as ex:
raise CLIError('Error in granting dns zone permisions to managed identity.\n') from ex
else:
raise CLIError('App Routing must be enabled to modify DNS zone resource IDs.\n')
self._update_dns_zone_resource_ids(mc, dns_zone_resource_ids)

return mc

def _enable_keyvault_secret_provider_addon(self, mc: ManagedCluster) -> None:
"""Helper function to enable keyvault secret provider addon for the ManagedCluster object.

:return: None
"""
mc.addon_profiles = mc.addon_profiles or {}
if not mc.addon_profiles.get(CONST_AZURE_KEYVAULT_SECRETS_PROVIDER_ADDON_NAME):
mc.addon_profiles[
CONST_AZURE_KEYVAULT_SECRETS_PROVIDER_ADDON_NAME
] = self.models.ManagedClusterAddonProfile( # pylint: disable=no-member
enabled=True,
config={
CONST_SECRET_ROTATION_ENABLED: "false",
CONST_ROTATION_POLL_INTERVAL: "2m",
},
)
elif not mc.addon_profiles[CONST_AZURE_KEYVAULT_SECRETS_PROVIDER_ADDON_NAME].enabled:
mc.addon_profiles[CONST_AZURE_KEYVAULT_SECRETS_PROVIDER_ADDON_NAME].enabled = True
mc.addon_profiles[CONST_AZURE_KEYVAULT_SECRETS_PROVIDER_ADDON_NAME].config = {
CONST_SECRET_ROTATION_ENABLED: "false",
CONST_ROTATION_POLL_INTERVAL: "2m",
}

# pylint: disable=too-many-nested-blocks
def _update_dns_zone_resource_ids(self, mc: ManagedCluster, dns_zone_resource_ids) -> None:
"""Helper function to update dns zone resource ids in app routing addon.

:return: None
"""
add_dns_zone = self.context.get_add_dns_zone()
delete_dns_zone = self.context.get_delete_dns_zone()
update_dns_zone = self.context.get_update_dns_zone()
attach_zones = self.context.get_attach_zones()

if mc.ingress_profile and mc.ingress_profile.web_app_routing and mc.ingress_profile.web_app_routing.enabled:
if add_dns_zone:
if mc.ingress_profile.web_app_routing.dns_zone_resource_ids is None:
mc.ingress_profile.web_app_routing.dns_zone_resource_ids = []
mc.ingress_profile.web_app_routing.dns_zone_resource_ids.extend(dns_zone_resource_ids)
if attach_zones:
try:
for dns_zone in dns_zone_resource_ids:
if not add_role_assignment(
self.cmd,
"DNS Zone Contributor",
mc.ingress_profile.web_app_routing.identity.object_id,
False,
scope=dns_zone
):
logger.warning(
'Could not create a role assignment for App Routing. '
'Are you an Owner on this subscription?')
except Exception as ex:
raise CLIError('Error in granting dns zone permisions to managed identity.\n') from ex
elif delete_dns_zone:
if mc.ingress_profile.web_app_routing.dns_zone_resource_ids:
dns_zone_resource_ids = [
x
for x in mc.ingress_profile.web_app_routing.dns_zone_resource_ids
if x not in dns_zone_resource_ids
]
mc.ingress_profile.web_app_routing.dns_zone_resource_ids = dns_zone_resource_ids
else:
raise CLIError('No DNS zone is used by App Routing.\n')
elif update_dns_zone:
mc.ingress_profile.web_app_routing.dns_zone_resource_ids = dns_zone_resource_ids
if attach_zones:
try:
for dns_zone in dns_zone_resource_ids:
if not add_role_assignment(
self.cmd,
"DNS Zone Contributor",
mc.ingress_profile.web_app_routing.identity.object_id,
False,
scope=dns_zone,
):
logger.warning(
'Could not create a role assignment for App Routing. '
'Are you an Owner on this subscription?')
except Exception as ex:
raise CLIError('Error in granting dns zone permisions to managed identity.\n') from ex
else:
raise CLIError('App Routing must be enabled to modify DNS zone resource IDs.\n')

def update_node_provisioning_profile(self, mc: ManagedCluster) -> ManagedCluster:
"""Updates the nodeProvisioningProfile field of the managed cluster

Expand Down Expand Up @@ -4518,11 +4538,17 @@ def check_is_postprocessing_required(self, mc: ManagedCluster) -> bool:
disable_azure_container_storage = self.context.get_intermediate(
"disable_azure_container_storage", default_value=False
)

if (enable_azure_container_storage or disable_azure_container_storage):
keyvault_id = self.context.get_keyvault_id()
enable_azure_keyvault_secrets_provider_addon = self.context.get_enable_kv() or (
mc.addon_profiles and mc.addon_profiles.get(CONST_AZURE_KEYVAULT_SECRETS_PROVIDER_ADDON_NAME)
and mc.addon_profiles[CONST_AZURE_KEYVAULT_SECRETS_PROVIDER_ADDON_NAME].enabled)
if (enable_azure_container_storage or disable_azure_container_storage) or \
(keyvault_id and enable_azure_keyvault_secrets_provider_addon):
return True
return postprocessing_required

# pylint: disable=too-many-statements
# pylint: disable=too-many-locals
def postprocessing_after_mc_created(self, cluster: ManagedCluster) -> None:
"""Postprocessing performed after the cluster is created.

Expand Down Expand Up @@ -4583,3 +4609,64 @@ def postprocessing_after_mc_created(self, cluster: ManagedCluster) -> None:
kubelet_identity_object_id,
pre_uninstall_validate,
)

# attach keyvault to app routing addon
from msrestazure.tools import parse_resource_id
from azure.cli.command_modules.keyvault.custom import set_policy
from azext_aks_preview._client_factory import get_keyvault_client
keyvault_id = self.context.get_keyvault_id()
enable_azure_keyvault_secrets_provider_addon = (
self.context.get_enable_kv() or
(cluster.addon_profiles and
cluster.addon_profiles.get(CONST_AZURE_KEYVAULT_SECRETS_PROVIDER_ADDON_NAME) and
cluster.addon_profiles[CONST_AZURE_KEYVAULT_SECRETS_PROVIDER_ADDON_NAME].enabled)
)
if keyvault_id:
if enable_azure_keyvault_secrets_provider_addon:
if cluster.ingress_profile and \
cluster.ingress_profile.web_app_routing and \
cluster.ingress_profile.web_app_routing.enabled:
if not is_valid_resource_id(keyvault_id):
raise InvalidArgumentValueError("Please provide a valid keyvault ID")
self.cmd.command_kwargs['operation_group'] = 'vaults'
keyvault_params = parse_resource_id(keyvault_id)
keyvault_subscription = keyvault_params['subscription']
keyvault_name = keyvault_params['name']
keyvault_rg = keyvault_params['resource_group']
keyvault_client = get_keyvault_client(self.cmd.cli_ctx, subscription_id=keyvault_subscription)
keyvault = keyvault_client.get(resource_group_name=keyvault_rg, vault_name=keyvault_name)
managed_identity_object_id = cluster.ingress_profile.web_app_routing.identity.object_id
print("managed_identity_object_id", managed_identity_object_id)
is_service_principal = False

try:
if keyvault.properties.enable_rbac_authorization:
print("within if block")
if not self.context.external_functions.add_role_assignment(
self.cmd,
"Key Vault Secrets User",
managed_identity_object_id,
is_service_principal,
scope=keyvault_id,
):
logger.warning(
"Could not create a role assignment for App Routing. "
"Are you an Owner on this subscription?"
)
else:
print("within else block")
keyvault = set_policy(
self.cmd,
keyvault_client,
keyvault_rg,
keyvault_name,
object_id=managed_identity_object_id,
secret_permissions=["Get"],
certificate_permissions=["Get"],
)
except Exception as ex:
raise CLIError('Error in granting keyvault permissions to managed identity.\n') from ex
else:
raise CLIError('App Routing must be enabled to attach keyvault.\n')
else:
raise CLIError('Keyvault secrets provider addon must be enabled to attach keyvault.\n')
Loading