Revo.MSPartner.psm1
function New-RevoPartnerAccess { param( [parameter(Mandatory = $true, ParameterSetName = "ServicePrincipal")] [string]$TenantID, [parameter(Mandatory = $true, ParameterSetName = "ServicePrincipal")] [string]$ClientID, [parameter(Mandatory = $true, ParameterSetName = "ServicePrincipal")] [string]$CertificateLocation, [parameter(Mandatory = $true, ParameterSetName = "ServicePrincipal")] [securestring]$CertificatePassword, [parameter(Mandatory = $false, ParameterSetName = "ServicePrincipal")] [switch]$SecureOutput, [parameter(Mandatory = $false, ParameterSetName = "ServicePrincipal")] [switch]$ForceRefresh, [parameter(Mandatory = $false, ParameterSetName = "ServicePrincipal")] [switch]$ClearToken ) begin { $ErrorActionPreference = "SilentlyContinue" } process { $Module = Get-Module -Name MSAL.PS -ListAvailable if ($null -eq $Module) { Install-Module -Name MSAL.PS -Scope CurrentUser -Force -Confirm:$false; Import-Module -Name MSAL.PS -Scope CurrentUser } else { Import-Module -Name MSAL.PS -Scope CurrentUser } if ($ClearToken) { Remove-Variable -Name RevoPartnerBearerToken -Force -ErrorAction SilentlyContinue Remove-Variable -Name RevoPartnerBearerTokenDetails -Force -ErrorAction SilentlyContinue Clear-MsalTokenCache -ErrorAction SilentlyContinue } $CerLocValidation = Test-Path -Path $CertificateLocation -ErrorAction SilentlyContinue if (!$CerLocValidation) { $CertLocationInvalid = $true } else { $ErrorActionPreference = 'SilentlyContinue' $Flag = [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable $Certificate = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($CertificateLocation, $CertificatePassword, $Flag) if ($Certificate) { $BearerValue = Get-Variable -Name "RevoPartnerBearerToken" -ValueOnly -ErrorAction SilentlyContinue if ($ForceRefresh -and $BearerValue) { $ParseInformation = Get-MsalToken -ClientId $ClientID -TenantId $TenantID -ClientCertificate $Certificate -Scopes 'https://graph.windows.net/.default' -ForceRefresh } else { $ParseInformation = Get-MsalToken -ClientId $ClientID -TenantId $TenantID -ClientCertificate $Certificate -Scopes 'https://graph.windows.net/.default' } } else { $CertPasswordInvalid = $true } } } end { $ErrorActionPreference = "Continue" if ($CertLocationInvalid) { Write-Error "Can't find the certificate. Please check your path." } elseif ($CertPasswordInvalid) { Write-Error "Certificate password incorrect. Please check the value." } else { New-Variable -Name "RevoPartnerBearerToken" -Value ($ParseInformation.TokenType + " " + $ParseInformation.AccessToken) -Scope Global -Force -ErrorAction SilentlyContinue New-Variable -Name "RevoPartnerBearerTokenDetails" -Value $ParseInformation -Scope Global -Force -ErrorAction SilentlyContinue if (!$SecureOutput) { Return $ParseInformation.TokenType + " " + $ParseInformation.AccessToken } } } } function New-RevoPartnerAccessByToken { param( [parameter(Mandatory = $true, ParameterSetName = "ServicePrincipal")] [string]$ClientID, [parameter(Mandatory = $true, ParameterSetName = "ServicePrincipal")] [string]$ResponseToken, [parameter(Mandatory = $true, ParameterSetName = "ServicePrincipal")] [string]$RefreshToken, [parameter(Mandatory = $false, ParameterSetName = "ServicePrincipal")] [switch]$SecureOutput, [parameter(Mandatory = $false, ParameterSetName = "ServicePrincipal")] [string]$TenantID ) begin { $ErrorActionPreference = "SilentlyContinue" } process { if ($TenantID) { $Internal_AuthHost = "https://login.microsoftonline.com/$TenantID/oauth2/v2.0/token" } else { $Internal_AuthHost = 'https://login.microsoftonline.com/common/oauth2/v2.0/token' } $Internal_ContentType = 'application/x-www-form-urlencoded' $Internal_Body = "client_id=$ENV:HS_AppId&scope=https://api.partnercenter.microsoft.com/user_impersonation%20offline_access&code=$ENV:HS_ResponseToken&grant_type=refresh_token&refresh_token=$ENV:HS_RefreshToken" $Internal_AccessToken = Invoke-WebRequest -Uri $Internal_AuthHost -ContentType $Internal_ContentType -Method POST -Body $Internal_Body $ParseInformation = ($Internal_AccessToken.Content | ConvertFrom-Json) } end { $ErrorActionPreference = "Continue" New-Variable -Name "RevoPartnerBearerToken" -Value ($ParseInformation.token_type + " " + $ParseInformation.access_token) -Scope Global -Force -ErrorAction SilentlyContinue New-Variable -Name "RevoPartnerBearerTokenDetails" -Value $ParseInformation -Scope Global -Force -ErrorAction SilentlyContinue if (!$SecureOutput) { Return $ParseInformation.token_type + " " + $ParseInformation.access_token } } } function Get-RevoPartnerResources { param( [parameter(Mandatory = $true, ParameterSetName = "Predefined")] [parameter(Mandatory = $true, ParameterSetName = "Subscriptions")] [parameter(Mandatory = $true, ParameterSetName = "RoleMember")] [parameter(Mandatory = $true, ParameterSetName = "InvoiceDownload")] [parameter(Mandatory = $true, ParameterSetName = "InvoiceLineItems")] [ValidateSet( "Customers", "PartnerProfile", "Subscriptions", "SupportProfile", "Organization", "ResellerRequestLink", "Roles", "RoleMember", "Invoices", "InvoiceDownload", "InvoiceLineItems", IgnoreCase = $true)] [string]$Resource, [parameter(Mandatory = $true, ParameterSetName = "Custom")] [string]$CustomURL, [parameter(Mandatory = $true, ParameterSetName = "Subscriptions")] [ValidateScript({ $Resource -eq 'Subscriptions' }, ErrorMessage = "CustomerID parameters it's only available on Subscriptions resource.")] [ValidatePattern('^[{]?[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}[}]?$', ErrorMessage = "CustomerID must be the GUID of the Customer Tenant ID.")] [string]$CustomerID, [parameter(Mandatory = $true, ParameterSetName = "RoleMember")] [ValidateScript({ $Resource -eq 'RoleMember' }, ErrorMessage = "RoleID parameters it's only available on RoleMember resource.")] [ValidatePattern('^[{]?[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}[}]?$', ErrorMessage = "RoleID must be the GUID of the Role.")] [string]$RoleID, [parameter(Mandatory = $true, ParameterSetName = "InvoiceDownload")] [parameter(Mandatory = $true, ParameterSetName = "InvoiceLineItems")] [ValidateScript({ $Resource -eq 'InvoiceDownload' -or $Resource -eq 'InvoiceLineItems' }, ErrorMessage = "InvoiceID parameters it's only available on InvoiceDownload resource.")] [string]$InvoiceID, [parameter(ParameterSetName = "Predefined")] [parameter(Mandatory = $true, ParameterSetName = "InvoiceDownload")] [ValidateScript({ $Resource -eq 'InvoiceDownload' }, ErrorMessage = "DownloadPath parameters it's only available on InvoiceDownload resource.")] [string]$DownloadPath, [parameter(Mandatory = $true, ParameterSetName = "InvoiceLineItems")] [ValidateScript({ $Resource -eq 'InvoiceLineItems' }, ErrorMessage = "InlineType parameters it's only available on InvoiceLineItems resource.")] [ValidateSet( "Recurring", "OneTime", IgnoreCase = $true)] [string]$InlineType ) begin { $ErrorActionPreference = "Stop" if ($Resource -eq 'Subscriptions' -and !$CustomerID) { Write-Error "Customer Tenant Id must be send by parameter CustomerID. Please validate and try again." break } $ErrorActionPreference = "SilentlyContinue" } process { $BaseURL = "https://api.partnercenter.microsoft.com/v1" if ($CustomURL) { $ResourceURL = $CustomURL } else { switch ($Resource) { Customers { $ResourceURL = "/customers" } PartnerProfile { $ResourceURL = "/profiles/mpn" } SupportProfile { $ResourceURL = "/profiles/support" } Organization { $ResourceURL = '/profiles/organization' } ResellerRequestLink { $ResourceURL = '/customers/relationshiprequests' } Subscriptions { $ResourceURL = "/customers/$CustomerID/subscriptions" } Roles { $ResourceURL = "/roles" } RoleMember { $ResourceURL = "/roles/$RoleID/usermembers" } Invoices { $ResourceURL = "/invoices" } InvoiceDownload { $ResourceURL = "/invoices/$InvoiceID/documents/statement" } InvoiceLineItems { if ($InlineType -eq "Recurring") { $ResourceURL = "/invoices/$InvoiceID/lineitems?provider=office&invoicelineitemtype=billinglineitems&size=2000" } else { $ResourceURL = "/invoices/$InvoiceID/lineitems?provider=onetime&invoicelineitemtype=billinglineitems&size=2000" } } Default { $ResourceURL = "/profiles/mpn" } } } $FinalURL = ($BaseURL + $ResourceURL) $AccessToken = Get-Variable -Name "RevoPartnerBearerToken" -ValueOnly -ErrorAction SilentlyContinue if ($null -ne $AccessToken) { $Headers = @{} $Headers.Add("Authorization", $AccessToken) $Headers.Add("Accept", "application/json") $Headers.Add("X-Locale", "es-PE") if ($Resource -eq 'InvoiceDownload') { $WebRequest = Invoke-WebRequest -Method Get -Uri $FinalURL -Headers $Headers -ErrorVariable InvokeError -OutFile (Join-Path $DownloadPath "$InvoiceID.pdf") } else { $WebRequest = Invoke-WebRequest -Method Get -Uri $FinalURL -Headers $Headers -ErrorVariable InvokeError } if ($InvokeError.Count -gt 0) { if ($InvokeError.ErrorRecord.ToString() -like "This resource can't be accessed by application credentials.") { $ModuleError = "This resource can't be accessed by application credentials. Try something diferent or use another credentials." } elseif ($InvokeError.ErrorRecord.ErrorDetails) { switch (($InvokeError.ErrorRecord.ErrorDetails.Message | ConvertFrom-Json -Depth 10).code) { 20002 { $ModuleError = ($InvokeError.ErrorRecord.ErrorDetails.Message | ConvertFrom-Json -Depth 10).description } 403 { $ModuleError = ($InvokeError.ErrorRecord.ErrorDetails.Message | ConvertFrom-Json -Depth 10).description } default { $ModuleError = "Undetermined error. Please try with other resource." } } } else { switch (($InvokeError.ErrorRecord.ErrorDetails.Message | ConvertFrom-Json -Depth 10).error.code) { 'ExpiredAuthenticationToken' { $ModuleError = "Your bearer token was expired, please reconnect with New-RevoPartnerAccess" } 'AuthenticationFailedInvalidHeader' { $ModuleError = "Your bearer token was malformed, please reconnect with New-RevoPartnerAccess" } 'AuthenticationFailed' { $ModuleError = "Your bearer token was invalid, please reconnect with New-RevoPartnerAccess" } default { $ModuleError = "Undetermined error. Please try with other resource or reconnect." } } } } else { if ($WebRequest) { if ($WebRequest.Content[0] -ne '{') { $Output = $WebRequest.Content.Substring(1) | ConvertFrom-Json -Depth 10 } else { $Output = $WebRequest.Content | ConvertFrom-Json -Depth 10 } } else { if ($Resource -ne 'InvoiceDownload') { $ModuleError = "Nothings returns. Try again." } } } } else { $ModuleError = "Cannot get the bearer token, please first connect by New-RevoPartnerAccess" } } end { $ErrorActionPreference = "Continue" if ($ModuleError) { Write-Error $ModuleError } else { if ($Resource -eq 'InvoiceDownload') { Return (Join-Path $DownloadPath "$InvoiceID.pdf") } else{ Return $Output } } } } |