[Core][Profile] Support lighthouse multi-tenant subscription#11886
[Core][Profile] Support lighthouse multi-tenant subscription#11886
Conversation
| } | ||
| # for Subscriptions - List REST API 2019-06-01's subscription account | ||
| if subscription_dict[_SUBSCRIPTION_NAME] != _TENANT_LEVEL_ACCOUNT_NAME: | ||
| if hasattr(s, 'subscription_tenant_id'): |
There was a problem hiding this comment.
what is the difference between subscription_tenant_id and tenant_id?
There was a problem hiding this comment.
There was a problem hiding this comment.
and what's difference between subscription_tenant_id and managed_by_tenants? in the pr comments example, managed_by_tenants is related with tenant_id. az login -t is switching tenant_id. subscription_tenant_id is readonly field?
There was a problem hiding this comment.
Good point. I also think these concepts are very confusing. I am following up with Lighthouse and our PMs trying to persuade them to change subscriptionTenantId to homeTenantId which is a read-only field indicating where the subscription is hosted. managedByTenants is a mapping from REST API's managedByTenants.
| if subscription_dict[_SUBSCRIPTION_NAME] != _TENANT_LEVEL_ACCOUNT_NAME: | ||
| if hasattr(s, 'subscription_tenant_id'): | ||
| subscription_dict[_SUBSCRIPTION_TENANT_ID] = s.subscription_tenant_id | ||
| if hasattr(s, 'managed_by_tenants'): |
There was a problem hiding this comment.
The code seems a little complicated here because of the check like if hasattr(s, 'managed_by_tenants'), is it possible that managed_by_tenants attribute does not exist? Can we move code like subscription_dict[_SUBSCRIPTION_TENANT_ID] = s.subscription_tenant_id to the initialization code of subscription_dict = {...} to make code more clean?
There was a problem hiding this comment.
managed_by_tenants is only present since API version 2019-06-01. It is not possible to do conditional initialization according to python syntax. https://stackoverflow.com/a/14263905
| from adal import AdalError | ||
| from azure.mgmt.resource.subscriptions.models import \ | ||
| (SubscriptionState, Subscription, SubscriptionPolicies, SpendingLimit) | ||
| (SubscriptionState, Subscription, SubscriptionPolicies, SpendingLimit, ManagedByTenant) |
There was a problem hiding this comment.
Because subscription models have api contraint, please use get_models() here.
There was a problem hiding this comment.
This test is only for latest. For specific test, it is in test_profile_v2016_06_01.py.
| add_sub = True | ||
| for sub_to_compare in all_subscriptions: | ||
| if sub_to_add.subscription_id == sub_to_compare.subscription_id: | ||
| logger.warning("Subscription %s '%s' can be accessed from tenants %s(default) and %s. " |
There was a problem hiding this comment.
For these new output formats, do we have some spec or context for this new multi-tenant behavior? I ask this because I want to learn if we should only output one subscription while it exists multi tenants or if we should output all of them and mark one of them as default one.
There was a problem hiding this comment.
We SHOULD and WILL display them all. But CLI is currently keying on subscriptionId in the account list which makes showing all of them impossible. This requires an overhaul of the account persistence mechanism.
|
In addition, changing api version will influence many other commands. Please make sure all the tests pass and re-record related test files. |
|
@Juliehzl, thanks for the notification. I was planning to do that but don't have time yet. |
# Conflicts: # src/azure-cli/azure/cli/command_modules/appconfig/tests/latest/export_features_prop.json
|
This test failure is caused by urllib3's breaking change urllib3/urllib3#1647 at util/url.py#L253-L255. urllib3 1.24 keeps the trailing dot We need to record with at least |
# Conflicts: # src/azure-cli/azure/cli/command_modules/appconfig/tests/latest/export_features.json
|
For botservice, the recorded YAML files are manually edited to replace |
|
Per discussion with Lighthouse team, closing as |
# Conflicts: # src/azure-cli/azure/cli/command_modules/botservice/tests/latest/recordings/test_botservice_create_should_remove_invalid_char_from_name_when_registration.yaml # src/azure-cli/azure/cli/command_modules/botservice/tests/latest/recordings/test_botservice_create_should_remove_invalid_char_from_name_when_webapp.yaml
# Conflicts: # src/azure-cli/HISTORY.rst
| }) | ||
| } | ||
| # for Subscriptions - List REST API 2019-06-01's subscription account | ||
| if subscription_dict[_SUBSCRIPTION_NAME] != _TENANT_LEVEL_ACCOUNT_NAME: |
There was a problem hiding this comment.
_TENANT_LEVEL_ACCOUNT_NAME [](start = 56, length = 26)
If a subscription is a tenant level account, does it mean it only belong to one tenant? In this case, the rest api response does not has homeTenentId? why do we need this check here?
There was a problem hiding this comment.
If a subscription is a tenant level account, does it mean it only belong to one tenant?
In that case, the account is a tenant with no subscriptions, not "belong to". The naming of subscription_dict is inaccurate. It contains both subscription and tenant accounts.
In this case, the rest api response does not has homeTenentId?
This tenant account is not generated from REST, but manually built up:
azure-cli/src/azure-cli-core/azure/cli/core/_profile.py
Lines 270 to 279 in 944c0c3
Why do we need this check here?
It doesn't make sense to include home_tenant_id and managed_by_tenants (whichs are subscription account's attributes) for a tenant account.
In fact, this is all due to the faulty original design that mixes subscription and tenant in the same list. This will and must be changed in the future to reflect the hierarchy. Tenant is a one-level-higher concept than subscription.
|
Hi @jiasli , all the logic implement here is to set homeTenantTd and managedByTenants value. I'm wondering, where do we use these properties? Just used to show to end user ? |
| sub_to_add.subscription_id, sub_to_add.display_name, | ||
| sub_to_compare.tenant_id, sub_to_add.tenant_id) | ||
| add_sub = False | ||
| break |
There was a problem hiding this comment.
if there are n subscriptions belong to multi tenants, we will write n lines of such similar warning here ? Can we just use a common message to combine these similar messages ?
# Conflicts: # src/azure-cli/azure/cli/command_modules/vm/tests/latest/recordings/test_vm_create_existing_ids_options.yaml # src/azure-cli/azure/cli/command_modules/vm/tests/latest/recordings/test_vm_create_existing_options.yaml # src/azure-cli/azure/cli/command_modules/vm/tests/latest/recordings/test_vmss_create_existing_ids_options.yaml # src/azure-cli/azure/cli/command_modules/vm/tests/latest/recordings/test_vmss_create_existing_options.yaml
|
There are conflicting files |
Juliehzl
left a comment
There was a problem hiding this comment.
No more concern for me if all the tests pass.
| subscriptions = self._find_using_specific_tenant( | ||
| tenant_id, | ||
| temp_credentials[_ACCESS_TOKEN]) | ||
| all_subscriptions.extend(subscriptions) |
There was a problem hiding this comment.
When are all_subscriptions different between old behavior and your new logic? when a subscription exists in multiple tenants? for example, it exists in two tenants, will it only show once in all_subscriptions?
There was a problem hiding this comment.
Yes. A subscription will only appear once since we are keying by subscriptionId. The old behavior is newly listed ones overwriting previously listed ones, while the new behavior is newly listed ones being discarded. Thus, we can make sure subscriptions from user's home tenant is preferred (home tenant is listed earlier).
History Notes:
[Profile] Preview: Add new attributes
homeTenantIdandmanagedByTenantsto subscription accounts. Please re-runaz loginfor the changes to take effect[Profile]
az login: Show a warning when a subscription is listed from more than one tenants and default to the first one. To select a specific tenant when accessing this subscription, please include--tenantinaz loginUpdate on 2020-02-04
Rename:
This PR does these tasks:
homeTenantIdandmanagedByTenantsfor subscription accounts while not changing the fields of bare tenant accounts generated by specifying--allow-no-subscriptionsTo test:
Run
az loginwhich will show a warning when a subscription is listed from more than one tenants:In the response
homeTenantIdandmanagedByTenantsare added.homeTenantIdmaps totenantIdof Subscriptions - List REST API (GUID is trimmed for simplicity):{ "cloudName": "AzureCloud", "id": "9535", "isDefault": false, "managedByTenants": [ { "tenantId": "2b8e" }, { "tenantId": "d6ad" } ], "name": "Visual Studio Enterprise", "state": "Disabled", "homeTenantId": "72f9", // maps to tenantId from REST API "tenantId": "72f9", // this is the tenant ID of the token "user": { "name": "@microsoft.com", "type": "user" }Then login with
az login -t 2b8e, this subscription is now as below. Notice thattenantIdhas changed to reflect the token tenant ID.{ "cloudName": "AzureCloud", "id": "9535", "isDefault": false, "managedByTenants": [ { "tenantId": "2b8e" } ], "name": "Visual Studio Enterprise", "state": "Disabled", "homeTenantId": "72f9", "tenantId": "2b8e", // tenant ID is switched to the one specified by -t "user": { "name": "@microsoft.com", "type": "user" } }This allows the user to operate on subscription
9535from tenant2b8e.For backward compatibility, switch profile with
az cloud set -n AzureCloud --profile 2019-03-01-hybridand login againaz login -t 2b8e{ "cloudName": "AzureCloud", "id": "9535", "isDefault": false, "name": "Visual Studio Enterprise", "state": "Disabled", "tenantId": "2b8e", "user": { "name": "@microsoft.com", "type": "user" } }This time, everything is the same as before. To switch cloud back, run
az cloud set -n AzureCloud --profile latest