1+ #! /bin/bash
2+ # Azure CLI shim for GitHub Codespaces
3+ # Intercepts 'az account get-access-token' requests and uses azure-auth-helper
4+ # to acquire tokens via the ado-codespaces-auth VS Code extension.
5+ #
6+ # This enables DefaultAzureCredential's AzureCliCredential to work in Codespaces
7+ # without requiring 'az login' (which times out waiting for browser auth).
8+ #
9+ # To install: Copy this to /usr/local/share/codespace-shims/az
10+ # The shims directory should already be in PATH for Codespaces.
11+
12+ # If ACTIONS_ID_TOKEN_REQUEST_URL is set, we're in GitHub Actions - skip interception
13+ if [ -n " ${ACTIONS_ID_TOKEN_REQUEST_URL} " ]; then
14+ source " $( dirname $0 ) " /resolve-shim.sh
15+ AZ_EXE=" $( resolve_shim) "
16+ exec " ${AZ_EXE} " " $@ "
17+ fi
18+
19+ source " $( dirname $0 ) " /resolve-shim.sh
20+
21+ # Well-known resource type mappings (az account get-access-token --resource-type)
22+ declare -A RESOURCE_TYPE_MAP=(
23+ [" arm" ]=" https://management.azure.com"
24+ [" aad-graph" ]=" https://graph.windows.net"
25+ [" ms-graph" ]=" https://graph.microsoft.com"
26+ [" batch" ]=" https://batch.core.windows.net"
27+ [" data-lake" ]=" https://datalake.azure.net"
28+ [" media" ]=" https://rest.media.azure.net"
29+ [" oss-rdbms" ]=" https://ossrdbms-aad.database.windows.net"
30+ )
31+
32+ # Check if this is a get-access-token request that we should intercept
33+ if [[ " $1 " == " account" && " $2 " == " get-access-token" ]]; then
34+ # Parse arguments to extract --resource, --scope, or --resource-type
35+ resource=" "
36+ scope=" "
37+ resource_type=" "
38+ prev=" "
39+
40+ for arg in " ${@: 3} " ; do
41+ case " $prev " in
42+ --resource)
43+ resource=" $arg "
44+ ;;
45+ --scope)
46+ scope=" $arg "
47+ ;;
48+ --resource-type)
49+ resource_type=" $arg "
50+ ;;
51+ esac
52+ prev=" $arg "
53+ done
54+
55+ # Resolve resource-type to resource URL if specified
56+ if [[ -n " $resource_type " && -z " $resource " ]]; then
57+ resource=" ${RESOURCE_TYPE_MAP[$resource_type]} "
58+ fi
59+
60+ # Determine the scope to request
61+ # Priority: explicit --scope > --resource/.default > --resource-type/.default
62+ request_scope=" "
63+ if [[ -n " $scope " ]]; then
64+ request_scope=" $scope "
65+ elif [[ -n " $resource " ]]; then
66+ # Append /.default if not already present
67+ if [[ " $resource " == * " /.default" ]]; then
68+ request_scope=" $resource "
69+ else
70+ request_scope=" ${resource} /.default"
71+ fi
72+ fi
73+
74+ # If we have a scope and azure-auth-helper exists, use it
75+ if [[ -n " $request_scope " && -f " ${HOME} /azure-auth-helper" ]]; then
76+ # Get token from azure-auth-helper
77+ token=$( " ${HOME} /azure-auth-helper" get-access-token " $request_scope " 2> /dev/null)
78+ exit_code=$?
79+
80+ if [[ $exit_code -eq 0 && -n " $token " ]]; then
81+ # Calculate expiry timestamps (conservative 1 hour estimate)
82+ # expires_on = POSIX timestamp, expiresOn = local datetime
83+ if date --version > /dev/null 2>&1 ; then
84+ # GNU date (Linux)
85+ expires_on=$( date -d " +1 hour" " +%s" )
86+ expires_on_datetime=$( date -d " +1 hour" " +%Y-%m-%d %H:%M:%S.000000" )
87+ else
88+ # BSD date (macOS)
89+ expires_on=$( date -v+1H " +%s" )
90+ expires_on_datetime=$( date -v+1H " +%Y-%m-%d %H:%M:%S.000000" )
91+ fi
92+
93+ # Return in az CLI JSON format (matching real az CLI output)
94+ cat << EOF
95+ {
96+ "accessToken": "${token} ",
97+ "expiresOn": "${expires_on_datetime} ",
98+ "expires_on": ${expires_on} ,
99+ "subscription": "",
100+ "tenant": "",
101+ "tokenType": "Bearer"
102+ }
103+ EOF
104+ exit 0
105+ fi
106+ # Fall through to real az CLI if azure-auth-helper fails
107+ fi
108+ fi
109+
110+ # Fall through to real az CLI for all other commands
111+ AZ_EXE=" $( resolve_shim) "
112+ if [[ -n " $AZ_EXE " ]]; then
113+ exec " ${AZ_EXE} " " $@ "
114+ else
115+ echo " Error: Azure CLI not found in PATH" >&2
116+ exit 1
117+ fi
0 commit comments