Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
56 changes: 56 additions & 0 deletions src/azure-cli/azure/cli/command_modules/acs/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -1627,10 +1627,66 @@ def aks_get_credentials(cmd, client, resource_group_name, name, admin=False,
encoding='UTF-8')
_print_or_merge_credentials(
path, kubeconfig, overwrite_existing, context_name)

# Check if kubeconfig requires kubelogin with devicecode and convert it
if uses_kubelogin_devicecode(kubeconfig):
if which("kubelogin"):
try:
# Run kubelogin convert-kubeconfig -l azurecli
subprocess.run(
["kubelogin", "convert-kubeconfig", "-l", "azurecli"],
cwd=os.path.dirname(path),
check=True,
)
logger.warning("Converted kubeconfig to use Azure CLI authentication.")
except subprocess.CalledProcessError as e:
logger.warning("Failed to convert kubeconfig with kubelogin: %s", str(e))
except Exception as e: # pylint: disable=broad-except
logger.warning("Error running kubelogin: %s", str(e))
else:
logger.warning(
"The kubeconfig uses devicecode authentication which requires kubelogin. "
"Please install kubelogin from https://github.com/Azure/kubelogin or run "
"'az aks install-cli' to install both kubectl and kubelogin. "
"If devicecode login fails, try running "
"'kubelogin convert-kubeconfig -l azurecli' to unblock yourself."
)

except (IndexError, ValueError):
raise CLIError("Fail to find kubeconfig file.")


def uses_kubelogin_devicecode(kubeconfig: str) -> bool:
try:
config = yaml.safe_load(kubeconfig)

# Check if users section exists and has at least one user
if not config or not config.get('users') or len(config['users']) == 0:
return False

first_user = config['users'][0]
user_info = first_user.get('user', {})
exec_info = user_info.get('exec', {})

# Check if command is kubelogin
command = exec_info.get('command', '')
if 'kubelogin' not in command:
return False

# Check if args contains --login and devicecode
args = exec_info.get('args', [])
# Join args into a string for easier pattern matching
args_str = ' '.join(args)
# Check for '--login devicecode' or '-l devicecode'
if '--login devicecode' in args_str or '-l devicecode' in args_str:
return True
return False
except (yaml.YAMLError, KeyError, TypeError, AttributeError) as e:
# If there's any error parsing the kubeconfig, assume it doesn't require kubelogin
logger.debug("Error parsing kubeconfig: %s", str(e))
return False


def _handle_merge(existing, addition, key, replace):
if not addition.get(key, False):
return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6621,6 +6621,17 @@ def test_aks_automatic_sku(self, resource_group, resource_group_location):
],
)

# get-credentials
fd, temp_path = tempfile.mkstemp()
self.kwargs.update({'file': temp_path})
try:
self.cmd(
'aks get-credentials -g {resource_group} -n {name} --file "{file}"')
self.assertGreater(os.path.getsize(temp_path), 0)
finally:
os.close(fd)
os.remove(temp_path)

# scale the cluster
scale_cluster_cmd = (
"aks scale --resource-group={resource_group} --name={name} "
Expand Down