@@ -31,11 +31,16 @@ type AzureCliAuthorizerOptions struct {
3131 // SubscriptionIdHint is the subscription to target when selecting an account with which to obtain an access token
3232 // Used to hint to Azure CLI which of its signed-in accounts it should select, based on apparent access to the subscription.
3333 SubscriptionIdHint string
34+
35+ // ForceAuthAtTenant skips the use of --subscription when authorising. This allows the CLI authorizer to obtain a tenant level token.
36+ // Use with caution. It is recommended to limit the token scope to a Subscription unless multiple subscriptions in the same tenant
37+ // need to be accessed.
38+ ForceAuthAtTenant bool
3439}
3540
3641// NewAzureCliAuthorizer returns an Authorizer which authenticates using the Azure CLI.
3742func NewAzureCliAuthorizer (ctx context.Context , options AzureCliAuthorizerOptions ) (Authorizer , error ) {
38- conf , err := newAzureCliConfig (options . Api , options . TenantId , options . AuxTenantIds , options . SubscriptionIdHint )
43+ conf , err := newAzureCliConfig (options )
3944 if err != nil {
4045 return nil , err
4146 }
@@ -96,7 +101,7 @@ func (a *AzureCliAuthorizer) Token(_ context.Context, _ *http.Request) (*oauth2.
96101
97102 // Prefer to specify subscription ID if provided, this hints to Azure CLI which account to use in the event
98103 // that multiple accounts are signed in, and each account has access to a subset of all subscriptions.
99- if a .SubscriptionIDHint != "" {
104+ if a .SubscriptionIDHint != "" && ! a . conf . ForceTenantAuth {
100105 azArgs = append (azArgs , "--subscription" , a .conf .SubscriptionIDHint )
101106
102107 // Cannot specify both `--subscription` and `--tenant`
@@ -175,6 +180,9 @@ type azureCliConfig struct {
175180 // TenantID is the required tenant ID for the primary token
176181 TenantID string
177182
183+ // ForceTenantAuth enforces token acquisition at the Tenant, rather than the specified subscription.
184+ ForceTenantAuth bool
185+
178186 // AuxiliaryTenantIDs is an optional list of tenant IDs for which to obtain additional tokens
179187 AuxiliaryTenantIDs []string
180188
@@ -186,12 +194,13 @@ type azureCliConfig struct {
186194}
187195
188196// newAzureCliConfig validates the supplied tenant ID and returns a new azureCliConfig.
189- func newAzureCliConfig (api environments. Api , tenantId string , auxiliaryTenantIds [] string , subscriptionIdHint string ) (* azureCliConfig , error ) {
197+ func newAzureCliConfig (options AzureCliAuthorizerOptions ) (* azureCliConfig , error ) {
190198 // check az-cli version, ensure that MSAL is supported
191199 if err := azurecli .CheckAzVersion (); err != nil {
192200 return nil , err
193201 }
194202
203+ var tenantId = options .TenantId
195204 // obtain default tenant ID if no tenant ID was provided
196205 if strings .TrimSpace (tenantId ) == "" {
197206 if defaultTenantId , err := azurecli .GetDefaultTenantID (); err != nil {
@@ -219,38 +228,39 @@ func newAzureCliConfig(api environments.Api, tenantId string, auxiliaryTenantIds
219228 }
220229
221230 // validate subscriptionIdHint, if applicable (currently only for Resource Manager)
222- if environments .ApiIsKnownPublished (api , "AzureResourceManager" ) {
223- if subscriptionIdHint != "" {
231+ if environments .ApiIsKnownPublished (options . Api , "AzureResourceManager" ) && ! options . ForceAuthAtTenant {
232+ if options . SubscriptionIdHint != "" {
224233 if availableSubscriptionIds , err := azurecli .ListAvailableSubscriptionIDs (); err != nil {
225234 return nil , err
226235 } else if availableSubscriptionIds == nil {
227236 return nil , fmt .Errorf ("no available subscription IDs returned by Azure CLI" )
228237 } else {
229238 found := false
230239 for _ , subId := range * availableSubscriptionIds {
231- if strings .EqualFold (subId , subscriptionIdHint ) {
240+ if strings .EqualFold (subId , options . SubscriptionIdHint ) {
232241 found = true
233242 break
234243 }
235244 }
236245 if ! found {
237- return nil , fmt .Errorf ("the provided subscription ID %q is not known by Azure CLI" , subscriptionIdHint )
246+ return nil , fmt .Errorf ("the provided subscription ID %q is not known by Azure CLI" , options . SubscriptionIdHint )
238247 }
239248 }
240249 }
241250 }
242251
243252 return & azureCliConfig {
244- Api : api ,
253+ Api : options . Api ,
245254 TenantID : tenantId ,
246- AuxiliaryTenantIDs : auxiliaryTenantIds ,
255+ AuxiliaryTenantIDs : options . AuxTenantIds ,
247256 DefaultSubscriptionID : subscriptionId ,
248- SubscriptionIDHint : strings .ToLower (subscriptionIdHint ),
257+ SubscriptionIDHint : strings .ToLower (options .SubscriptionIdHint ),
258+ ForceTenantAuth : options .ForceAuthAtTenant ,
249259 }, nil
250260}
251261
252262// TokenSource provides a source for obtaining access tokens using AzureCliAuthorizer.
253- func (c * azureCliConfig ) TokenSource (ctx context.Context ) (Authorizer , error ) {
263+ func (c * azureCliConfig ) TokenSource (_ context.Context ) (Authorizer , error ) {
254264 // Cache access tokens internally to avoid unnecessary `az` invocations
255265 return NewCachedAuthorizer (& AzureCliAuthorizer {
256266 TenantID : c .TenantID ,
0 commit comments