Skip to content

Commit 19c13e5

Browse files
authored
{AKS} az aks get-credentials: Convert device code mode kubeconfig to Azure CLI token format to bypass conditional access login blocks (#9288)
1 parent 1e129ba commit 19c13e5

4 files changed

Lines changed: 69 additions & 0 deletions

File tree

src/aks-preview/HISTORY.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ To release a new version, please select a new version number (usually plus 1 to
1111

1212
Pending
1313
+++++++
14+
* `az aks get-credentials`: Convert device code mode kubeconfig to Azure CLI token format to bypass conditional access login blocks.
1415

1516
19.0.0b4
1617
+++++++

src/aks-preview/azext_aks_preview/_helpers.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,37 @@ def print_or_merge_credentials(path, kubeconfig, overwrite_existing, context_nam
9797
os.remove(temp_path)
9898

9999

100+
def uses_kubelogin_devicecode(kubeconfig: str) -> bool:
101+
try:
102+
config = yaml.safe_load(kubeconfig)
103+
104+
# Check if users section exists and has at least one user
105+
if not config or not config.get('users') or len(config['users']) == 0:
106+
return False
107+
108+
first_user = config['users'][0]
109+
user_info = first_user.get('user', {})
110+
exec_info = user_info.get('exec', {})
111+
112+
# Check if command is kubelogin
113+
command = exec_info.get('command', '')
114+
if 'kubelogin' not in command:
115+
return False
116+
117+
# Check if args contains --login and devicecode
118+
args = exec_info.get('args', [])
119+
# Join args into a string for easier pattern matching
120+
args_str = ' '.join(args)
121+
# Check for '--login devicecode' or '-l devicecode'
122+
if '--login devicecode' in args_str or '-l devicecode' in args_str:
123+
return True
124+
return False
125+
except (yaml.YAMLError, KeyError, TypeError, AttributeError) as e:
126+
# If there's any error parsing the kubeconfig, assume it doesn't require kubelogin
127+
logger.debug("Error parsing kubeconfig: %s", str(e))
128+
return False
129+
130+
100131
def _merge_kubernetes_configurations(existing_file, addition_file, replace, context_name=None):
101132
existing = _load_kubernetes_configuration(existing_file)
102133
addition = _load_kubernetes_configuration(addition_file)

src/aks-preview/azext_aks_preview/custom.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import threading
1515
import time
1616
import webbrowser
17+
import subprocess
1718

1819
from azext_aks_preview._client_factory import (
1920
CUSTOM_MGMT_AKS_PREVIEW,
@@ -72,6 +73,8 @@
7273
get_all_extensions_in_allow_list,
7374
raise_validation_error_if_extension_type_not_in_allow_list,
7475
get_extension_in_allow_list,
76+
uses_kubelogin_devicecode,
77+
which,
7578
)
7679
from azext_aks_preview._podidentity import (
7780
_ensure_managed_identity_operator_permission,
@@ -1526,6 +1529,29 @@ def aks_get_credentials(
15261529
encoding='UTF-8')
15271530
print_or_merge_credentials(
15281531
path, kubeconfig, overwrite_existing, context_name)
1532+
# Check if kubeconfig requires kubelogin with devicecode and convert it
1533+
if uses_kubelogin_devicecode(kubeconfig):
1534+
if which("kubelogin"):
1535+
try:
1536+
# Run kubelogin convert-kubeconfig -l azurecli
1537+
subprocess.run(
1538+
["kubelogin", "convert-kubeconfig", "-l", "azurecli"],
1539+
cwd=os.path.dirname(path),
1540+
check=True,
1541+
)
1542+
logger.warning("Converted kubeconfig to use Azure CLI authentication.")
1543+
except subprocess.CalledProcessError as e:
1544+
logger.warning("Failed to convert kubeconfig with kubelogin: %s", str(e))
1545+
except Exception as e: # pylint: disable=broad-except
1546+
logger.warning("Error running kubelogin: %s", str(e))
1547+
else:
1548+
logger.warning(
1549+
"The kubeconfig uses devicecode authentication which requires kubelogin. "
1550+
"Please install kubelogin from https://github.com/Azure/kubelogin or run "
1551+
"'az aks install-cli' to install both kubectl and kubelogin. "
1552+
"If devicecode login fails, try running "
1553+
"'kubelogin convert-kubeconfig -l azurecli' to unblock yourself."
1554+
)
15291555
except (IndexError, ValueError) as exc:
15301556
raise CLIError("Fail to find kubeconfig file.") from exc
15311557

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5321,6 +5321,17 @@ def test_aks_automatic_sku(self, resource_group, resource_group_location):
53215321
],
53225322
)
53235323

5324+
# get-credentials
5325+
fd, temp_path = tempfile.mkstemp()
5326+
self.kwargs.update({'file': temp_path})
5327+
try:
5328+
self.cmd(
5329+
'aks get-credentials -g {resource_group} -n {name} --file "{file}"')
5330+
self.assertGreater(os.path.getsize(temp_path), 0)
5331+
finally:
5332+
os.close(fd)
5333+
os.remove(temp_path)
5334+
53245335
# scale the cluster
53255336
scale_cluster_cmd = (
53265337
"aks scale --resource-group={resource_group} --name={name} "

0 commit comments

Comments
 (0)