2

I've just started trying to use the MgGraph module to try and perform operations on an Office 365 tenant to perform some configuration automation and I'm having a hard time wrapping my head around some of these cmdlets - in particular, the one I'm currently messing around with, New-MgAgreement, in an attempt to automatically upload a terms of use file.

I guess, for starters, is this a viable path to achieving this? Is there some other method I should attempt to be using to try and accomplish this? And if not, I guess how do I go about actually doing this? In short, this is what I've attempted:

  1. I'm utilizing a file picker via Windows Forms to prompt to capture the file I wish to upload
  2. I've created a hash for the File parameter of the cmdlet to satisfy the properties needed (I thought...) as well as filling out the other parameters needed to provide information about the terms of use object being created on the tenant
  3. When I try to run the command, I was initially told that "value cannot be null - parameter name source" which makes sense because I didn't see any parameters specifying source in the documentation for the physical file, so I tried simply adding a "source" parameter to the New-MgAgreement cmdlet thinking I just missed it in the documentation, but upon trying to do that, it tells me "a parameter cannot be found that matches parameter name 'source'.

Just to give an idea of my mindset when trying to achieve this, this is a code snippet hopefully illustrating the direction I'm trying to go about doing this:

Function Main {
    Connect-Modules
    Set-Tenant-Terms-Of-Use
    Get-Tenant-Terms-Of-Use
}

Function Connect-Modules {
    Connect-AzureAD
    $tenantId = Get-AzureADTenantDetail | Select-Object ObjectId
    C:\Windows\System32\cmd.exe /c start shell:AppsFolder\Microsoft.MicrosoftEdge_8wekyb3d8bbwe!MicrosoftEdge -private https://microsoft.com/devicelogin
    Connect-MgGraph -Scopes "User.Read.All", "Group.ReadWrite.All", "Agreement.Read.All", "Agreement.ReadWrite.All" -TenantId $tenantId.ObjectId.ToString()
}

Function Set-Tenant-Terms-Of-Use {
    $FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property @{ 
        InitialDirectory = [Environment]::GetFolderPath('Desktop')
        Filter = 'PDF (*.pdf)|*.pdf'
    }
    $companyName = Read-Host "Please enter your company name: "
    $null = $FileBrowser.ShowDialog()
    $fileHash = @{
        DisplayName = "All users terms of use";
        FileName = $FileBrowser.SafeFileName
        IsDefault = $true
        IsMajorVersion = $true
        Language = "English (Default)"
    }
    New-MgAgreement -DisplayName "$companyName Terms of Use" -File $fileHash -source $FileBrowser.FileName
}

Function Get-Tenant-Terms-Of-Use {
    $termsOfUse = Get-MgAgreement | Select-Object Id, DisplayName
    Write-Host $termsOfUse.Id.ToString()
    Write-Host $termsOfUse.DisplayName.ToString()
}

Main
Disconnect-MgGraph

I'll admit... I'm kind of completely lost on this one - I haven't really worked with Graph previously and I'm trying to get the hang of it since it seems to have a lot of capabilities that hook into areas of an Azure/O365 tenant that the other modules I'm used to using do not. I appreciate any schooling I can get on the topic! Thank you!

EDIT - So I can get this to work the way I want via Graph Explorer... I realized I needed to convert my file to base64 and put the value under the data property under the FileData parameter from within the File Parameter... but when I try to mirror this in PowerShell using the same parameter values as what is included in Graph Explorer I just get a "New-MgAgreement: Value cannot be null. Parameter name: source"... so it's just that I don't know how to format this using the cmdlet... and I just can't wrap my head around how to use the complex parameters apparently given the documentation.

RedMageKnight
  • 187
  • 2
  • 12
  • The [REST API docs](https://learn.microsoft.com/en-us/graph/api/agreement-post-agreements?view=graph-rest-1.0&tabs=http) may be helpful for how the request should be structured as it looks like the module you are using is just AutoRest anyway. – Ash May 03 '21 at 21:05
  • Yeah, I've been referencing both of those for guidance, but I guess I'm not sure where the actual file used for upload fits in to which parameter. I also missed the bodyparameter requirement, so maybe I'll try to use the FileBrowser object somewhere in there instead of the standalone File parameter. – RedMageKnight May 03 '21 at 21:22

1 Answers1

3

I was able to reproduce this issue. As an alternative, you can use Invoke-MgGraphRequest passing in the agreements endpoint and upload the agreement - this worked for me see below:

enter image description here

Agreement Resource Sample Data

$data 
{
  "displayName": "MSGraph Sample",
  "isViewingBeforeAcceptanceRequired": true,
  "files": [
    {
      "fileName": "TOU.pdf",
      "language": "en",
      "isDefault": true,
      "fileData": {
        "data": "SGVsbG8gd29ybGQ="
      }
    }
  ]
}
#Using IGR
Invoke-MgGraphRequest  -Uri https://graph.microsoft.com/v1.0/agreements -Method POST -Body $data

Please let me know if this helps and if you have further questions.

Diana
  • 690
  • 6
  • 14
  • Thank you @Diana, this was clutch for me and does exactly what I'm aiming to achieve. I'm hoping using Invoke-MgGraphRequest will be as clutch in some of the other flows I'm hoping to automate. Thank you so much for your help, I was banging my head against the wall with this for a couple of days and you've saved me a ton of additional headache :) – RedMageKnight May 05 '21 at 15:43