-
Notifications
You must be signed in to change notification settings - Fork 3.3k
[Core][Profile] Support lighthouse multi-tenant subscription #11886
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is the difference between subscription_tenant_id and tenant_id?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because subscription models have api contraint, please use get_models() here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
| def _build_tenant_level_accounts(self, tenants): | |
| result = [] | |
| for t in tenants: | |
| s = self._new_account() | |
| s.id = '/subscriptions/' + t | |
| s.subscription = t | |
| s.tenant_id = t | |
| s.display_name = _TENANT_LEVEL_ACCOUNT_NAME | |
| result.append(s) | |
| return result |
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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).
jsntcy
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
![]()
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