Skip to content

New-MgSitePermission - does it even work? #2024

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

Closed
JeremyTBradshaw opened this issue May 19, 2023 · 8 comments
Closed

New-MgSitePermission - does it even work? #2024

JeremyTBradshaw opened this issue May 19, 2023 · 8 comments

Comments

@JeremyTBradshaw
Copy link

I'm trying but failing to get this cmdlet to work, using the latest version in either Windows PowerShell or PowerShell Core. I get "Invalid Request" nothing more. I'm following the example on this page exactly: https://learn.microsoft.com/en-us/powershell/module/microsoft.graph.sites/new-mgsitepermission?view=graph-powershell-1.0#examples

I also notice that ErrorDetails is populated in PowerShell core, but not in Windows PowerShell. While looking into that I've noticed there is no additional detail nested inside of ErrorDetail, just the "message".

Here's what I'm doing (id's falsified for privacy):

$body = @{
        roles               = @("write")
        grantedToIdentities = @(
            @{
                application = {
                    id = '4cb5473a-a53e-3cb7-5628-6a276544960e'
                    displayName = 'My registered app with consent-granted Sites.Selected'
                }
            }
        )
    }
}
Connect-MgGraph -AppId <appid/clientId who has Sites.FullControl.All granted/consented> -TenantId <my Tid> -CertificateThumbprint <cert thumbprint>
New-MgSitePermission -SiteId <my site ID> -BodyParameter $ps.Body

I get back:

Windows PowerShell:

writeErrorStream      : True
Exception             : Microsoft.Graph.PowerShell.Runtime.RestException`1[Microsoft.Graph.PowerShell.Models.IMicrosoftGraphODataErrorsOdataError]: Invalid request
TargetObject          : { SiteId = REMOVED, body = Microsoft.Graph.PowerShell.Models.MicrosoftGraphPermission1 }
CategoryInfo          : InvalidOperation: ({ SiteId = f47c...phPermission1 }:<>f__AnonymousType0`2) [New-MgSitePermission_Create], RestException`1
FullyQualifiedErrorId : invalidRequest,Microsoft.Graph.PowerShell.Cmdlets.NewMgSitePermission_Create
ErrorDetails          : Invalid request
InvocationInfo        : System.Management.Automation.InvocationInfo
ScriptStackTrace      : at New-MgSitePermission<Process>, C:\Users\MYUSER\OneDrive - MYORG\Documents\WindowsPowerShell\Modules\Microsoft.Graph.Sites\1.27.0\exports\v1.0\ProxyCmdletDefinitions.ps1: line 58281
                        at <ScriptBlock>, <No file>: line 1
PipelineIterationInfo : {0, 1}
PSMessageDetails      :

PowerShell Core:

Exception             : Microsoft.Graph.PowerShell.Runtime.RestException`1[Microsoft.Graph.PowerShell.Models.IMicrosoft
                        GraphODataErrorsOdataError]: Invalid request
TargetObject          : { SiteId = MYSITEID, body =
                        Microsoft.Graph.PowerShell.Models.MicrosoftGraphPermission1 }
CategoryInfo          : InvalidOperation: ({ SiteId = f47cd5b5…tGraphPermission1 }:<>f__AnonymousType0`2)
                        [New-MgSitePermission_Create], RestException`1
FullyQualifiedErrorId : invalidRequest,Microsoft.Graph.PowerShell.Cmdlets.NewMgSitePermission_Create
ErrorDetails          : Invalid request
InvocationInfo        : System.Management.Automation.InvocationInfo
ScriptStackTrace      : at New-MgSitePermission<Process>, C:\Users\MYUSER\OneDrive - MYORG\Document
                        s\PowerShell\Modules\Microsoft.Graph.Sites\1.27.0\exports\v1.0\ProxyCmdletDefinitions.ps1:
                        line 58281
                        at <ScriptBlock>, <No file>: line 1
PipelineIterationInfo : {0, 1}
PSMessageDetails      :

I also tested with MSGraphPSEssentials' New-MSGraphRequest and it's the same. Tested again with Invoke-RestMethod and then once more with Invoke-WebRequest - they're all failing the same.

Lastly, for another app/site where the Sites.Selected setup has already been configured (using MSGraphPSEssentials, in the past), I'm also struggling to get New-MgSiteListItem working. Similar stuff, wherein the errors that come back are not verbose at all, just 400 Bad Request. I feel like the errors coming back used to be way more verbose, but maybe it's just the sites resource that is very lacking in this area? Please help.

@ghost ghost added the ToTriage label May 19, 2023
@JeremyTBradshaw
Copy link
Author

Alas, I found a few more details in $error[0].Exception (PS Core):

PS C:\Users\MYUSER> $err.ErrorDetails | fl

Message           : Invalid request
RecommendedAction :


PS C:\Users\MYUSER> $err.Exception

Error           : Microsoft.Graph.PowerShell.Models.MicrosoftGraphODataErrorsOdataError
StatusCode      : BadRequest
Code            : invalidRequest
RequestMessage  : Method: POST, RequestUri: 'https://graph.microsoft.com/v1.0/sites/MYSITEIDE/permissions', Version: 1.1, Content: <null>, Headers:
                  {
                    FeatureFlag: 00000047
                    Cache-Control: no-store, no-cache
                    SdkVersion: graph-powershell/1.27.0
                    SdkVersion: Graph-dotnet-1.25.1
                    Accept-Encoding: gzip
                  }
ResponseHeaders : {[Cache-Control, System.String[]], [Transfer-Encoding, System.String[]], [Vary, System.String[]], [Strict-Transport-Security, System.String[]]…}
ResponseBody    : {"error":{"code":"invalidRequest","message":"Invalid request","innerError":{"date":"2023-05-19T18:02:05","request-id":"d081d9d3-ef0c-4f74-a6a1-a1e473b4063a","client-request-id":"d081d9d3-ef0c-4f74-a6a1-a1e473b4063a"}}}
ClientRequestId :
RequestId       :
Message         : Invalid request
Action          :
TargetSite      :
Data            : {}
InnerException  :
HelpLink        :
Source          :
HResult         : -2146233088
StackTrace      :

@JeremyTBradshaw
Copy link
Author

And lastly, realized the errors sent back are very intentionally formatted a very specific way, and everything I'm getting back is following suit, but still I'm not seeing anything other than BadRequest/InvalidRequest
https://learn.microsoft.com/en-us/graph/errors
https://docs.oasis-open.org/odata/odata-json-format/v4.0/os/odata-json-format-v4.0-os.html#_Toc372793091

PS C:\Users\MYUSER> $err.Exception.error |fl

Error                : Microsoft.Graph.PowerShell.Models.MicrosoftGraphODataErrorsMainError
AdditionalProperties : {}

PS C:\Users\MYUSER> $err.Exception.error.error

Code           Message         Target
----           -------         ------
invalidRequest Invalid request

PS C:\Users\MYUSER> $err.Exception.error.error |fl -force

Code                 : invalidRequest
Details              :
Innererror           : Microsoft.Graph.PowerShell.Models.MicrosoftGraphODataErrorsInnerError
Message              : Invalid request
Target               :
AdditionalProperties : {}

PS C:\Users\MYUSER> $err.Exception.error.error.innererror |fl -force

AdditionalProperties : {}

@JeremyTBradshaw
Copy link
Author

I can't help but feel this is the exact same issue as this one - #1185 - which was for New-MgSiteListItem / Update-MgSiteListItem. I feel like the very basic error "Invalid Request" with zero additional info to help is the telling evidence. My current guess is that when #1185 was resolved, not all the applicable commands were fixed.

@JeremyTBradshaw
Copy link
Author

And I'm just gonna keep on pumping details into here. The way these cmdlets are documented is extremely insufficient. They all state to do Get-Help -Online and then review the NOTES sections. well those NOTES are A) massive documents with hardly any formatting to make them reader-friendly, and B) inadequate. As an example, here are the notes about the BodyParameter parameter:

.Notes
COMPLEX PARAMETER PROPERTIES

To create the parameters described below, construct a hash table containing the appropriate properties. For information on hash tables, run Get-Help about_Hash_Tables.

BODYPARAMETER <IMicrosoftGraphPermission>: permission
  [(Any) <Object>]: This indicates any property can be added to this object.
  [Id <String>]: The unique idenfier for an entity. Read-only.
  [ExpirationDateTime <DateTime?>]: A format of yyyy-MM-ddTHH:mm:ssZ of DateTimeOffset indicates the expiration time of the permission. DateTime.MinValue indicates there is no expiration set for this permission. Optional.
  [GrantedTo <IMicrosoftGraphIdentitySet>]: identitySet
    [(Any) <Object>]: This indicates any property can be added to this object.
    [Application <IMicrosoftGraphIdentity>]: identity
      [(Any) <Object>]: This indicates any property can be added to this object.
      [DisplayName <String>]: The display name of the identity. Note that this might not always be available or up to date. For example, if a user changes their display name, the API might show the new value in a future response, but the items associated with the user won't show up as having changed when using delta.
      [Id <String>]: Unique identifier for the identity.
    [Device <IMicrosoftGraphIdentity>]: identity
    [User <IMicrosoftGraphIdentity>]: identity
  [GrantedToIdentities <IMicrosoftGraphIdentitySet[]>]: 
  [GrantedToIdentitiesV2 <IMicrosoftGraphSharePointIdentitySet[]>]: For link type permissions, the details of the users to whom permission was granted. Read-only.
    [Application <IMicrosoftGraphIdentity>]: identity
    [Device <IMicrosoftGraphIdentity>]: identity
    [User <IMicrosoftGraphIdentity>]: identity
    [Group <IMicrosoftGraphIdentity>]: identity
    [SiteGroup <IMicrosoftGraphSharePointIdentity>]: sharePointIdentity
      [(Any) <Object>]: This indicates any property can be added to this object.
      [DisplayName <String>]: The display name of the identity. Note that this might not always be available or up to date. For example, if a user changes their display name, the API might show the new value in a future response, but the items associated with the user won't show up as having changed when using delta.
      [Id <String>]: Unique identifier for the identity.
      [LoginName <String>]: The sign in name of the SharePoint identity.
    [SiteUser <IMicrosoftGraphSharePointIdentity>]: sharePointIdentity
  [GrantedToV2 <IMicrosoftGraphSharePointIdentitySet>]: sharePointIdentitySet
  [HasPassword <Boolean?>]: Indicates whether the password is set for this permission. This property only appears in the response. Optional. Read-only. For OneDrive Personal only..
  [InheritedFrom <IMicrosoftGraphItemReference>]: itemReference
    [(Any) <Object>]: This indicates any property can be added to this object.
    [DriveId <String>]: Unique identifier of the drive instance that contains the driveItem. Only returned if the item is located in a [drive][]. Read-only.
    [DriveType <String>]: Identifies the type of drive. Only returned if the item is located in a [drive][]. See [drive][] resource for values.
    [Id <String>]: Unique identifier of the driveItem in the drive or a listItem in a list. Read-only.
    [Name <String>]: The name of the item being referenced. Read-only.
    [Path <String>]: Path that can be used to navigate to the item. Read-only.
    [ShareId <String>]: A unique identifier for a shared resource that can be accessed via the [Shares][] API.
    [SharepointIds <IMicrosoftGraphSharepointIds>]: sharepointIds
      [(Any) <Object>]: This indicates any property can be added to this object.
      [ListId <String>]: The unique identifier (guid) for the item's list in SharePoint.
      [ListItemId <String>]: An integer identifier for the item within the containing list.
      [ListItemUniqueId <String>]: The unique identifier (guid) for the item within OneDrive for Business or a SharePoint site.
      [SiteId <String>]: The unique identifier (guid) for the item's site collection (SPSite).
      [SiteUrl <String>]: The SharePoint URL for the site that contains the item.
      [TenantId <String>]: The unique identifier (guid) for the tenancy.
      [WebId <String>]: The unique identifier (guid) for the item's site (SPWeb).
    [SiteId <String>]: For OneDrive for Business and SharePoint, this property represents the ID of the site that contains the parent document library of the driveItem resource or the parent list of the listItem resource. The value is the same as the id property of that [site][] resource. It is an opaque string that consists of three identifiers of the site. For OneDrive, this property is not populated.
  [Invitation <IMicrosoftGraphSharingInvitation>]: sharingInvitation
    [(Any) <Object>]: This indicates any property can be added to this object.
    [Email <String>]: The email address provided for the recipient of the sharing invitation. Read-only.
    [InvitedBy <IMicrosoftGraphIdentitySet>]: identitySet
    [RedeemedBy <String>]: 
    [SignInRequired <Boolean?>]: If true the recipient of the invitation needs to sign in in order to access the shared item. Read-only.
  [Link <IMicrosoftGraphSharingLink>]: sharingLink
    [(Any) <Object>]: This indicates any property can be added to this object.
    [Application <IMicrosoftGraphIdentity>]: identity
    [PreventsDownload <Boolean?>]: If true then the user can only use this link to view the item on the web, and cannot use it to download the contents of the item. Only for OneDrive for Business and SharePoint.
    [Scope <String>]: The scope of the link represented by this permission. Value anonymous indicates the link is usable by anyone, organization indicates the link is only usable for users signed into the same tenant.
    [Type <String>]: The type of the link created.
    [WebHtml <String>]: For embed links, this property contains the HTML code for an <iframe> element that will embed the item in a webpage.
    [WebUrl <String>]: A URL that opens the item in the browser on the OneDrive website.
  [Roles <String[]>]: The type of permission, for example, read. See below for the full list of roles. Read-only.
  [ShareId <String>]: A unique token that can be used to access this shared item via the **shares** API. Read-only.

Nowhere in there do a see any guidance as to what keys/fields NEED to be added to the hashtable. Based on the single example that is given, I know that 'roles' and 'grantedtoidentities' are what I'm after. But what about the rest of those things? No idea. Within the nested hashtable 'grantedtoidentities', there are again many possible fields yet the only example shows just 'id' and 'displayname'. When I mimic the example, it doesn't work and the error message is inadequate. I find it frustrating, and I feel the version numbers on these modules are way off. These things are in the 0.0.X stages. Not 2.0.0-release candidate stages.

@JeremyTBradshaw
Copy link
Author

And finally, here's my big moment.....

The problem with pebkac - I was missing the "@" in my body parameter, so my application wasn't been sent as a nested hashtable rather it was sort of a script block.

I had this: application = {
instead of this application = @{

Fixed now. Will leave my novel of comments here for blooper reel purposes but am now closing this issue.

🙇‍♂️

@ghost ghost removed the ToTriage label May 24, 2023
@mikew3432
Copy link

@JeremyTBradshaw re: your
application = {
id = '4cb5473a-a53e-3cb7-5628-6a276544960e'
Was your id the App Registration Object ID, or the Service Principal/Enterprise Application Object ID, or was it the Service Principal AppID?
Thanks much

@JeremyTBradshaw
Copy link
Author

@mikewoodd3432 that ID was the application's (App Registration) AppId/ClientId.

It seems backwards since ACL's/permissions generally deal with principals. Check this page though: https://learn.microsoft.com/en-us/graph/api/resources/identity?view=graph-rest-1.0
They mention sometimes you won't be able to know the id and to only supply displayName in those cases. I think that might be when the app registration is in someone else's tenant, such as multitenant app or System Managed Identities.

I don't find this documented, but I believe the recent Tech community blog post might state it (site is down right now) or various unofficial blog posts at least. It really should at least be documented on the page I linked above, ideally on several other official pages too, like anywhere they show an example permission object where it only shows "id".

@icguy
Copy link

icguy commented Aug 1, 2024

Fyi, I had the same problem with the same request and the same error using the dotnet SDK.

The problem in my case was that as of writing this according to the documentation you have to provide the GrantedTo field, which is wrong.

I had to switch to using the GrantedToIdentities field and everything worked.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants