-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Add new az ad app permissions grant and list commands for OAuth2 permissions for AAD registered apps #6975
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
yugangw-msft
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.
@shanepeckham, thanks for the contribution. Good improvement! I left a few comments, mostly to help get your change integrate well with the existing commands
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.
I believe the command should be grant, instead of update
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.
Changed to grant and reworked for new command ad app permission grant
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.
Does AAD graph support "permission revoke"? If yes, I suggest you author it like az ad app permission grant so we can add revoke and list later
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.
Changed to g.custom_command('permission grant', 'grant_application')
Also added g.custom_command('permission list', 'list_granted_application')
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.
I would suggest you back out the formatting change and only submit the command change
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.
Fixed formatting - accidental change
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.
unnecessary, for not optional argument, CLI command parser will ensure users supply the values.
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.
Removed optional argument validation
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.
It this a right assumption? If you like to focus on common permission, I suggest add a elif by comparing with the real id of impersonation and then keep the guid for the rest. Also move the code block to end since this is only for display.
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 pass the scope into the payload and is required to grant permissions, so we can't move it. This is a common well know AAD GUID and as far as I know this scope needs to be set differently as per the code block.
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.
Want to get on the same page with you. The 00000002-0000-0000-c000-000000000000, to me, is the resource id of AAD graph. Scope in this context, means delegated permissions. Right?
If yes, the code here means if the resource is AAD graph, the delegated permission will be READ. For native apps, this permission is way too limited, can we also use user_impersonation, or expose as an argument if we can't make a reasonable default 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.
Removed this for now and we can re-implement if required
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.
Suggest name it sp_object_id, as object id is not a service principal name. SPN is either related application's id, or app id uri.
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.
Implemented as client_sp_object_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.
I would suggest you just call list_sps in the same file.
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.
Extended list_sps to include search by appid/clientid
def list_sps(client, spn=None, display_name=None, query_filter=None, appid=None):
sub_filters = []
if query_filter:
sub_filters.append(query_filter)
if spn:
sub_filters.append("servicePrincipalNames/any(c:c eq '{}')".format(spn))
if display_name:
sub_filters.append("startswith(displayName,'{}')".format(display_name))
if appid:
sub_filters.append("appId eq '{}'".format(appid))
return client.list(filter=(' and '.join(sub_filters)))
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.
should be --app-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.
Implemented
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.
I suggest do not redefine, rather let the default one take over
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.
Implemented
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.
Please rebase and get rid of the change which have been merged into the public repo
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.
Rebased
1a34dd9 to
a0ae68d
Compare
yugangw-msft
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.
A few more suggestions. Please also fix linter error reported by CI
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.
You can just use _resolve_service_principal which returns the object id you need.
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.
Implemented and extended to query by appId
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.
please check out my comments below. If you use _resolve_service_principal, then this change can be reverted
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.
Reverted
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.
Want to get on the same page with you. The 00000002-0000-0000-c000-000000000000, to me, is the resource id of AAD graph. Scope in this context, means delegated permissions. Right?
If yes, the code here means if the resource is AAD graph, the delegated permission will be READ. For native apps, this permission is way too limited, can we also use user_impersonation, or expose as an argument if we can't make a reasonable default 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.
Again, please back out the format change here and below. The change here is not correct anyway.
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.
Backed out
5a2acc1 to
2466c9b
Compare
2466c9b to
4445dc3
Compare
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.
One last suggestion hope to help you write less code. Also please get CI passing by doing 2 things:
a. Add group help to ad app permission
b. fix lint error(you can just suppress them using #pylint: disable=no-member)
Once this finalized, I will coordinate to get you spec pr and sdk published
|
|
||
|
|
||
| def _resolve_service_principal(client, identifier): | ||
| def _resolve_service_principal(client, identifier=None, appid=None): |
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.
Can you please double check this is needed? appid and app id uri are both service principal names which the existing query below should cover it. I did a quick check just now for reference, but let me know if you do need it.
(env) D:\sdk\azure-cli>az ad app show --id e96b494b-61a2-4a42-a33c-e11ab1f1a6b6
{
"appId": "e96b494b-61a2-4a42-a33c-e11ab1f1a6b6",
<omit irrelevant fields>
}
(env) D:\sdk\azure-cli>az ad sp show --id e96b494b-61a2-4a42-a33c-e11ab1f1a6b6
{
"appDisplayName": "yugangw-op2",
"appId": "e96b494b-61a2-4a42-a33c-e11ab1f1a6b6",
"appOwnerTenantId": "54826b22-38d6-4fb2-bad9-b7b93a3e9c5a",
"objectId": "e0a58f57-dcae-48ab-98b6-ee173a6097fa",
"objectType": "ServicePrincipal",
servicePrincipalNames": [
"http://yugangw-op2",
"e96b494b-61a2-4a42-a33c-e11ab1f1a6b6"
],
"servicePrincipalType": "Application",
<omit irrelevant fields>
}
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.
@yugangw-msft I can confirm that the appId can be the same as the objectId, but it is not always. In all of my test cases, like for example creating an app in the portal, the SP associated with the app will be autogenerated and needs to be searched for by the appId. The code is definitely needed.
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.
object id is irrelevant here which is different thing from the app id. I am talking about the app id of the application. The service principal provisioned in the tenant for the application should have the app id as part of the servicePrincipalNames array. If you see the appid is not in the servicePrincipalNames of the SP then your change is definitely needed. To get my comment clear, I am talking about the following array in the SP object
servicePrincipalNames": [
"http://yugangw-op2",
"e96b494b-61a2-4a42-a33c-e11ab1f1a6b6" <---this 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.
@yugangw-msft Not sure if I am missing something here, this is the flow:
- I have the appId/clientId of my app
- I need to get the objectId of the SP associated with my app
- The app array does not contain the objectId of the SP
- I cannot query the SP by the objectId as I do not have the objectId, I only have the appId
- I query the SP by the appId which gives me the SP ObjectId
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 flow is right. My comment is on step 5 that you don't need to update _resolve_service_principal to take a new argument of appid, rather just pass the app id to the existing argument of identifier which should work.
The reason is the _resolve_service_principal queries for SP using servicePrincipalNames, and appid is one of service principal name, so the query should just work.
If you have tried but not working, please let me know
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.
@yugangw-msft , thank you, in my tests this was not working for me. Will try again
just pass the app id to the existing argument of identifier which should work
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.
thanks. Is it easy for you to share a repro for me to try out?
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.
@yugangw-msft , you are right - my tests were bad, will remove appId from query and rebase
|
All are taken care through #7611 |
This is needed so that we can programmatically grant and list OAuth2 consent to an application in Azure Active Directory. This is the supported and correct way to do this respecting customer approval workflows. Example use case includes Azure Kubernetes Service RBAC integration with Azure Active Directory.
This PR has the following dependencies upstream that need to be merged first:
New command has the following help format:
Usage:
This checklist is used to make sure that common guidelines for a pull request are followed.