EnhancedGraphAO.psm1
#Region '.\Private\Convert-RsaParametersToPem.ps1' -1 function Convert-RsaParametersToPem { param ( [Parameter(Mandatory = $true)] [System.Security.Cryptography.RSAParameters]$rsaParameters ) $builder = [System.Text.StringBuilder]::new() $builder.AppendLine("-----BEGIN RSA PRIVATE KEY-----") | Out-Null # Combine all RSA parameters and convert them to Base64 $params = @( $rsaParameters.Modulus, $rsaParameters.Exponent, $rsaParameters.D, $rsaParameters.P, $rsaParameters.Q, $rsaParameters.DP, $rsaParameters.DQ, $rsaParameters.InverseQ ) foreach ($param in $params) { $b64 = [System.Convert]::ToBase64String($param) $builder.AppendLine($b64) | Out-Null } $builder.AppendLine("-----END RSA PRIVATE KEY-----") | Out-Null return $builder.ToString() } #EndRegion '.\Private\Convert-RsaParametersToPem.ps1' 32 #Region '.\Private\Generate-JWTAssertion.ps1' -1 function Generate-JWTAssertion { param ( [Parameter(Mandatory = $true)] [hashtable]$jwtHeader, [Parameter(Mandatory = $true)] [hashtable]$jwtPayload, [Parameter(Mandatory = $true)] [System.Security.Cryptography.X509Certificates.X509Certificate2]$cert ) $jwtHeaderJson = ($jwtHeader | ConvertTo-Json -Compress) $jwtPayloadJson = ($jwtPayload | ConvertTo-Json -Compress) $jwtHeaderEncoded = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($jwtHeaderJson)).TrimEnd('=').Replace('+', '-').Replace('/', '_') $jwtPayloadEncoded = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($jwtPayloadJson)).TrimEnd('=').Replace('+', '-').Replace('/', '_') $dataToSign = "$jwtHeaderEncoded.$jwtPayloadEncoded" $sha256 = [Security.Cryptography.SHA256]::Create() $hash = $sha256.ComputeHash([Text.Encoding]::UTF8.GetBytes($dataToSign)) $rsa = [Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($cert) $signature = [Convert]::ToBase64String($rsa.SignHash($hash, [Security.Cryptography.HashAlgorithmName]::SHA256, [Security.Cryptography.RSASignaturePadding]::Pkcs1)).TrimEnd('=').Replace('+', '-').Replace('/', '_') return "$dataToSign.$signature" } #EndRegion '.\Private\Generate-JWTAssertion.ps1' 25 #Region '.\Private\Get-UnixTime.ps1' -1 function Get-UnixTime { param ( [Parameter(Mandatory = $true)] [int]$offsetMinutes ) return [int]([DateTimeOffset]::UtcNow.ToUnixTimeSeconds() + ($offsetMinutes * 60)) } #EndRegion '.\Private\Get-UnixTime.ps1' 9 #Region '.\Private\Send-TokenRequest.ps1' -1 function Send-TokenRequest { param ( [Parameter(Mandatory = $true)] [string]$tokenEndpoint, [Parameter(Mandatory = $true)] [string]$clientId, [Parameter(Mandatory = $true)] [string]$clientAssertion ) $body = @{ client_id = $clientId scope = "https://graph.microsoft.com/.default" client_assertion = $clientAssertion client_assertion_type = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer" grant_type = "client_credentials" } try { Write-EnhancedLog -Message "Sending request to token endpoint: $tokenEndpoint" -Level "INFO" $response = Invoke-RestMethod -Method Post -Uri $tokenEndpoint -ContentType "application/x-www-form-urlencoded" -Body $body Write-EnhancedLog -Message "Successfully obtained access token." -Level "INFO" return $response.access_token } catch { Write-EnhancedLog -Message "Error obtaining access token: $_" throw $_ } } #EndRegion '.\Private\Send-TokenRequest.ps1' 30 #Region '.\Public\Add-KeyCredentialToApp.ps1' -1 # Associate certificate with App Registration function Add-KeyCredentialToApp { param ( [Parameter(Mandatory = $true)] [string]$AppId, [Parameter(Mandatory = $true)] [string]$CertPath ) # Read the certificate file using the constructor $cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($CertPath) $certBytes = $cert.RawData $base64Cert = [System.Convert]::ToBase64String($certBytes) # Convert certificate dates to DateTime and adjust for time zone $startDate = [datetime]::Parse($cert.NotBefore.ToString("o")) $endDate = [datetime]::Parse($cert.NotAfter.ToString("o")) # Adjust the start and end dates to ensure they are valid and in UTC $startDate = [System.TimeZoneInfo]::ConvertTimeBySystemTimeZoneId($startDate, [System.TimeZoneInfo]::Local.Id, 'UTC') $endDate = [System.TimeZoneInfo]::ConvertTimeBySystemTimeZoneId($endDate, [System.TimeZoneInfo]::Local.Id, 'UTC') # Adjust end date by subtracting one day to avoid potential end date issues $endDate = $endDate.AddDays(-1) # Prepare the key credential parameters $keyCredentialParams = @{ CustomKeyIdentifier = [System.Convert]::FromBase64String([System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($cert.Thumbprint.Substring(0, 32)))) DisplayName = "GraphCert" EndDateTime = $endDate StartDateTime = $startDate KeyId = [Guid]::NewGuid().ToString() Type = "AsymmetricX509Cert" Usage = "Verify" Key = $certBytes } # Create the key credential object $keyCredential = [Microsoft.Graph.PowerShell.Models.MicrosoftGraphKeyCredential]::new() $keyCredential.CustomKeyIdentifier = $keyCredentialParams.CustomKeyIdentifier $keyCredential.DisplayName = $keyCredentialParams.DisplayName $keyCredential.EndDateTime = $keyCredentialParams.EndDateTime $keyCredential.StartDateTime = $keyCredentialParams.StartDateTime $keyCredential.KeyId = $keyCredentialParams.KeyId $keyCredential.Type = $keyCredentialParams.Type $keyCredential.Usage = $keyCredentialParams.Usage $keyCredential.Key = $keyCredentialParams.Key # Update the application with the new key credential try { Update-MgApplication -ApplicationId $AppId -KeyCredentials @($keyCredential) Write-Host "Key credential added successfully to the application." } catch { Write-Host "An error occurred: $_" -ForegroundColor Red } } #EndRegion '.\Public\Add-KeyCredentialToApp.ps1' 60 #Region '.\Public\Connect-GraphWithCert.ps1' -1 function Connect-GraphWithCert { param ( [Parameter(Mandatory = $true)] [string]$tenantId, [Parameter(Mandatory = $true)] [string]$clientId, [Parameter(Mandatory = $true)] [string]$certPath, [Parameter(Mandatory = $true)] [string]$certPassword, [switch]$ConnectToIntune, [switch]$ConnectToTeams ) try { # Log the certificate path Log-Params -Params @{certPath = $certPath} # Load the certificate from the PFX file $cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($certPath, $certPassword) # Define the splat for Connect-MgGraph $GraphParams = @{ ClientId = $clientId TenantId = $tenantId Certificate = $cert } # Log the parameters Log-Params -Params $GraphParams # Obtain access token (if needed separately) $accessToken = Get-MsGraphAccessTokenCert -tenantId $tenantId -clientId $clientId -certPath $certPath -certPassword $certPassword Log-Params -Params @{accessToken = $accessToken} # Connect to Microsoft Graph Write-EnhancedLog -message 'Calling Connect-MgGraph with client certificate file path and password' -Level 'INFO' Connect-MgGraph @GraphParams -NoWelcome # Conditional check for Intune connection if ($ConnectToIntune) { try { # Define the parameters for non-interactive connection to Intune $IntuneGraphconnectionParams = @{ ClientId = $clientId TenantId = $tenantId ClientCert = $cert } # Log the connection attempt Write-EnhancedLog -Message "Calling Connect-MSIntuneGraph with connectionParams" -Level "WARNING" # Call the Connect-MSIntuneGraph function with splatted parameters $Session = Connect-MSIntuneGraph @IntuneGraphconnectionParams # Log the successful connection Write-EnhancedLog -Message "Connecting to Graph using Connect-MSIntuneGraph - done" -Level "INFO" } catch { Handle-Error -ErrorRecord $_ } } # Conditional check for Teams connection if ($ConnectToTeams) { try { Write-EnhancedLog -Message "Connecting to Microsoft Teams" -Level "INFO" # Connect to Microsoft Teams using the certificate Connect-MicrosoftTeams -TenantId $tenantId -Certificate $cert -ApplicationId $clientId Write-EnhancedLog -Message "Connected to Microsoft Teams" -Level "INFO" } catch { Handle-Error -ErrorRecord $_ } } return $accessToken } catch { Handle-Error -ErrorRecord $_ } } #Note for Teams Connection you must add RBAC role like Teams Admin to the app as well in additon to the API permissions as mentioned below # https://learn.microsoft.com/en-us/MicrosoftTeams/teams-powershell-application-authentication # Setup Application-based authentication # An initial onboarding is required for authentication using application objects. Application and service principal are used interchangeably, but an application is like a class object while a service principal is like an instance of the class. You can learn more about these objects at Application and service principal objects in Microsoft Entra ID. # Sample steps for creating applications in Microsoft Entra ID are mentioned below. For detailed steps, refer to this article. # 1- Register the application in Microsoft Entra ID. # 2- Assign API permissions to the application. # 2.1 For *-Cs cmdlets - the Microsoft Graph API permission needed is Organization.Read.All. # 2.2 For Non *-Cs cmdlets - the Microsoft Graph API permissions needed are Organization.Read.All, User.Read.All, Group.ReadWrite.All, AppCatalog.ReadWrite.All, TeamSettings.ReadWrite.All, Channel.Delete.All, ChannelSettings.ReadWrite.All, ChannelMember.ReadWrite.All. # 3. Generate a self-signed certificate. # 4. Attach the certificate to the Microsoft Entra application. # 5. Assign Microsoft Entra roles to the application. Refer to this Assign a role procedure, but search for the application instead of a user. # The application needs to have the appropriate RBAC roles assigned. Because the apps are provisioned in Microsoft Entra ID, you can use any of the supported built-in roles. #EndRegion '.\Public\Connect-GraphWithCert.ps1' 100 #Region '.\Public\Connect-ToIntuneInteractive.ps1' -1 # The following does not work any more due to # If you are using the Microsoft Intune PowerShell app registration in #Entra with applicationId d1ddf0e4-d672-4dae-b554-9d5bdfd93547, you will need to update your code before April 1, 2024 # https://oofhours.com/2024/03/29/using-a-well-known-intune-app-id-for-access-to-graph-not-for-much-longer/ function Connect-ToIntuneInteractive { param ( [Parameter(Mandatory = $true)] [string]$tenantId, [Parameter(Mandatory = $true)] [string]$clientId # Use your newly registered app's client ID ) try { # Log the start of the interactive login Write-EnhancedLog -Message "Starting interactive login for Intune with custom app registration..." -Level 'INFO' # Write-EnhancedLog -Message "Starting interactive login to Intune..." -Level 'INFO' # Define the scopes needed for Intune $scopes = "DeviceManagementApps.ReadWrite.All", "DeviceManagementManagedDevices.ReadWrite.All" # Connect interactively to Microsoft Graph (Intune) using the custom app registration Connect-MgGraph -ClientId $clientId -TenantId $tenantId -Scopes $scopes -NoWelcome # Conditional check for Intune connection # if ($ConnectToIntune) { # try { # Log the connection attempt # Write-EnhancedLog -Message "Calling Connect-MSIntuneGraph interactively" -Level "WARNING" # Call the Connect-MSIntuneGraph function interactively (no parameters needed for interactive login) # $Session = Connect-MSIntuneGraph -tenantId $tenantId # Log the successful connection Write-EnhancedLog -Message "Connecting to Graph using Connect-MSIntuneGraph interactively - done" -Level "INFO" # } catch { # Handle-Error -ErrorRecord $_ # } # } # Log a successful connection Write-EnhancedLog -Message "Successfully connected to Microsoft Intune interactively using custom app registration." -Level 'INFO' } catch { # Handle any errors during the interactive connection $errorMessage = "Failed to connect to Intune interactively. Reason: $($_.Exception.Message)" Write-EnhancedLog -Message $errorMessage -Level 'ERROR' throw $errorMessage } } #EndRegion '.\Public\Connect-ToIntuneInteractive.ps1' 53 #Region '.\Public\Connect-ToMicrosoftGraphIfServerCore.ps1' -1 function Connect-ToMicrosoftGraphIfServerCore { param ( [string[]]$Scopes ) if (Is-ServerCore) { Write-Output "Running on Windows Server Core. Using device authentication for Microsoft Graph." Connect-MgGraph -Scopes $Scopes -Verbose -UseDeviceAuthentication } else { Write-Output "Not running on Windows Server Core. Using default authentication for Microsoft Graph." Connect-MgGraph -Scopes $Scopes -Verbose } } #EndRegion '.\Public\Connect-ToMicrosoftGraphIfServerCore.ps1' 14 #Region '.\Public\Convert-EntraDeviceIdToIntuneDeviceId.ps1' -1 function Convert-EntraDeviceIdToIntuneDeviceId { param ( [Parameter(Mandatory = $true)] [string]$entraDeviceId, [hashtable]$headers ) Write-EnhancedLog -Message "Converting Entra Device ID: $entraDeviceId to Intune Device ID" -Level "INFO" -ForegroundColor ([ConsoleColor]::Cyan) try { # Construct the Graph API URL to retrieve device details $graphApiUrl = "https://graph.microsoft.com/v1.0/deviceManagement/managedDevices?`$filter=azureADDeviceId eq '$entraDeviceId'" Write-Output "Constructed Graph API URL: $graphApiUrl" # Send the request $response = Invoke-WebRequest -Uri $graphApiUrl -Headers $headers -Method Get $data = ($response.Content | ConvertFrom-Json).value if ($data -and $data.Count -gt 0) { $intuneDeviceId = $data[0].id Write-EnhancedLog -Message "Converted Entra Device ID: $entraDeviceId to Intune Device ID: $intuneDeviceId" -Level "INFO" -ForegroundColor ([ConsoleColor]::Green) return $intuneDeviceId } else { Write-EnhancedLog -Message "No Intune Device found for Entra Device ID: $entraDeviceId" -Level "WARN" -ForegroundColor ([ConsoleColor]::Yellow) return $null } } catch { Write-EnhancedLog -Message "Error converting Entra Device ID to Intune Device ID: $_" -Level "ERROR" -ForegroundColor ([ConsoleColor]::Red) return $null } } # # Example usage # $headers = @{ Authorization = "Bearer your-access-token" } # $entraDeviceId = "73e94a92-fc5a-45b6-bf6c-90ce8a353c44" # $intuneDeviceId = Convert-EntraDeviceIdToIntuneDeviceId -entraDeviceId $entraDeviceId -Headers $headers # Write-Output "Intune Device ID: $intuneDeviceId" #EndRegion '.\Public\Convert-EntraDeviceIdToIntuneDeviceId.ps1' 39 #Region '.\Public\Create-AndVerifyServicePrincipal.ps1' -1 function Create-AndVerifyServicePrincipal { param ( [Parameter(Mandatory = $true)] [string]$ClientId ) try { Write-EnhancedLog -Message "Creating a new service principal for the application with Client ID: $ClientId" -Level "INFO" # Create a new service principal for the application New-MgServicePrincipal -AppId $ClientId Write-EnhancedLog -Message "Service principal created successfully." -Level "INFO" # Verify the creation $servicePrincipal = Get-MgServicePrincipal -Filter "AppId eq '$ClientId'" if ($null -eq $servicePrincipal) { Write-EnhancedLog -Message "Service principal not found after creation." -Level "ERROR" throw "Service principal not found after creation" } Write-EnhancedLog -Message "Service principal verified successfully." -Level "INFO" # Display the service principal details $servicePrincipal | Format-Table DisplayName, AppId, Id return $servicePrincipal } catch { Write-EnhancedLog -Message "An error occurred while creating or verifying the service principal." -Level "ERROR" Handle-Error -ErrorRecord $_ throw $_ } } # Example usage # Create-AndVerifyServicePrincipal -ClientId "your-application-id" #EndRegion '.\Public\Create-AndVerifyServicePrincipal.ps1' 39 #Region '.\Public\Create-AppRegistration.ps1' -1 # function Create-AppRegistration { # param ( # [string]$AppName, # # [string]$PermsFile = "$PSScriptRoot\permissions.json" # [string]$PermsFile # ) # try { # if (-Not (Test-Path $PermsFile)) { # Write-EnhancedLog -Message "Permissions file not found: $PermsFile" -Level "ERROR" # throw "Permissions file missing" # } # $permissions = Get-Content -Path $PermsFile -Raw | ConvertFrom-Json # # Convert the JSON data to the required types # $requiredResourceAccess = @() # foreach ($perm in $permissions.permissions) { # $resourceAccess = @() # foreach ($access in $perm.ResourceAccess) { # $resourceAccess += [Microsoft.Graph.PowerShell.Models.IMicrosoftGraphResourceAccess]@{ # Id = [Guid]$access.Id # Type = $access.Type # } # } # $requiredResourceAccess += [Microsoft.Graph.PowerShell.Models.IMicrosoftGraphRequiredResourceAccess]@{ # ResourceAppId = [Guid]$perm.ResourceAppId # ResourceAccess = $resourceAccess # } # } # # Connect to Graph interactively # # Connect-MgGraph -Scopes "Application.ReadWrite.All" # # Get tenant details # $tenantDetails = Get-MgOrganization | Select-Object -First 1 # # Create the application # $app = New-MgApplication -DisplayName $AppName -SignInAudience "AzureADMyOrg" -RequiredResourceAccess $requiredResourceAccess # if ($null -eq $app) { # Write-EnhancedLog -Message "App registration failed" -Level "ERROR" # throw "App registration failed" # } # Write-EnhancedLog -Message "App registered successfully" -Level "INFO" # return @{ App = $app; TenantDetails = $tenantDetails } # } # catch { # Handle-Error -ErrorRecord $_ # } # } # function Create-AppRegistration { # param ( # [string]$AppName, # # Provide the path to the PSD1 file instead of JSON # [string]$PermsFile # ) # try { # if (-Not (Test-Path $PermsFile)) { # Write-EnhancedLog -Message "Permissions file not found: $PermsFile" -Level "ERROR" # throw "Permissions file missing" # } # # Load the PSD1 permissions file # $permissions = Import-PowerShellDataFile -Path $PermsFile # # Convert the PSD1 data to the required types # $requiredResourceAccess = @() # foreach ($perm in $permissions.permissions) { # $resourceAccess = @() # # Loop through both applicationPermissions and delegatedPermissions # foreach ($accessType in @('applicationPermissions', 'delegatedPermissions')) { # if ($perm.ContainsKey($accessType)) { # foreach ($access in $perm[$accessType]) { # $resourceAccess += [Microsoft.Graph.PowerShell.Models.IMicrosoftGraphResourceAccess]@{ # Id = [Guid]$access.id # Type = $access.type # } # } # } # } # $requiredResourceAccess += [Microsoft.Graph.PowerShell.Models.IMicrosoftGraphRequiredResourceAccess]@{ # ResourceAppId = [Guid]$perm.resourceAppId # ResourceAccess = $resourceAccess # } # } # # Connect to Graph interactively # # Connect-MgGraph -Scopes "Application.ReadWrite.All" # # Get tenant details # $tenantDetails = Get-MgOrganization | Select-Object -First 1 # # Create the application # $app = New-MgApplication -DisplayName $AppName -SignInAudience "AzureADMyOrg" -RequiredResourceAccess $requiredResourceAccess # if ($null -eq $app) { # Write-EnhancedLog -Message "App registration failed" -Level "ERROR" # throw "App registration failed" # } # Write-EnhancedLog -Message "App registered successfully" -Level "INFO" # return @{ App = $app; TenantDetails = $tenantDetails } # } # catch { # Handle-Error -ErrorRecord $_ # } # } # # Function to get the permission ID based on the name and type (either Role or Scope) # function Get-PermissionId { # param ( # [string]$permissionName, # [string]$permissionType # ) # if ($permissionType -eq 'Role') { # # Fetch App Role by value # $appRole = $graphServicePrincipal.appRoles | Where-Object { $_.value -eq $permissionName } # return $appRole.id # } elseif ($permissionType -eq 'Scope') { # # Fetch OAuth2 Scope by value # $oauthScope = $graphServicePrincipal.oauth2PermissionScopes | Where-Object { $_.value -eq $permissionName } # return $oauthScope.id # } else { # throw "Unknown permission type: $permissionType" # } # } # function Create-AppRegistration { # param ( # [string]$AppName, # # Provide the path to the PSD1 file instead of JSON # [string]$PermsFile # ) # try { # if (-Not (Test-Path $PermsFile)) { # Write-EnhancedLog -Message "Permissions file not found: $PermsFile" -Level "ERROR" # throw "Permissions file missing" # } # # Load the PSD1 permissions file # $permissions = Import-PowerShellDataFile -Path $PermsFile # # Fetch the Microsoft Graph Service Principal # $graphServicePrincipal = Get-MgServicePrincipal -Filter "displayName eq 'Microsoft Graph'" -Select id,appRoles,oauth2PermissionScopes # # Convert the PSD1 data to the required types # $requiredResourceAccess = @() # foreach ($perm in $permissions.permissions) { # $resourceAccess = @() # # Loop through both applicationPermissions and delegatedPermissions # foreach ($accessType in @('applicationPermissions', 'delegatedPermissions')) { # if ($perm.ContainsKey($accessType)) { # foreach ($access in $perm[$accessType]) { # $permissionId = Get-PermissionId -permissionName $access.name -permissionType $access.type # if (-not $permissionId) { # Write-EnhancedLog -Message "Permission ID not found for $($access.name)" -Level "ERROR" # throw "Permission ID missing for $($access.name)" # } # $resourceAccess += [Microsoft.Graph.PowerShell.Models.IMicrosoftGraphResourceAccess]@{ # Id = [Guid]$permissionId # Type = $access.type # } # } # } # } # $requiredResourceAccess += [Microsoft.Graph.PowerShell.Models.IMicrosoftGraphRequiredResourceAccess]@{ # ResourceAppId = [Guid]$perm.resourceAppId # ResourceAccess = $resourceAccess # } # } # # Connect to Graph interactively # # Connect-MgGraph -Scopes "Application.ReadWrite.All" # # Get tenant details # $tenantDetails = Get-MgOrganization | Select-Object -First 1 # # Create the application # $app = New-MgApplication -DisplayName $AppName -SignInAudience "AzureADMyOrg" -RequiredResourceAccess $requiredResourceAccess # if ($null -eq $app) { # Write-EnhancedLog -Message "App registration failed" -Level "ERROR" # throw "App registration failed" # } # Write-EnhancedLog -Message "App registered successfully" -Level "INFO" # return @{ App = $app; TenantDetails = $tenantDetails } # } # catch { # Handle-Error -ErrorRecord $_ # } # } # Function to get the permission ID based on the name and type (either Role or Scope) function Get-PermissionId { param ( [string]$permissionName, [string]$permissionType ) try { if ($permissionType -eq 'Role') { # Fetch App Role by value $appRole = $graphServicePrincipal.appRoles | Where-Object { $_.value -eq $permissionName } if ($null -eq $appRole) { Write-EnhancedLog -Message "Permission ID not found for $permissionName (Type: $permissionType)" -Level "ERROR" throw "Permission ID missing for $permissionName" } return $appRole.id } elseif ($permissionType -eq 'Scope') { # Fetch OAuth2 Scope by value $oauthScope = $graphServicePrincipal.oauth2PermissionScopes | Where-Object { $_.value -eq $permissionName } if ($null -eq $oauthScope) { Write-EnhancedLog -Message "Permission ID not found for $permissionName (Type: $permissionType)" -Level "ERROR" throw "Permission ID missing for $permissionName" } return $oauthScope.id } else { Write-EnhancedLog -Message "Unknown permission type: $permissionType for $permissionName" -Level "ERROR" throw "Unknown permission type: $permissionType" } } catch { Write-EnhancedLog -Message "Error while retrieving permission ID for $permissionName $_" -Level "ERROR" return $null } } function Create-AppRegistration { param ( [string]$AppName, # Provide the path to the PSD1 file instead of JSON [string]$PermsFile ) try { if (-Not (Test-Path $PermsFile)) { Write-EnhancedLog -Message "Permissions file not found: $PermsFile" -Level "ERROR" throw "Permissions file missing" } # Load the PSD1 permissions file $permissions = Import-PowerShellDataFile -Path $PermsFile # Fetch the Microsoft Graph Service Principal $graphServicePrincipal = Get-MgServicePrincipal -Filter "displayName eq 'Microsoft Graph'" -Select id,appRoles,oauth2PermissionScopes # Convert the PSD1 data to the required types $requiredResourceAccess = @() foreach ($perm in $permissions.permissions) { $resourceAccess = @() # Loop through both applicationPermissions and delegatedPermissions foreach ($accessType in @('applicationPermissions', 'delegatedPermissions')) { if ($perm.ContainsKey($accessType)) { foreach ($access in $perm[$accessType]) { $permissionId = Get-PermissionId -permissionName $access.name -permissionType $access.type if (-not $permissionId) { # Log and skip the permission if the ID is not found Write-EnhancedLog -Message "Skipping permission $($access.name) due to missing ID" -Level "WARNING" continue } $resourceAccess += [Microsoft.Graph.PowerShell.Models.IMicrosoftGraphResourceAccess]@{ Id = [Guid]$permissionId Type = $access.type } } } } if ($resourceAccess.Count -gt 0) { $requiredResourceAccess += [Microsoft.Graph.PowerShell.Models.IMicrosoftGraphRequiredResourceAccess]@{ ResourceAppId = [Guid]$perm.resourceAppId ResourceAccess = $resourceAccess } } else { Write-EnhancedLog -Message "No valid resource access found for $($perm.resourceAppId), skipping this entry" -Level "WARNING" } } # Ensure we have valid resource access before proceeding if ($requiredResourceAccess.Count -eq 0) { Write-EnhancedLog -Message "No valid permissions found in the PSD1 file, aborting app registration" -Level "ERROR" throw "No valid permissions found" } # Connect to Graph interactively if needed # Connect-MgGraph -Scopes "Application.ReadWrite.All" # Get tenant details $tenantDetails = Get-MgOrganization | Select-Object -First 1 # Create the application $app = New-MgApplication -DisplayName $AppName -SignInAudience "AzureADMyOrg" -RequiredResourceAccess $requiredResourceAccess if ($null -eq $app) { Write-EnhancedLog -Message "App registration failed" -Level "ERROR" throw "App registration failed" } Write-EnhancedLog -Message "App registered successfully" -Level "INFO" return @{ App = $app; TenantDetails = $tenantDetails } } catch { Write-EnhancedLog -Message "Error occurred during app registration: $_" -Level "ERROR" Handle-Error -ErrorRecord $_ } } #EndRegion '.\Public\Create-AppRegistration.ps1' 350 #Region '.\Public\Create-SelfSignedCert.ps1' -1 # function Create-SelfSignedCert { # param ( # [string]$CertName, # [string]$CertStoreLocation = "Cert:\CurrentUser\My", # [string]$TenantName, # [string]$AppId # ) # $cert = New-SelfSignedCertificate -CertStoreLocation $CertStoreLocation ` # -Subject "CN=$CertName, O=$TenantName, OU=$AppId" ` # -KeyLength 2048 ` # -NotAfter (Get-Date).AddDays(30) # if ($null -eq $cert) { # Write-EnhancedLog -Message "Failed to create certificate" -Level "ERROR" -ForegroundColor ([ConsoleColor]::Red) # throw "Certificate creation failed" # } # Write-EnhancedLog -Message "Certificate created successfully" -Level "INFO" -ForegroundColor ([ConsoleColor]::Cyan) # return $cert # } # function Create-SelfSignedCert { # param ( # [string]$CertName, # [string]$CertStoreLocation = "Cert:\CurrentUser\My", # [string]$TenantName, # [string]$AppId, # # [string]$OutputPath = "C:\Certificates", # [string]$OutputPath, # # [string]$PfxPassword = "YourPfxPassword" # [string]$PfxPassword # ) # try { # # Create output directory if it doesn't exist # if (-not (Test-Path -Path $OutputPath)) { # New-Item -ItemType Directory -Path $OutputPath # } # # Define certificate subject details # $subject = "CN=$CertName, O=$TenantName, OU=$AppId, L=City, S=State, C=US" # # Generate the self-signed certificate # $cert = New-SelfSignedCertificate -CertStoreLocation $CertStoreLocation ` # -Subject $subject ` # -KeyLength 2048 ` # -KeyExportPolicy Exportable ` # -NotAfter (Get-Date).AddDays(30) ` # -KeyUsage DigitalSignature, KeyEncipherment ` # -FriendlyName "$CertName for $TenantName" # if ($null -eq $cert) { # Write-EnhancedLog -Message "Failed to create certificate" -Level "ERROR" # throw "Certificate creation failed" # } # Write-EnhancedLog -Message "Certificate created successfully" -Level "INFO" # # Convert password to secure string # $securePfxPassword = ConvertTo-SecureString -String $PfxPassword -Force -AsPlainText # # Export the certificate to a PFX file # $pfxFilePath = Join-Path -Path $OutputPath -ChildPath "$CertName-$TenantName-$AppId.pfx" # Export-PfxCertificate -Cert $cert -FilePath $pfxFilePath -Password $securePfxPassword # Write-EnhancedLog -Message "PFX file created successfully at $pfxFilePath" -Level "INFO" # # Export the private key # $privateKeyFilePath = Join-Path -Path $OutputPath -ChildPath "$CertName-$TenantName-$AppId.key" # $privateKey = $cert.PrivateKey # $privateKeyBytes = [System.Convert]::ToBase64String($privateKey.ExportCspBlob($true)) # Set-Content -Path $privateKeyFilePath -Value $privateKeyBytes # Write-EnhancedLog -Message "Private key file created successfully at $privateKeyFilePath" -Level "INFO" # return $cert # } catch { # Write-EnhancedLog -Message "An error occurred while creating the self-signed certificate" -Level "ERROR" # Handle-Error -ErrorRecord $_ # throw $_ # } # } # Example usage # $cert = Create-SelfSignedCert -CertName "GraphCert" -TenantName "YourTenantName" -AppId "YourAppId" -OutputPath $OutputPath # function Create-SelfSignedCert { # param ( # [string]$CertName, # [string]$CertStoreLocation = "Cert:\CurrentUser\My", # [string]$TenantName, # [string]$AppId, # [string]$OutputPath, # [string]$PfxPassword # ) # try { # # Create output directory if it doesn't exist # if (-not (Test-Path -Path $OutputPath)) { # New-Item -ItemType Directory -Path $OutputPath -Force # } # # Get the logged-in user for the Graph API session # Write-EnhancedLog -Message "Fetching current user information from Microsoft Graph API." -Level "INFO" # $currentUserResponse = Invoke-MgGraphRequest -Uri "https://graph.microsoft.com/v1.0/me" -Method GET # Write-EnhancedLog -Message "Response from Microsoft Graph API: $($currentUserResponse | ConvertTo-Json -Compress)" -Level "DEBUG" # $currentUser = $currentUserResponse # # $DBG # # Define certificate subject details # $subject = "CN=$CertName-$AppId, O=$TenantName, OU=$AppId, L=City, S=State, C=US" # # Generate the self-signed certificate # $certParams = @{ # CertStoreLocation = $CertStoreLocation # Subject = $subject # Issuer = "CN=$($currentUser.DisplayName)-$($currentUser.userPrincipalName)" # KeyLength = 2048 # KeyExportPolicy = "Exportable" # NotAfter = (Get-Date).AddDays(30) # KeyUsage = "DigitalSignature, KeyEncipherment" # FriendlyName = "$CertName-$AppId for $TenantName" # } # # Generate the self-signed certificate # $cert = New-SelfSignedCertificate @certParams # $DBG # if ($null -eq $cert) { # Write-EnhancedLog -Message "Failed to create certificate" -Level "ERROR" # throw "Certificate creation failed" # } # Write-EnhancedLog -Message "Certificate created successfully" -Level "INFO" # # Convert password to secure string # $securePfxPassword = ConvertTo-SecureString -String $PfxPassword -Force -AsPlainText # # Export the certificate to a PFX file # # $pfxFilePath = Join-Path -Path "$OutputPath" -ChildPath "$CertName-$TenantName-$AppId.pfx" # $pfxFilePath = $null # # $pfxFilePath = Join-Path -Path "$OutputPath" -ChildPath "$CertName-$TenantName.pfx" # $pfxFilePath = Join-Path -Path "$OutputPath" -ChildPath "$CertName.pfx" # # $pfxFilePath = Join-Path -Path "$OutputPath" -ChildPath "1.pfx" # # $pfxFilePath = "C:\Code\GraphAppwithCert\Graph\Information and Communications Technology Council_b5dae566-ad8f-44e1-9929-5669f1dbb343\c.pfx" # # $DBG # Export-PfxCertificate -Cert $cert -FilePath "$pfxFilePath" -Password $securePfxPassword # Write-EnhancedLog -Message "Certificate $cert exported successfully to pfx file located in $pfxFilePath " -Level "INFO" # $DBG # Write-EnhancedLog -Message "PFX file created successfully at $pfxFilePath" -Level "INFO" # # Export the private key # # $privateKeyFilePath = Join-Path -Path "$OutputPath" -ChildPath "$CertName-$TenantName-$AppId.key" # $privateKeyFilePath = Join-Path -Path "$OutputPath" -ChildPath "$CertName-$TenantName.key" # $privateKey = $cert.PrivateKey # $rsaParameters = $privateKey.ExportParameters($true) # $privateKeyPem = Convert-RsaParametersToPem -rsaParameters $rsaParameters # Set-Content -Path $privateKeyFilePath -Value $privateKeyPem # Write-EnhancedLog -Message "Private key file created successfully at $privateKeyFilePath" -Level "INFO" # return $cert # } # catch { # Write-EnhancedLog -Message "An error occurred while creating the self-signed certificate" -Level "ERROR" # Handle-Error -ErrorRecord $_ # throw $_ # } # } # # Example usage # $certParams = @{ # CertName = "GraphCert" # TenantName = "YourTenantName" # AppId = "YourAppId" # OutputPath = "C:\Certificates" # PfxPassword = "YourPfxPassword" # } # $cert = Create-SelfSignedCert @certParams # function Create-SelfSignedCert { # param ( # [string]$CertName, # [string]$CertStoreLocation = "Cert:\CurrentUser\My", # [string]$TenantName, # [string]$AppId, # [string]$OutputPath, # [string]$PfxPassword # ) # try { # # Get the logged-in user for the Graph API session # Write-EnhancedLog -Message "Fetching current user information from Microsoft Graph API." -Level "INFO" # $currentUserResponse = Invoke-MgGraphRequest -Uri "https://graph.microsoft.com/v1.0/me" -Method GET # Write-EnhancedLog -Message "Response from Microsoft Graph API: $($currentUserResponse | ConvertTo-Json -Compress)" -Level "DEBUG" # $currentUser = $currentUserResponse # # Create output directory if it doesn't exist # if (-not (Test-Path -Path $OutputPath)) { # New-Item -ItemType Directory -Path $OutputPath # } # # Define certificate subject details # $subject = "CN=$CertName-$AppId, O=$TenantName, OU=$AppId, L=City, S=State, C=US" # # Splat the parameters # $certParams = @{ # CertStoreLocation = $CertStoreLocation # Subject = $subject # Issuer = "CN=$($currentUser.displayName)" # KeyLength = 2048 # KeyExportPolicy = "Exportable" # NotAfter = (Get-Date).AddDays(30) # KeyUsage = @("DigitalSignature", "KeyEncipherment") # FriendlyName = "$CertName-$AppId for $TenantName" # } # # Generate the self-signed certificate # $cert = New-SelfSignedCertificate @certParams # if ($null -eq $cert) { # Write-EnhancedLog -Message "Failed to create certificate" -Level "ERROR" # throw "Certificate creation failed" # } # Write-EnhancedLog -Message "Certificate created successfully" -Level "INFO" # # Convert password to secure string # $securePfxPassword = ConvertTo-SecureString -String $PfxPassword -Force -AsPlainText # # Export the certificate to a PFX file # $pfxFilePath = Join-Path -Path $OutputPath -ChildPath "$CertName-$TenantName-$AppId.pfx" # Export-PfxCertificate -Cert $cert -FilePath $pfxFilePath -Password $securePfxPassword # Write-EnhancedLog -Message "PFX file created successfully at $pfxFilePath" -Level "INFO" # return $cert # } catch { # Write-EnhancedLog -Message "An error occurred while creating the self-signed certificate." -Level "ERROR" # Handle-Error -ErrorRecord $_ # throw $_ # } # } # Example usage # $scopes = @("User.Read.All", "Application.ReadWrite.All", "Directory.ReadWrite.All") # Connect-MgGraph -Scopes $scopes # $certParams = @{ # CertName = "GraphCert" # TenantName = $tenantDetails.DisplayName # AppId = $app.AppId # OutputPath = $certexportDirectory # PfxPassword = $certPassword # } # $cert = Create-SelfSignedCert @certParams function Create-SelfSignedCert { param ( [string]$CertName, [string]$CertStoreLocation = "Cert:\CurrentUser\My", [string]$TenantName, [string]$AppId, [string]$OutputPath, [string]$PfxPassword ) try { # Get the logged-in user for the Graph API session Write-EnhancedLog -Message "Fetching current user information from Microsoft Graph API." -Level "INFO" $currentUserResponse = Invoke-MgGraphRequest -Uri "https://graph.microsoft.com/v1.0/me" -Method GET Write-EnhancedLog -Message "Response from Microsoft Graph API: $($currentUserResponse | ConvertTo-Json -Compress)" -Level "DEBUG" $currentUser = $currentUserResponse # Create output directory if it doesn't exist if (-not (Test-Path -Path $OutputPath)) { New-Item -ItemType Directory -Path $OutputPath } # Define certificate subject details $subject = "CN=$CertName-$AppId, O=$TenantName, OU=$AppId, L=City, S=State, C=US" $Issuer = "CN=$($currentUser.DisplayName)-$($currentUser.userPrincipalName)" # Splat the parameters $certParams = @{ CertStoreLocation = $CertStoreLocation Subject = $subject KeyLength = 2048 KeyExportPolicy = "Exportable" NotAfter = (Get-Date).AddDays(30) KeyUsage = @("DigitalSignature", "KeyEncipherment") FriendlyName = "$CertName-$AppId for $TenantName by $Issuer" } # Generate the self-signed certificate $cert = New-SelfSignedCertificate @certParams if ($null -eq $cert) { Write-EnhancedLog -Message "Failed to create certificate" -Level "ERROR" throw "Certificate creation failed" } Write-EnhancedLog -Message "Certificate created successfully" -Level "INFO" # Convert password to secure string $securePfxPassword = ConvertTo-SecureString -String $PfxPassword -Force -AsPlainText # Export the certificate to a PFX file $pfxFilePath = Join-Path -Path $OutputPath -ChildPath "$CertName-$AppId.pfx" Export-PfxCertificate -Cert $cert -FilePath $pfxFilePath -Password $securePfxPassword Write-EnhancedLog -Message "PFX file created successfully at $pfxFilePath" -Level "INFO" # $DBG return $cert } catch { Write-EnhancedLog -Message "An error occurred while creating the self-signed certificate." -Level "ERROR" Handle-Error -ErrorRecord $_ throw $_ } } # # Example usage # $scopes = @("User.Read.All", "Application.ReadWrite.All", "Directory.ReadWrite.All") # Connect-MgGraph -Scopes $scopes # $certParams = @{ # CertName = "GraphCert" # TenantName = $tenantDetails.DisplayName # AppId = $app.AppId # OutputPath = $certexportDirectory # PfxPassword = $certPassword # } # $cert = Create-SelfSignedCert @certParams #EndRegion '.\Public\Create-SelfSignedCert.ps1' 395 #Region '.\Public\Create-SelfSignedCertOpenSSL.ps1' -1 # We'll create the following functions: # Get-CurrentUser # Generate-Certificate # Convert-CertificateToPfx # Import-PfxCertificateToStore # Create-SelfSignedCertOpenSSL function Get-CurrentUser { try { Write-EnhancedLog -Message "Fetching current user information from Microsoft Graph API." -Level "INFO" $currentUserResponse = Invoke-MgGraphRequest -Uri "https://graph.microsoft.com/v1.0/me" -Method GET Write-EnhancedLog -Message "Response from Microsoft Graph API: $($currentUserResponse | ConvertTo-Json -Compress)" -Level "DEBUG" return $currentUserResponse } catch { Write-EnhancedLog -Message "An error occurred while fetching the current user information." -Level "ERROR" Handle-Error -ErrorRecord $_ throw $_ } } function Convert-CertificateToPfx { param ( [string]$CertKeyPath, [string]$CertCrtPath, [string]$PfxPath, [string]$PfxPassword ) try { $opensslPfxCmd = "openssl pkcs12 -export -out `"$PfxPath`" -inkey `"$CertKeyPath`" -in `"$CertCrtPath`" -passout pass:$PfxPassword" Write-EnhancedLog -Message "Running OpenSSL command to convert certificate to PFX format: $opensslPfxCmd" -Level "INFO" $processInfo = New-Object System.Diagnostics.ProcessStartInfo $processInfo.FileName = "/bin/bash" $processInfo.Arguments = "-c `"$opensslPfxCmd`"" $processInfo.RedirectStandardOutput = $true $processInfo.RedirectStandardError = $true $processInfo.UseShellExecute = $false $processInfo.CreateNoWindow = $true $process = New-Object System.Diagnostics.Process $process.StartInfo = $processInfo $process.Start() | Out-Null $stdout = $process.StandardOutput.ReadToEnd() $stderr = $process.StandardError.ReadToEnd() $process.WaitForExit() Write-EnhancedLog -Message "Standard Output: $stdout" -Level "DEBUG" Write-EnhancedLog -Message "Standard Error: $stderr" -Level "DEBUG" if ($process.ExitCode -ne 0) { Write-EnhancedLog -Message "OpenSSL PFX command failed with exit code $($process.ExitCode)" -Level "ERROR" throw "PFX file creation failed" } Write-EnhancedLog -Message "PFX file created successfully at $PfxPath" -Level "INFO" } catch { Write-EnhancedLog -Message "An error occurred while converting the certificate to PFX format." -Level "ERROR" Handle-Error -ErrorRecord $_ throw $_ } } function Import-PfxCertificateToStore { param ( [string]$PfxPath, [string]$PfxPassword, [string]$CertStoreLocation ) try { $securePfxPassword = ConvertTo-SecureString -String $PfxPassword -Force -AsPlainText $cert = Import-PfxCertificate -FilePath $PfxPath -Password $securePfxPassword -CertStoreLocation $CertStoreLocation Write-EnhancedLog -Message "Certificate imported successfully into store location $CertStoreLocation" -Level "INFO" return $cert } catch { Write-EnhancedLog -Message "An error occurred while importing the PFX certificate to the store." -Level "ERROR" Handle-Error -ErrorRecord $_ throw $_ } } function Create-DummyCertWithOpenSSL { param ( # [string]$OutputDir = "/workspaces/cert" [string]$OutputDir ) try { # Ensure the output directory exists if (-not (Test-Path -Path $OutputDir)) { New-Item -ItemType Directory -Path $OutputDir -Force | Out-Null Write-EnhancedLog -Message "Created output directory: $OutputDir" -Level "INFO" } else { Write-EnhancedLog -Message "Output directory already exists: $OutputDir" -Level "INFO" } # Define a simple command to run OpenSSL $opensslCmd = "openssl req -x509 -nodes -days 1 -newkey rsa:2048 -keyout $OutputDir/dummy.key -out $OutputDir/dummy.crt -subj '/CN=DummyCert/O=DummyOrg/C=US'" Write-EnhancedLog -Message "Running OpenSSL command: $opensslCmd" -Level "INFO" # Use Start-Process to execute the command $startInfo = New-Object System.Diagnostics.ProcessStartInfo $startInfo.FileName = "/bin/bash" $startInfo.Arguments = "-c `"$opensslCmd`"" $startInfo.RedirectStandardOutput = $true $startInfo.RedirectStandardError = $true $startInfo.UseShellExecute = $false $startInfo.CreateNoWindow = $true $process = New-Object System.Diagnostics.Process $process.StartInfo = $startInfo $process.Start() | Out-Null # Capture the output $stdout = $process.StandardOutput.ReadToEnd() $stderr = $process.StandardError.ReadToEnd() $process.WaitForExit() # Output the results Write-EnhancedLog -Message "Standard Output: $stdout" -Level "INFO" Write-EnhancedLog -Message "Standard Error: $stderr" -Level "INFO" if ($process.ExitCode -ne 0) { Write-EnhancedLog -Message "OpenSSL command failed with exit code $($process.ExitCode)" -Level "ERROR" throw "Certificate creation failed" } else { Write-EnhancedLog -Message "Certificate created successfully using OpenSSL" -Level "INFO" } } catch { Write-EnhancedLog -Message "An error occurred while generating the certificate." -Level "ERROR" Handle-Error -ErrorRecord $_ throw $_ } } # # Test the function # Create-DummyCertWithOpenSSL # $DBG function Create-SelfSignedCertOpenSSL { param ( [string]$CertName, [string]$CertStoreLocation = "Cert:\CurrentUser\My", [string]$TenantName, [string]$AppId, [string]$OutputPath, [string]$PfxPassword ) try { $currentUser = Get-CurrentUser # Create output directory if it doesn't exist if (-not (Test-Path -Path $OutputPath)) { New-Item -ItemType Directory -Path $OutputPath -Force | Out-Null } Write-EnhancedLog -Message "calling Run-GenerateCertificateScript" -Level "INFO" $DBG # $certPaths = Run-GenerateCertificateScript -CertName $CertName -TenantName $TenantName -AppId $AppId -OutputPath $OutputPath -CurrentUser $currentUser -RealCertName $CertName -RealTenantName $TenantName -RealAppId $AppId Create-DummyCertWithOpenSSL -OutputDir $OutputPath Write-EnhancedLog -Message "Done calling Run-GenerateCertificateScript" -Level "INFO" $DBG $pfxFilePath = Join-Path -Path $OutputPath -ChildPath "$CertName-$AppId.pfx" Convert-CertificateToPfx -CertKeyPath $certPaths.KeyPath -CertCrtPath $certPaths.CrtPath -PfxPath $pfxFilePath -PfxPassword $PfxPassword if ($PSVersionTable.OS -match "Windows") { try { $securePfxPassword = ConvertTo-SecureString -String $PfxPassword -Force -AsPlainText $cert = Import-PfxCertificateToStore -FilePath $pfxFilePath -Password $securePfxPassword -CertStoreLocation $CertStoreLocation Write-EnhancedLog -Message "Certificate imported successfully into store location $CertStoreLocation" -Level "INFO" } catch { Write-EnhancedLog -Message "An error occurred while importing the PFX certificate to the store." -Level "ERROR" Handle-Error -ErrorRecord $_ throw $_ } } else { Write-EnhancedLog -Message "Running on a non-Windows OS, skipping the import of the PFX certificate to the store." -Level "INFO" $cert = $null } return $cert } catch { Write-EnhancedLog -Message "An error occurred while creating the self-signed certificate." -Level "ERROR" Handle-Error -ErrorRecord $_ throw $_ } } #EndRegion '.\Public\Create-SelfSignedCertOpenSSL.ps1' 208 #Region '.\Public\ExportCertificatetoCER.ps1' -1 # # Define the function # function ExportCertificatetoCER { # param ( # [Parameter(Mandatory = $true)] # [string]$CertThumbprint, # [Parameter(Mandatory = $true)] # [string]$ExportDirectory # ) # try { # # Get the certificate from the current user's personal store # $cert = Get-Item -Path "Cert:\CurrentUser\My\$CertThumbprint" # # Ensure the export directory exists # if (-not (Test-Path -Path $ExportDirectory)) { # New-Item -ItemType Directory -Path $ExportDirectory -Force # } # # Dynamically create a file name using the certificate subject name and current timestamp # $timestamp = (Get-Date).ToString("yyyyMMddHHmmss") # $subjectName = $cert.SubjectName.Name -replace "[^a-zA-Z0-9]", "_" # $fileName = "${subjectName}_$timestamp" # # Set the export file path # $certPath = Join-Path -Path $ExportDirectory -ChildPath "$fileName.cer" # # Export the certificate to a file (DER encoded binary format with .cer extension) # $cert | Export-Certificate -FilePath $certPath -Type CERT -Force | Out-Null # # Output the export file path # Write-EnhancedLog -Message "Certificate exported to: $certPath" # # Return the export file path # return $certPath # } # catch { # Write-Host "Failed to export certificate: $_" -ForegroundColor Red # } # } function ExportCertificatetoCER { param ( [Parameter(Mandatory = $true)] [string]$CertThumbprint, [Parameter(Mandatory = $true)] [string]$ExportDirectory, [Parameter(Mandatory = $true)] [string]$Certname ) try { Write-EnhancedLog -Message "Starting certificate export process for thumbprint: $CertThumbprint" -Level "INFO" # Get the certificate from the current user's personal store $cert = Get-Item -Path "Cert:\CurrentUser\My\$CertThumbprint" if (-not $cert) { Write-EnhancedLog -Message "Certificate with thumbprint $CertThumbprint not found." -Level "ERROR" throw "Certificate with thumbprint $CertThumbprint not found." } Write-EnhancedLog -Message "Certificate with thumbprint $CertThumbprint found." -Level "INFO" # Ensure the export directory exists if (-not (Test-Path -Path $ExportDirectory)) { Write-EnhancedLog -Message "Export directory $ExportDirectory does not exist. Creating directory." -Level "INFO" New-Item -ItemType Directory -Path $ExportDirectory -Force } Write-EnhancedLog -Message "Using export directory: $ExportDirectory" -Level "INFO" # Dynamically create a file name using the certificate subject name and current timestamp $timestamp = (Get-Date).ToString("yyyyMMddHHmmss") # $subjectName = $cert.SubjectName.Name -replace "[^a-zA-Z0-9]", "_" # $fileName = "${subjectName}_$timestamp" $fileName = "${certname}_$timestamp" # Set the export file path $certPath = Join-Path -Path $ExportDirectory -ChildPath "$fileName.cer" Write-EnhancedLog -Message "Export file path set to: $certPath" -Level "INFO" # Export the certificate to a file (DER encoded binary format with .cer extension) # $DBG Export-Certificate -Cert $cert -FilePath $certPath -Type CERT -Force | Out-Null Write-EnhancedLog -Message "Certificate successfully exported to: $certPath" -Level "INFO" # Return the export file path return $certPath } catch { $errorMessage = $_.Exception.Message Write-EnhancedLog -Message "Failed to export certificate: $errorMessage" -Level "ERROR" Handle-Error -ErrorRecord $_ throw $_ } } #EndRegion '.\Public\ExportCertificatetoCER.ps1' 103 #Region '.\Public\Get-AppInfoFromJson.ps1' -1 function Get-AppInfoFromJson { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$jsonPath ) Begin { Write-EnhancedLog -Message "Starting Get-AppInfoFromJson function" -Level "INFO" Log-Params -Params @{ jsonPath = $jsonPath } } Process { try { # Check if the file exists if (-Not (Test-Path -Path $jsonPath)) { Write-Error "The file at path '$jsonPath' does not exist." return } # Read the JSON content from the file Write-EnhancedLog -Message "Reading JSON content from file: $jsonPath" -Level "INFO" $jsonContent = Get-Content -Path $jsonPath -Raw # Check if the JSON content is empty if (-Not $jsonContent) { Write-EnhancedLog -Message "The JSON content is empty." -Level "ERROR" return } # Convert the JSON content to a PowerShell object Write-EnhancedLog -Message "Converting JSON content to PowerShell object" -Level "INFO" $appData = ConvertFrom-Json -InputObject $jsonContent # Check if the appData is empty or null if (-Not $appData) { Write-EnhancedLog -Message "The JSON content did not contain any data." -Level "ERROR" return } # Extract the required information Write-EnhancedLog -Message "Extracting required information from JSON data" -Level "INFO" $extractedData = $appData | ForEach-Object { [PSCustomObject]@{ Id = $_.Id DisplayName = $_.DisplayName AppId = $_.AppId SignInAudience = $_.SignInAudience PublisherDomain = $_.PublisherDomain } } # Return the extracted data return $extractedData } catch { Write-EnhancedLog -Message "An error occurred while processing the JSON content: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ } } End { Write-EnhancedLog -Message "Exiting Get-AppInfoFromJson function" -Level "INFO" } } #EndRegion '.\Public\Get-AppInfoFromJson.ps1' 65 #Region '.\Public\Get-AppName.ps1' -1 # Function to read the application name from app.json and append a timestamp function Get-AppName { param ( [string]$AppJsonFile ) if (-Not (Test-Path $AppJsonFile)) { Write-EnhancedLog -Message "App JSON file not found: $AppJsonFile" -Level "ERROR" -ForegroundColor ([ConsoleColor]::Red) throw "App JSON file missing" } $appConfig = Get-Content -Path $AppJsonFile | ConvertFrom-Json $baseAppName = $appConfig.AppName $timestamp = (Get-Date).ToString("yyyyMMddHHmmss") $uniqueAppName = "$baseAppName-$timestamp" Write-EnhancedLog -Message "Generated unique app name: $uniqueAppName" -Level "INFO" -ForegroundColor ([ConsoleColor]::Cyan) return $uniqueAppName } #EndRegion '.\Public\Get-AppName.ps1' 20 #Region '.\Public\Get-FriendlyNamesForPermissions.ps1' -1 #need to the test the following first function Get-FriendlyNamesForPermissions { param ( [string]$tenantId, [string]$clientId, [string]$clientSecret, [string]$permissionsFile ) # Function to get access token function Get-MsGraphAccessToken { param ( [string]$tenantId, [string]$clientId, [string]$clientSecret ) $body = @{ grant_type = "client_credentials" client_id = $clientId client_secret = $clientSecret scope = "https://graph.microsoft.com/.default" } $response = Invoke-RestMethod -Method Post -Uri "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token" -ContentType "application/x-www-form-urlencoded" -Body $body return $response.access_token } # Load permissions from the JSON file if (Test-Path -Path $permissionsFile) { $permissions = Get-Content -Path $permissionsFile | ConvertFrom-Json } else { Write-Error "Permissions file not found: $permissionsFile" throw "Permissions file not found: $permissionsFile" } # Get access token $accessToken = Get-MsGraphAccessToken -tenantId $tenantId -clientId $clientId -clientSecret $clientSecret # Create header for Graph API requests $headers = @{ Authorization = "Bearer $accessToken" } # Translate IDs to friendly names foreach ($permission in $permissions) { $id = $permission.Id $url = "https://graph.microsoft.com/v1.0/servicePrincipals?$filter=appRoles/id eq '$id' or oauth2PermissionScopes/id eq '$id'&$select=displayName" $response = Invoke-RestMethod -Method Get -Uri $url -Headers $headers $friendlyName = $response.value[0].displayName $permission | Add-Member -MemberType NoteProperty -Name FriendlyName -Value $friendlyName } return $permissions } # # Example usage # $tenantId = "your-tenant-id" # $clientId = "your-client-id" # $clientSecret = "your-client-secret" # $permissionsFilePath = Join-Path -Path $PSScriptRoot -ChildPath "permissions.json" # $friendlyPermissions = Get-FriendlyNamesForPermissions -tenantId $tenantId -clientId $clientId -clientSecret $clientSecret -permissionsFile $permissionsFilePath # $friendlyPermissions | Format-Table -AutoSize #EndRegion '.\Public\Get-FriendlyNamesForPermissions.ps1' 67 #Region '.\Public\Get-MsGraphAccessToken.ps1' -1 function Get-MsGraphAccessToken { param ( [string]$tenantId, [string]$clientId, [string]$clientSecret ) $tokenEndpoint = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token" $body = @{ client_id = $clientId scope = "https://graph.microsoft.com/.default" client_secret = $clientSecret grant_type = "client_credentials" } $httpClient = New-Object System.Net.Http.HttpClient $bodyString = ($body.GetEnumerator() | ForEach-Object { "$($_.Key)=$($_.Value)" }) -join '&' try { $content = New-Object System.Net.Http.StringContent($bodyString, [System.Text.Encoding]::UTF8, "application/x-www-form-urlencoded") $response = $httpClient.PostAsync($tokenEndpoint, $content).Result if (-not $response.IsSuccessStatusCode) { Write-EnhancedLog -Message "HTTP request failed with status code: $($response.StatusCode)" -Level "ERROR" return $null } $responseContent = $response.Content.ReadAsStringAsync().Result $accessToken = (ConvertFrom-Json $responseContent).access_token if ($accessToken) { Write-EnhancedLog -Message "Access token retrieved successfully" -Level "INFO" return $accessToken } else { Write-EnhancedLog -Message "Failed to retrieve access token, response was successful but no token was found." -Level "ERROR" return $null } } catch { Write-EnhancedLog -Message "Failed to execute HTTP request or process results: $_" -Level "ERROR" return $null } } #EndRegion '.\Public\Get-MsGraphAccessToken.ps1' 45 #Region '.\Public\Get-MsGraphAccessTokenCert.ps1' -1 function Get-MsGraphAccessTokenCert { param ( [Parameter(Mandatory = $true)] [string]$tenantId, [Parameter(Mandatory = $true)] [string]$clientId, [Parameter(Mandatory = $true)] [string]$certPath, [Parameter(Mandatory = $true)] [string]$certPassword ) $tokenEndpoint = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token" # Load the certificate $cert = Load-Certificate -certPath $certPath -certPassword $certPassword # Create JWT header $jwtHeader = @{ alg = "RS256" typ = "JWT" x5t = [Convert]::ToBase64String($cert.GetCertHash()) } $now = [System.DateTime]::UtcNow Write-EnhancedLog -Message "Current UTC Time: $now" # Get nbf and exp times $nbfTime = Get-UnixTime -offsetMinutes -5 # nbf is 5 minutes ago $expTime = Get-UnixTime -offsetMinutes 55 # exp is 55 minutes from now Write-EnhancedLog -Message "nbf (not before) time: $nbfTime" Write-EnhancedLog -Message "exp (expiration) time: $expTime" # Create JWT payload $jwtPayload = @{ aud = $tokenEndpoint exp = $expTime iss = $clientId jti = [guid]::NewGuid().ToString() nbf = $nbfTime sub = $clientId } Write-EnhancedLog -Message "JWT Payload: $(ConvertTo-Json $jwtPayload -Compress)" # Generate JWT assertion $clientAssertion = Generate-JWTAssertion -jwtHeader $jwtHeader -jwtPayload $jwtPayload -cert $cert # Send token request return Send-TokenRequest -tokenEndpoint $tokenEndpoint -clientId $clientId -clientAssertion $clientAssertion } # # Example usage of Get-MsGraphAccessTokenCert # $tenantId = "b5dae566-ad8f-44e1-9929-5669f1dbb343" # $clientId = "8230c33e-ff30-419c-a1fc-4caf98f069c9" # $certPath = "C:\Code\appgallery\Intune-Win32-Deployer\apps-winget-repo\PR4B_ExportVPNtoSPO-v1\PR4B-ExportVPNtoSPO-v2\graphcert.pfx" # $certPassword = "somepassword" # $accessToken = Get-MsGraphAccessTokenCert -tenantId $tenantId -clientId $clientId -certPath $certPath -certPassword $certPassword # Write-Host "Access Token: $accessToken" #EndRegion '.\Public\Get-MsGraphAccessTokenCert.ps1' 62 #Region '.\Public\Get-Secrets.ps1' -1 function Get-Secrets { <# .SYNOPSIS Loads secrets from a JSON file. .DESCRIPTION This function reads a JSON file containing secrets and returns an object with these secrets. .PARAMETER SecretsPath The path to the JSON file containing secrets. If not provided, the default is "secrets.json" in the same directory as the script. .EXAMPLE $secrets = Get-Secrets -SecretsPath "C:\Path\To\secrets.json" This example loads secrets from the specified JSON file. .NOTES If the SecretsPath parameter is not provided, the function assumes the JSON file is named "secrets.json" and is located in the same directory as the script. #> [CmdletBinding()] param ( [Parameter(Mandatory = $false)] # [string]$SecretsPath = (Join-Path -Path $PSScriptRoot -ChildPath "secrets.json") [string]$SecretsPath ) try { Write-EnhancedLog -Message "Attempting to load secrets from path: $SecretsPath" -Level "INFO" -ForegroundColor ([ConsoleColor]::Cyan) # Check if the secrets file exists if (-not (Test-Path -Path $SecretsPath)) { Write-EnhancedLog -Message "Secrets file not found at path: $SecretsPath" -Level "ERROR" -ForegroundColor ([ConsoleColor]::Red) throw "Secrets file not found at path: $SecretsPath" } # Load and parse the secrets file $secrets = Get-Content -Path $SecretsPath -Raw | ConvertFrom-Json Write-EnhancedLog -Message "Successfully loaded secrets from path: $SecretsPath" -Level "INFO" -ForegroundColor ([ConsoleColor]::Green) return $secrets } catch { Write-EnhancedLog -Message "Error loading secrets from path: $SecretsPath. Error: $_" -Level "ERROR" -ForegroundColor ([ConsoleColor]::Red) throw $_ } } #EndRegion '.\Public\Get-Secrets.ps1' 47 #Region '.\Public\Get-SignInLogs.ps1' -1 function Get-SignInLogs { param ( [string]$url, [hashtable]$headers ) $allLogs = @() while ($url) { try { Write-EnhancedLog -Message "Requesting URL: $url" -Level "INFO" -ForegroundColor ([ConsoleColor]::Cyan) # Make the API request $response = Invoke-WebRequest -Uri $url -Headers $headers -Method Get $data = ($response.Content | ConvertFrom-Json) # Collect the logs $allLogs += $data.value # Check for pagination $url = $data.'@odata.nextLink' } catch { Write-EnhancedLog -Message "Error: $($_.Exception.Message)" -Level "ERROR" -ForegroundColor ([ConsoleColor]::Red) break } } return $allLogs } #EndRegion '.\Public\Get-SignInLogs.ps1' 29 #Region '.\Public\Get-TenantDetails.ps1' -1 function Get-TenantDetails { try { # Retrieve the organization details $organization = Get-MgOrganization # Extract the required details $tenantName = $organization.DisplayName $tenantId = $organization.Id # Initialize tenantDomain $tenantDomain = $null # Search for a verified domain matching the onmicrosoft.com pattern foreach ($domain in $organization.VerifiedDomains) { if ($domain.Name -match '\.onmicrosoft\.com$') { $tenantDomain = $domain.Name break } } # Adjust the tenant domain if necessary if ($tenantDomain -match '\.mail\.onmicrosoft\.com$') { $tenantDomain = $tenantDomain -replace '\.mail\.onmicrosoft\.com$', '.onmicrosoft.com' } if ($null -eq $tenantDomain) { throw "No onmicrosoft.com domain found." } # Output tenant summary Write-EnhancedLog -Message "Tenant Name: $tenantName" -Level "INFO" Write-EnhancedLog -Message "Tenant ID: $tenantId" -Level "INFO" Write-EnhancedLog -Message "Tenant Domain: $tenantDomain" -Level "INFO" # Return the extracted details return @{ TenantName = $tenantName TenantId = $tenantId TenantDomain = $tenantDomain } } catch { Handle-Error -ErrorRecord $_ Write-EnhancedLog -Message "Failed to retrieve tenant details" -Level "ERROR" return $null } } # # Example usage # $tenantDetails = Get-TenantDetails # if ($null -ne $tenantDetails) { # $tenantName = $tenantDetails.TenantName # $tenantId = $tenantDetails.TenantId # $tenantDomain = $tenantDetails.TenantDomain # # Use the tenant details as needed # Write-EnhancedLog -Message "Using Tenant Details outside the function" -Level "INFO" # Write-EnhancedLog -Message "Tenant Name: $tenantName" -Level "INFO" # Write-EnhancedLog -Message "Tenant ID: $tenantId" -Level "INFO" # Write-EnhancedLog -Message "Tenant Domain: $tenantDomain" -Level "INFO" # } else { # Write-EnhancedLog -Message "Tenant details could not be retrieved." -Level "ERROR" # } #EndRegion '.\Public\Get-TenantDetails.ps1' 65 #Region '.\Public\Grant-AdminConsentToAllPermissions.ps1' -1 # using namespace System.Collections.Generic # function Grant-AdminConsentToAllPermissions { # param( # [string]$AppDisplayName # ) # $App = Get-MgApplication -Filter "DisplayName eq '$AppDisplayName'" # $sp = Get-MgServicePrincipal -Filter "AppId eq '$($App.AppId)'" # # $DBG # foreach ($resourceAccess in $App.RequiredResourceAccess) { # $resourceSp = Get-MgServicePrincipal -Filter "AppId eq '$($resourceAccess.ResourceAppId)'" # if (!$resourceSp) { # throw "Please cleanup permissions in the Azure portal for the app '$App.AppId', it contains permissions for removed App." # } # $scopesIdToValue = @{} # $resourceSp.PublishedPermissionScopes | ForEach-Object { $scopesIdToValue[$_.Id] = $_.Value } # [HashSet[string]]$requiredScopes = $resourceAccess.ResourceAccess | ForEach-Object { $scopesIdToValue[$_.Id] } # $grant = Get-MgOauth2PermissionGrant -Filter "ClientId eq '$($sp.Id)' and ResourceId eq '$($resourceSp.Id)'" # $newGrantRequired = $true # if ($grant) { # [HashSet[string]]$grantedScopes = $grant.Scope.Split(" ") # if (!$requiredScopes.IsSubsetOf($grantedScopes)) { # Write-Host "Revoking grant for '$($resourceSp.DisplayName)'" # Remove-MgOauth2PermissionGrant -OAuth2PermissionGrantId $grant.Id # } # else { # $newGrantRequired = $false # } # } # if ($newGrantRequired) { # $consentExpiry = ([datetime]::Now.AddYears(10)) # $scopesToGrant = $requiredScopes -join " " # Write-Host "Issuing grant for '$($resourceSp.DisplayName)', scope = $scopesToGrant" # New-MgOauth2PermissionGrant -ClientId $sp.Id -ConsentType "AllPrincipals" ` # -ResourceId $resourceSp.Id -Scope $scopesToGrant ` # -ExpiryTime $consentExpiry | Out-Null # } # } # } # # Grant-AdminConsentToAllPermissions -AppDisplayName 'GraphApp-Test001-20240618142134' #EndRegion '.\Public\Grant-AdminConsentToAllPermissions.ps1' 47 #Region '.\Public\Grant-AdminConsentToApiPermissions.ps1' -1 # function Grant-AdminConsentToApiPermissions { # param ( # [Parameter(Mandatory = $true)] # [string]$clientId, # [Parameter(Mandatory = $true)] # [string]$SPPermissionsPath # ) # try { # Write-EnhancedLog -Message "Starting the process to grant admin consent to API permissions for App ID: $clientId" -Level "INFO" # # Load permissions from JSON file # $permissionsFile = Join-Path -Path $SPPermissionsPath -ChildPath "SPPermissions.json" # if (-not (Test-Path -Path $permissionsFile)) { # Write-EnhancedLog -Message "Permissions file not found: $permissionsFile" -Level "ERROR" # throw "Permissions file not found" # } # $permissionsJson = Get-Content -Path $permissionsFile -Raw | ConvertFrom-Json # $permissions = $permissionsJson.permissions | Where-Object { $_.granted -eq $true } | Select-Object -ExpandProperty name # Write-EnhancedLog -Message "Permissions to be granted: $($permissions -join ', ')" -Level "INFO" # # Create and verify the service principal # Create-AndVerifyServicePrincipal -ClientId $clientId # Write-EnhancedLog -Message "Granting admin consent to API permissions for App ID: $clientId" -Level "INFO" # # Retrieve the service principal for the application # $servicePrincipal = Get-MgServicePrincipal -Filter "AppId eq '$clientId'" # if ($null -eq $servicePrincipal) { # Write-EnhancedLog -Message "Service principal not found for the specified application ID." -Level "ERROR" # throw "Service principal not found" # } # Write-EnhancedLog -Message "Service principal for app ID: $clientId retrieved successfully." -Level "INFO" # # Retrieve the service principal ID # $servicePrincipalId = $servicePrincipal.Id # # Retrieve the Microsoft Graph service principal # $graphServicePrincipal = Get-MgServicePrincipal -Filter "displayName eq 'Microsoft Graph'" -Select id,appRoles # if ($null -eq $graphServicePrincipal) { # Write-EnhancedLog -Message "Microsoft Graph service principal not found." -Level "ERROR" # throw "Microsoft Graph service principal not found" # } # $resourceId = $graphServicePrincipal.Id # $appRoles = $graphServicePrincipal.AppRoles # # Find the IDs of the required permissions # $requiredRoles = $appRoles | Where-Object { $permissions -contains $_.Value } | Select-Object Id, Value # if ($requiredRoles.Count -eq 0) { # Write-EnhancedLog -Message "No matching app roles found for the specified permissions." -Level "ERROR" # throw "No matching app roles found" # } # Write-EnhancedLog -Message "App roles to be granted: $($requiredRoles.Value -join ', ')" -Level "INFO" # # Grant the app roles (application permissions) # foreach ($role in $requiredRoles) { # $body = @{ # principalId = $servicePrincipalId # resourceId = $resourceId # appRoleId = $role.Id # } # $response = Invoke-MgGraphRequest -Uri "https://graph.microsoft.com/v1.0/servicePrincipals/$resourceId/appRoleAssignedTo" -Method POST -Body ($body | ConvertTo-Json) -ContentType "application/json" # Write-EnhancedLog -Message "Granted app role: $($role.Value) with ID: $($role.Id)" -Level "INFO" # } # # $DBG # Write-EnhancedLog -Message "Admin consent granted successfully." -Level "INFO" # return $response # } catch { # Write-EnhancedLog -Message "An error occurred while granting admin consent." -Level "ERROR" # Handle-Error -ErrorRecord $_ # throw $_ # } # } # # # Example usage # # $scopes = @("Application.ReadWrite.All", "Directory.ReadWrite.All", "AppRoleAssignment.ReadWrite.All") # # Connect-MgGraph -Scopes $scopes # # Grant-AdminConsentToApiPermissions -ClientId "your-application-id" # function Grant-AdminConsentToApiPermissions { # param ( # [Parameter(Mandatory = $true)] # [string]$clientId, # [Parameter(Mandatory = $true)] # [string]$SPPermissionsPath # ) # try { # Write-EnhancedLog -Message "Starting the process to grant admin consent to API permissions for App ID: $clientId" -Level "INFO" # # Load permissions from the PSD1 file # $permissionsFile = Join-Path -Path $SPPermissionsPath -ChildPath "SPPermissions.psd1" # if (-not (Test-Path -Path $permissionsFile)) { # Write-EnhancedLog -Message "Permissions file not found: $permissionsFile" -Level "ERROR" # throw "Permissions file not found" # } # $permissionsData = Import-PowerShellDataFile -Path $permissionsFile # # Extract the permissions that are granted and consolidate both application and delegated permissions # $grantedPermissions = @( # $permissionsData.applicationPermissions | Where-Object { $_.granted -eq $true } | Select-Object -ExpandProperty name # $permissionsData.delegatedPermissions | Where-Object { $_.granted -eq $true } | Select-Object -ExpandProperty name # ) # Wait-Debugger # Write-EnhancedLog -Message "Permissions to be granted: $($grantedPermissions -join ', ')" -Level "INFO" # # Create and verify the service principal # Create-AndVerifyServicePrincipal -ClientId $clientId # Write-EnhancedLog -Message "Granting admin consent to API permissions for App ID: $clientId" -Level "INFO" # # Retrieve the service principal for the application # $servicePrincipal = Get-MgServicePrincipal -Filter "AppId eq '$clientId'" # if ($null -eq $servicePrincipal) { # Write-EnhancedLog -Message "Service principal not found for the specified application ID." -Level "ERROR" # throw "Service principal not found" # } # Write-EnhancedLog -Message "Service principal for app ID: $clientId retrieved successfully." -Level "INFO" # # Retrieve the service principal ID # $servicePrincipalId = $servicePrincipal.Id # # Retrieve the Microsoft Graph service principal # $graphServicePrincipal = Get-MgServicePrincipal -Filter "displayName eq 'Microsoft Graph'" -Select id,appRoles # if ($null -eq $graphServicePrincipal) { # Write-EnhancedLog -Message "Microsoft Graph service principal not found." -Level "ERROR" # throw "Microsoft Graph service principal not found" # } # $resourceId = $graphServicePrincipal.Id # $appRoles = $graphServicePrincipal.AppRoles # # Find the IDs of the required permissions # $requiredRoles = $appRoles | Where-Object { $grantedPermissions -contains $_.Value } | Select-Object Id, Value # if ($requiredRoles.Count -eq 0) { # Write-EnhancedLog -Message "No matching app roles found for the specified permissions." -Level "ERROR" # throw "No matching app roles found" # } # Write-EnhancedLog -Message "App roles to be granted: $($requiredRoles.Value -join ', ')" -Level "INFO" # # Grant the app roles (application permissions) # foreach ($role in $requiredRoles) { # $body = @{ # principalId = $servicePrincipalId # resourceId = $resourceId # appRoleId = $role.Id # } # $response = Invoke-MgGraphRequest -Uri "https://graph.microsoft.com/v1.0/servicePrincipals/$resourceId/appRoleAssignedTo" -Method POST -Body ($body | ConvertTo-Json) -ContentType "application/json" # Write-EnhancedLog -Message "Granted app role: $($role.Value) with ID: $($role.Id)" -Level "INFO" # } # Write-EnhancedLog -Message "Admin consent granted successfully." -Level "INFO" # return $response # } catch { # Write-EnhancedLog -Message "An error occurred while granting admin consent." -Level "ERROR" # Handle-Error -ErrorRecord $_ # throw $_ # } # } # Example usage: # Grant-AdminConsentToApiPermissions -ClientId "your-application-id" -SPPermissionsPath "C:\path\to\permissions" # function Grant-AdminConsentToApiPermissions { # param ( # [Parameter(Mandatory = $true)] # [string]$clientId, # [Parameter(Mandatory = $true)] # [string]$SPPermissionsPath # ) # try { # Write-EnhancedLog -Message "Starting the process to grant admin consent to API permissions for App ID: $clientId" -Level "INFO" # # Load permissions from the PSD1 file # $permissionsFile = Join-Path -Path $SPPermissionsPath -ChildPath "SPPermissions.psd1" # if (-not (Test-Path -Path $permissionsFile)) { # Write-EnhancedLog -Message "Permissions file not found: $permissionsFile" -Level "ERROR" # throw "Permissions file not found" # } # $permissionsData = Import-PowerShellDataFile -Path $permissionsFile # # Extract the permissions that are granted and consolidate both application and delegated permissions # $grantedPermissions = @( # $permissionsData.applicationPermissions | Where-Object { $_.granted -eq $true } | Select-Object -ExpandProperty permissionName # $permissionsData.delegatedPermissions | Where-Object { $_.granted -eq $true } | Select-Object -ExpandProperty permissionName # ) # if ($grantedPermissions.Count -eq 0) { # Write-EnhancedLog -Message "No permissions to be granted were found." -Level "WARNING" # } else { # Write-EnhancedLog -Message "Permissions to be granted: $($grantedPermissions -join ', ')" -Level "INFO" # } # # Create and verify the service principal # Create-AndVerifyServicePrincipal -ClientId $clientId # Write-EnhancedLog -Message "Granting admin consent to API permissions for App ID: $clientId" -Level "INFO" # # Retrieve the service principal for the application # $servicePrincipal = Get-MgServicePrincipal -Filter "AppId eq '$clientId'" # if ($null -eq $servicePrincipal) { # Write-EnhancedLog -Message "Service principal not found for the specified application ID." -Level "ERROR" # throw "Service principal not found" # } # Write-EnhancedLog -Message "Service principal for app ID: $clientId retrieved successfully." -Level "INFO" # # Retrieve the service principal ID # $servicePrincipalId = $servicePrincipal.Id # # Retrieve the Microsoft Graph service principal # $graphServicePrincipal = Get-MgServicePrincipal -Filter "displayName eq 'Microsoft Graph'" -Select id,appRoles # if ($null -eq $graphServicePrincipal) { # Write-EnhancedLog -Message "Microsoft Graph service principal not found." -Level "ERROR" # throw "Microsoft Graph service principal not found" # } # $resourceId = $graphServicePrincipal.Id # $appRoles = $graphServicePrincipal.AppRoles # # Find the IDs of the required permissions # $requiredRoles = $appRoles | Where-Object { $grantedPermissions -contains $_.Value } | Select-Object Id, Value # if ($requiredRoles.Count -eq 0) { # Write-EnhancedLog -Message "No matching app roles found for the specified permissions." -Level "ERROR" # throw "No matching app roles found" # } # Write-EnhancedLog -Message "App roles to be granted: $($requiredRoles.Value -join ', ')" -Level "INFO" # # Grant the app roles (application permissions) # foreach ($role in $requiredRoles) { # $body = @{ # principalId = $servicePrincipalId # resourceId = $resourceId # appRoleId = $role.Id # } # $response = Invoke-MgGraphRequest -Uri "https://graph.microsoft.com/v1.0/servicePrincipals/$resourceId/appRoleAssignedTo" -Method POST -Body ($body | ConvertTo-Json) -ContentType "application/json" # Write-EnhancedLog -Message "Granted app role: $($role.Value) with ID: $($role.Id)" -Level "INFO" # } # Write-EnhancedLog -Message "Admin consent granted successfully." -Level "INFO" # return $response # } catch { # Write-EnhancedLog -Message "An error occurred while granting admin consent." -Level "ERROR" # Handle-Error -ErrorRecord $_ # throw $_ # } # } # function Grant-AdminConsentToApiPermissions { # param ( # [Parameter(Mandatory = $true)] # [string]$clientId, # [Parameter(Mandatory = $true)] # [string]$SPPermissionsPath # ) # try { # Write-EnhancedLog -Message "Starting the process to grant admin consent to API permissions for App ID: $clientId" -Level "INFO" # # Load permissions from the PSD1 file # $permissionsFile = Join-Path -Path $SPPermissionsPath -ChildPath "SPPermissions.psd1" # if (-not (Test-Path -Path $permissionsFile)) { # Write-EnhancedLog -Message "Permissions file not found: $permissionsFile" -Level "ERROR" # throw "Permissions file not found" # } # $permissionsData = Import-PowerShellDataFile -Path $permissionsFile # # Extract the permissions that are granted and consolidate both application and delegated permissions # $grantedPermissions = @( # $permissionsData.applicationPermissions | Where-Object { $_.granted -eq $true } | Select-Object -ExpandProperty name # $permissionsData.delegatedPermissions | Where-Object { $_.granted -eq $true } | Select-Object -ExpandProperty name # ) # if ($grantedPermissions.Count -eq 0) { # Write-EnhancedLog -Message "No permissions to be granted were found." -Level "WARNING" # } else { # Write-EnhancedLog -Message "Permissions to be granted: $($grantedPermissions -join ', ')" -Level "INFO" # } # # Create and verify the service principal # Create-AndVerifyServicePrincipal -ClientId $clientId # Write-EnhancedLog -Message "Granting admin consent to API permissions for App ID: $clientId" -Level "INFO" # # Retrieve the service principal for the application # $servicePrincipal = Get-MgServicePrincipal -Filter "AppId eq '$clientId'" # if ($null -eq $servicePrincipal) { # Write-EnhancedLog -Message "Service principal not found for the specified application ID." -Level "ERROR" # throw "Service principal not found" # } # Write-EnhancedLog -Message "Service principal for app ID: $clientId retrieved successfully." -Level "INFO" # # Retrieve the service principal ID # $servicePrincipalId = $servicePrincipal.Id # # Retrieve the Microsoft Graph service principal # $graphServicePrincipal = Get-MgServicePrincipal -Filter "displayName eq 'Microsoft Graph'" -Select id,appRoles # if ($null -eq $graphServicePrincipal) { # Write-EnhancedLog -Message "Microsoft Graph service principal not found." -Level "ERROR" # throw "Microsoft Graph service principal not found" # } # $resourceId = $graphServicePrincipal.Id # $appRoles = $graphServicePrincipal.AppRoles # # Find the IDs of the required permissions # $requiredRoles = $appRoles | Where-Object { $grantedPermissions -contains $_.Value } | Select-Object Id, Value # if ($requiredRoles.Count -eq 0) { # Write-EnhancedLog -Message "No matching app roles found for the specified permissions." -Level "ERROR" # throw "No matching app roles found" # } # Write-EnhancedLog -Message "App roles to be granted: $($requiredRoles.Value -join ', ')" -Level "INFO" # # Grant the app roles (application permissions) # foreach ($role in $requiredRoles) { # $body = @{ # principalId = $servicePrincipalId # resourceId = $resourceId # appRoleId = $role.Id # } # $response = Invoke-MgGraphRequest -Uri "https://graph.microsoft.com/v1.0/servicePrincipals/$resourceId/appRoleAssignedTo" -Method POST -Body ($body | ConvertTo-Json) -ContentType "application/json" # Write-EnhancedLog -Message "Granted app role: $($role.Value) with ID: $($role.Id)" -Level "INFO" # } # Write-EnhancedLog -Message "Admin consent granted successfully." -Level "INFO" # return $response # } catch { # Write-EnhancedLog -Message "An error occurred while granting admin consent." -Level "ERROR" # Handle-Error -ErrorRecord $_ # throw $_ # } # } # function Grant-AdminConsentToApiPermissions { # param ( # [Parameter(Mandatory = $true)] # [string]$clientId, # [Parameter(Mandatory = $true)] # [string]$SPPermissionsPath # ) # try { # Write-EnhancedLog -Message "Starting the process to grant admin consent to API permissions for App ID: $clientId" -Level "INFO" # # Load permissions from the PSD1 file # $permissionsFile = Join-Path -Path $SPPermissionsPath -ChildPath "SPPermissions.psd1" # if (-not (Test-Path -Path $permissionsFile)) { # Write-EnhancedLog -Message "Permissions file not found: $permissionsFile" -Level "ERROR" # throw "Permissions file not found" # } # # Import the PSD1 data # $permissionsData = Import-PowerShellDataFile -Path $permissionsFile # # Ensure application and delegated permissions are present # $applicationPermissions = $permissionsData.applicationPermissions # $delegatedPermissions = $permissionsData.delegatedPermissions # # Combine both granted application and delegated permissions # $grantedPermissions = @( # $applicationPermissions | Where-Object { $_.granted -eq $true } | Select-Object -ExpandProperty name # $delegatedPermissions | Where-Object { $_.granted -eq $true } | Select-Object -ExpandProperty name # ) # if ($grantedPermissions.Count -eq 0) { # Write-EnhancedLog -Message "No permissions to be granted were found." -Level "WARNING" # } else { # Write-EnhancedLog -Message "Permissions to be granted: $($grantedPermissions -join ', ')" -Level "INFO" # } # # Create and verify the service principal # Create-AndVerifyServicePrincipal -ClientId $clientId # Write-EnhancedLog -Message "Granting admin consent to API permissions for App ID: $clientId" -Level "INFO" # # Retrieve the service principal for the application # $servicePrincipal = Get-MgServicePrincipal -Filter "AppId eq '$clientId'" # if ($null -eq $servicePrincipal) { # Write-EnhancedLog -Message "Service principal not found for the specified application ID." -Level "ERROR" # throw "Service principal not found" # } # Write-EnhancedLog -Message "Service principal for app ID: $clientId retrieved successfully." -Level "INFO" # # Retrieve the service principal ID # $servicePrincipalId = $servicePrincipal.Id # # Retrieve the Microsoft Graph service principal # $graphServicePrincipal = Get-MgServicePrincipal -Filter "displayName eq 'Microsoft Graph'" -Select id,appRoles # if ($null -eq $graphServicePrincipal) { # Write-EnhancedLog -Message "Microsoft Graph service principal not found." -Level "ERROR" # throw "Microsoft Graph service principal not found" # } # $resourceId = $graphServicePrincipal.Id # $appRoles = $graphServicePrincipal.AppRoles # # Find the IDs of the required permissions # $requiredRoles = $appRoles | Where-Object { $grantedPermissions -contains $_.Value } | Select-Object Id, Value # if ($requiredRoles.Count -eq 0) { # Write-EnhancedLog -Message "No matching app roles found for the specified permissions." -Level "ERROR" # throw "No matching app roles found" # } # Write-EnhancedLog -Message "App roles to be granted: $($requiredRoles.Value -join ', ')" -Level "INFO" # # Grant the app roles (application permissions) # foreach ($role in $requiredRoles) { # $body = @{ # principalId = $servicePrincipalId # resourceId = $resourceId # appRoleId = $role.Id # } # $response = Invoke-MgGraphRequest -Uri "https://graph.microsoft.com/v1.0/servicePrincipals/$resourceId/appRoleAssignedTo" -Method POST -Body ($body | ConvertTo-Json) -ContentType "application/json" # Write-EnhancedLog -Message "Granted app role: $($role.Value) with ID: $($role.Id)" -Level "INFO" # } # Write-EnhancedLog -Message "Admin consent granted successfully." -Level "INFO" # return $response # } catch { # Write-EnhancedLog -Message "An error occurred while granting admin consent." -Level "ERROR" # Handle-Error -ErrorRecord $_ # throw $_ # } # } # function Grant-AdminConsentToApiPermissions { # param ( # [Parameter(Mandatory = $true)] # [string]$clientId, # [Parameter(Mandatory = $true)] # [string]$SPPermissionsPath # ) # try { # Write-EnhancedLog -Message "Starting the process to grant admin consent to API permissions for App ID: $clientId" -Level "INFO" # # Load permissions from the PSD1 file # $permissionsFile = Join-Path -Path $SPPermissionsPath -ChildPath "SPPermissions.psd1" # if (-not (Test-Path -Path $permissionsFile)) { # Write-EnhancedLog -Message "Permissions file not found: $permissionsFile" -Level "ERROR" # throw "Permissions file not found" # } # $permissionsData = Import-PowerShellDataFile -Path $permissionsFile # $applicationPermissions = $permissionsData.applicationPermissions | Where-Object { $_.granted -eq $true } | Select-Object -ExpandProperty name # $delegatedPermissions = $permissionsData.delegatedPermissions | Where-Object { $_.granted -eq $true } | Select-Object -ExpandProperty name # Write-EnhancedLog -Message "Application permissions to be granted: $($applicationPermissions -join ', ')" -Level "INFO" # Write-EnhancedLog -Message "Delegated permissions to be granted: $($delegatedPermissions -join ', ')" -Level "INFO" # # Create and verify the service principal # Create-AndVerifyServicePrincipal -ClientId $clientId # Write-EnhancedLog -Message "Granting admin consent to API permissions for App ID: $clientId" -Level "INFO" # # Retrieve the service principal for the application # $servicePrincipal = Get-MgServicePrincipal -Filter "AppId eq '$clientId'" # if ($null -eq $servicePrincipal) { # Write-EnhancedLog -Message "Service principal not found for the specified application ID." -Level "ERROR" # throw "Service principal not found" # } # Write-EnhancedLog -Message "Service principal for app ID: $clientId retrieved successfully." -Level "INFO" # # Retrieve the service principal ID # $servicePrincipalId = $servicePrincipal.Id # # Retrieve the Microsoft Graph service principal # $graphServicePrincipal = Get-MgServicePrincipal -Filter "displayName eq 'Microsoft Graph'" -Select id,appRoles # if ($null -eq $graphServicePrincipal) { # Write-EnhancedLog -Message "Microsoft Graph service principal not found." -Level "ERROR" # throw "Microsoft Graph service principal not found" # } # $resourceId = $graphServicePrincipal.Id # $appRoles = $graphServicePrincipal.AppRoles # # Combine the permissions (application + delegated) # $allPermissions = $applicationPermissions + $delegatedPermissions # # Find the IDs of the required permissions # $requiredRoles = $appRoles | Where-Object { $allPermissions -contains $_.Value } | Select-Object Id, Value # if ($requiredRoles.Count -eq 0) { # Write-EnhancedLog -Message "No matching app roles found for the specified permissions." -Level "ERROR" # throw "No matching app roles found" # } # Write-EnhancedLog -Message "App roles to be granted: $($requiredRoles.Value -join ', ')" -Level "INFO" # # Grant the app roles (application permissions) # foreach ($role in $requiredRoles) { # $body = @{ # principalId = $servicePrincipalId # resourceId = $resourceId # appRoleId = $role.Id # } # $response = Invoke-MgGraphRequest -Uri "https://graph.microsoft.com/v1.0/servicePrincipals/$resourceId/appRoleAssignedTo" -Method POST -Body ($body | ConvertTo-Json) -ContentType "application/json" # Write-EnhancedLog -Message "Granted app role: $($role.Value) with ID: $($role.Id)" -Level "INFO" # } # Write-EnhancedLog -Message "Admin consent granted successfully." -Level "INFO" # return $response # } catch { # Write-EnhancedLog -Message "An error occurred while granting admin consent." -Level "ERROR" # Handle-Error -ErrorRecord $_ # throw $_ # } # } # function Grant-AdminConsentToApiPermissions { # param ( # [Parameter(Mandatory = $true)] # [string]$clientId, # [Parameter(Mandatory = $true)] # [string]$SPPermissionsPath # ) # try { # Write-EnhancedLog -Message "Starting the process to grant admin consent to API permissions for App ID: $clientId" -Level "INFO" # # Load permissions from the PSD1 file # $permissionsFile = Join-Path -Path $SPPermissionsPath -ChildPath "SPPermissions.psd1" # if (-not (Test-Path -Path $permissionsFile)) { # Write-EnhancedLog -Message "Permissions file not found: $permissionsFile" -Level "ERROR" # throw "Permissions file not found" # } # $permissionsData = Import-PowerShellDataFile -Path $permissionsFile # # Combine application and delegated permissions # $allPermissions = @($permissionsData.applicationPermissions + $permissionsData.delegatedPermissions) # # Filter granted permissions and ensure property existence # $grantedPermissions = foreach ($perm in $allPermissions) { # if ($perm.PSObject.Properties['name'] -and $perm.granted -eq $true) { # $perm.name # } else { # # Log if property is missing or invalid # Write-EnhancedLog -Message "Permission object missing 'name' property or is not granted: $($perm | Out-String)" -Level "WARNING" # } # } # if ($grantedPermissions.Count -eq 0) { # Write-EnhancedLog -Message "No granted permissions found." -Level "ERROR" # throw "No granted permissions found." # } # Write-EnhancedLog -Message "Permissions to be granted: $($grantedPermissions -join ', ')" -Level "INFO" # # Create and verify the service principal # Create-AndVerifyServicePrincipal -ClientId $clientId # Write-EnhancedLog -Message "Granting admin consent to API permissions for App ID: $clientId" -Level "INFO" # # Retrieve the service principal for the application # $servicePrincipal = Get-MgServicePrincipal -Filter "AppId eq '$clientId'" # if ($null -eq $servicePrincipal) { # Write-EnhancedLog -Message "Service principal not found for the specified application ID." -Level "ERROR" # throw "Service principal not found" # } # Write-EnhancedLog -Message "Service principal for app ID: $clientId retrieved successfully." -Level "INFO" # # Retrieve the service principal ID # $servicePrincipalId = $servicePrincipal.Id # # Retrieve the Microsoft Graph service principal # $graphServicePrincipal = Get-MgServicePrincipal -Filter "displayName eq 'Microsoft Graph'" -Select id,appRoles # if ($null -eq $graphServicePrincipal) { # Write-EnhancedLog -Message "Microsoft Graph service principal not found." -Level "ERROR" # throw "Microsoft Graph service principal not found" # } # $resourceId = $graphServicePrincipal.Id # $appRoles = $graphServicePrincipal.AppRoles # # Find the IDs of the required permissions # $requiredRoles = $appRoles | Where-Object { $grantedPermissions -contains $_.Value } | Select-Object Id, Value # if ($requiredRoles.Count -eq 0) { # Write-EnhancedLog -Message "No matching app roles found for the specified permissions." -Level "ERROR" # throw "No matching app roles found" # } # Write-EnhancedLog -Message "App roles to be granted: $($requiredRoles.Value -join ', ')" -Level "INFO" # # Grant the app roles (application permissions) # foreach ($role in $requiredRoles) { # $body = @{ # principalId = $servicePrincipalId # resourceId = $resourceId # appRoleId = $role.Id # } # $response = Invoke-MgGraphRequest -Uri "https://graph.microsoft.com/v1.0/servicePrincipals/$resourceId/appRoleAssignedTo" -Method POST -Body ($body | ConvertTo-Json) -ContentType "application/json" # Write-EnhancedLog -Message "Granted app role: $($role.Value) with ID: $($role.Id)" -Level "INFO" # } # Write-EnhancedLog -Message "Admin consent granted successfully." -Level "INFO" # return $response # } catch { # Write-EnhancedLog -Message "An error occurred while granting admin consent." -Level "ERROR" # Handle-Error -ErrorRecord $_ # throw $_ # } # } function Grant-AdminConsentToApiPermissions { param ( [Parameter(Mandatory = $true)] [string]$clientId, [Parameter(Mandatory = $true)] [string]$SPPermissionsPath ) try { Write-EnhancedLog -Message "Starting the process to grant admin consent to API permissions for App ID: $clientId" -Level "INFO" # Load permissions from the PSD1 file $permissionsFile = Join-Path -Path $SPPermissionsPath -ChildPath "SPPermissions.psd1" if (-not (Test-Path -Path $permissionsFile)) { Write-EnhancedLog -Message "Permissions file not found: $permissionsFile" -Level "ERROR" throw "Permissions file not found" } $permissionsData = Import-PowerShellDataFile -Path $permissionsFile # Combine application and delegated permissions $allPermissions = @($permissionsData.applicationPermissions + $permissionsData.delegatedPermissions) # Filter granted permissions and ensure property existence $grantedPermissions = @() $allPermissions | ForEach-Object { if ($_ -is [hashtable] -or $_ -is [pscustomobject]) { # If it's a hashtable, make sure the 'name' and 'granted' properties exist if ($_['name'] -and $_['granted'] -eq $true) { $grantedPermissions += $_['name'] } else { # Log if 'name' or 'granted' is missing or false Write-EnhancedLog -Message "Permission object missing 'name' or 'granted' is false: $($_ | Out-String)" -Level "WARNING" } } else { # Log if it's not a supported object type Write-EnhancedLog -Message "Unsupported object type: $($_.GetType().FullName)" -Level "WARNING" } } if ($grantedPermissions.Count -eq 0) { Write-EnhancedLog -Message "No granted permissions found." -Level "ERROR" throw "No granted permissions found." } Write-EnhancedLog -Message "Permissions to be granted: $($grantedPermissions -join ', ')" -Level "INFO" # Create and verify the service principal Create-AndVerifyServicePrincipal -ClientId $clientId Write-EnhancedLog -Message "Granting admin consent to API permissions for App ID: $clientId" -Level "INFO" # Retrieve the service principal for the application $servicePrincipal = Get-MgServicePrincipal -Filter "AppId eq '$clientId'" if ($null -eq $servicePrincipal) { Write-EnhancedLog -Message "Service principal not found for the specified application ID." -Level "ERROR" throw "Service principal not found" } Write-EnhancedLog -Message "Service principal for app ID: $clientId retrieved successfully." -Level "INFO" # Retrieve the service principal ID $servicePrincipalId = $servicePrincipal.Id # Retrieve the Microsoft Graph service principal $graphServicePrincipal = Get-MgServicePrincipal -Filter "displayName eq 'Microsoft Graph'" -Select id,appRoles if ($null -eq $graphServicePrincipal) { Write-EnhancedLog -Message "Microsoft Graph service principal not found." -Level "ERROR" throw "Microsoft Graph service principal not found" } $resourceId = $graphServicePrincipal.Id $appRoles = $graphServicePrincipal.AppRoles # Find the IDs of the required permissions $requiredRoles = $appRoles | Where-Object { $grantedPermissions -contains $_.Value } | Select-Object Id, Value if ($requiredRoles.Count -eq 0) { Write-EnhancedLog -Message "No matching app roles found for the specified permissions." -Level "ERROR" throw "No matching app roles found" } Write-EnhancedLog -Message "App roles to be granted: $($requiredRoles.Value -join ', ')" -Level "INFO" # Grant the app roles (application permissions) foreach ($role in $requiredRoles) { $body = @{ principalId = $servicePrincipalId resourceId = $resourceId appRoleId = $role.Id } $response = Invoke-MgGraphRequest -Uri "https://graph.microsoft.com/v1.0/servicePrincipals/$resourceId/appRoleAssignedTo" -Method POST -Body ($body | ConvertTo-Json) -ContentType "application/json" Write-EnhancedLog -Message "Granted app role: $($role.Value) with ID: $($role.Id)" -Level "INFO" } Write-EnhancedLog -Message "Admin consent granted successfully." -Level "INFO" return $response } catch { Write-EnhancedLog -Message "An error occurred while granting admin consent." -Level "ERROR" Handle-Error -ErrorRecord $_ throw $_ } } #EndRegion '.\Public\Grant-AdminConsentToApiPermissions.ps1' 818 #Region '.\Public\Grant-AdminConsentToDelegatedPermissions.ps1' -1 # function Grant-AdminConsentToDelegatedPermissions { # param ( # [Parameter(Mandatory = $true)] # [string]$AppId, # [Parameter(Mandatory = $true)] # [string]$Permissions, # [Parameter(Mandatory = $true)] # [string]$AccessToken # ) # try { # Write-EnhancedLog -Message "Granting tenant-wide admin consent to API permissions for App ID: $AppId" -Level "INFO" # # Retrieve the service principal for Microsoft Graph # $graphServicePrincipal = Get-MgServicePrincipal -Filter "displayName eq 'Microsoft Graph'" -Select id,displayName,appId,oauth2PermissionScopes # if ($null -eq $graphServicePrincipal) { # Write-EnhancedLog -Message "Service principal for Microsoft Graph not found." -Level "ERROR" # throw "Service principal for Microsoft Graph not found" # } # Write-EnhancedLog -Message "Microsoft Graph service principal retrieved successfully." -Level "INFO" # # Retrieve the service principal for the client application # $clientServicePrincipal = Get-MgServicePrincipal -Filter "appId eq '$AppId'" # if ($null -eq $clientServicePrincipal) { # Write-EnhancedLog -Message "Service principal not found for the specified application ID." -Level "ERROR" # throw "Service principal not found" # } # Write-EnhancedLog -Message "Service principal for client application retrieved successfully." -Level "INFO" # # Grant the delegated permissions to the client enterprise application # $body = @{ # clientId = $clientServicePrincipal.Id # consentType = "AllPrincipals" # resourceId = $graphServicePrincipal.Id # scope = $Permissions # } # $headers = @{ # "Authorization" = "Bearer $AccessToken" # "Content-Type" = "application/json" # } # $response = Invoke-RestMethod -Uri "https://graph.microsoft.com/v1.0/oauth2PermissionGrants" -Method POST -Headers $headers -Body ($body | ConvertTo-Json) # Write-EnhancedLog -Message "Tenant-wide admin consent granted successfully." -Level "INFO" # return $response # } catch { # Write-EnhancedLog -Message "An error occurred while granting tenant-wide admin consent." -Level "ERROR" # Handle-Error -ErrorRecord $_ # throw $_ # } # } # # Example usage # # $accessToken = "your-access-token" # # Grant-AdminConsentToDelegatedPermissions -AppId "08216f27-1d3d-4a9f-9406-80f957e7fca6" -Permissions "User.Read.All Group.Read.All" -AccessToken $accessToken #EndRegion '.\Public\Grant-AdminConsentToDelegatedPermissions.ps1' 63 #Region '.\Public\Grant-AdminConsentUsingAzCli.ps1' -1 # function Grant-AdminConsentUsingAzCli { # param ( # [Parameter(Mandatory = $true)] # [string]$AppId # ) # try { # Write-EnhancedLog -Message "Granting admin consent to Azure AD application with App ID: $AppId using Azure CLI" -Level "INFO" # #First download and install Az CLI # # $ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest -Uri https://aka.ms/installazurecliwindows -OutFile .\AzureCLI.msi; Start-Process msiexec.exe -Wait -ArgumentList '/I AzureCLI.msi /quiet'; Remove-Item .\AzureCLI.msi # # Run the following to fix the issue mentioned here https://github.com/Azure/azure-cli/issues/28997 # az account clear # az config set core.enable_broker_on_windows=false # # Now login (it will open up a web browser window to login as normal) # #If you have an Azure Subscription # # az login # #If you DO NOT have an Azure Subscription # az login --allow-no-subscriptions # # $DBG # # Execute the Azure CLI command to grant admin consent # $azCliCommand = "az ad app permission admin-consent --id $AppId" # $output = Invoke-Expression -Command $azCliCommand # # $DBG # if ($output -match "deprecated") { # Write-EnhancedLog -Message "The 'admin-consent' command is deprecated. Use 'az ad app permission grant' instead." -Level "WARNING" # } # Write-EnhancedLog -Message "Admin consent granted successfully using Azure CLI." -Level "INFO" # az logout # return $output # } catch { # Write-EnhancedLog -Message "An error occurred while granting admin consent using Azure CLI." -Level "ERROR" # Handle-Error -ErrorRecord $_ # throw $_ # } # } # # Example usage # # Grant-AdminConsentUsingAzCli -AppId "your-application-id" # #Readme # # https://github.com/Azure/azure-cli/issues/28997 # # Solution: (After installing azure-cli-2.61.0-x64.msi the az command will become available through the PATH ENV Variable located in C:\Program Files\Microsoft SDKs\Azure\CLI2\wbin now to fix the az login issue mentioned follow these steps carefully # # Step 1: open CMD or PoweShell 5 or 7 (in VS Code, Terminal or normal Shell) AS Admin # # Step 2: Run the following command az account clear (you will get nothing back) # # Step 3: Run the following command az config set core.enable_broker_on_windows=false (you will get "A web browser has been opened at https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize. Please continue the login in the web browser. If no web browser is available or if the web browser fails to open, use device code flow with az login --use-device-code.") and then a web login page will open # # Step4: Once you login it will say in the webpage # # You have logged into Microsoft Azure! # # You can close this window, or we will redirect you to the Azure CLI documentation in 1 minute. # #Example Output # # C:\Users\Administrator>az account clear # # C:\Users\Administrator>az login # # Please select the account you want to log in with. # # User cancelled the Accounts Control Operation.. Status: Response_Status.Status_UserCanceled, Error code: 0, Tag: 528315210 # # Please explicitly log in with: # # az login # # C:\Users\Administrator>az account clear # # C:\Users\Administrator>az config set core.enable_broker_on_windows=false # # Command group 'config' is experimental and under development. Reference and support levels: https://aka.ms/CLI_refstatus # # C:\Users\Administrator>az login # # A web browser has been opened at https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize. Please continue the login in the web browser. If no web browser is available or if the web browser fails to open, use device code flow with `az login --use-device-code`. # # Retrieving tenants and subscriptions for the selection... # # The following tenants don't contain accessible subscriptions. Use `az login --allow-no-subscriptions` to have tenant level access. # # 5784dc53-9279-4dc4-8b3d-cf6e8d4f9c50 'CASN' # # No subscriptions found for NovaAdmin_AOllivierre@casn.ca. # # C:\Users\Administrator> # # az login --allow-no-subscriptions in pwsh at 05:40:25 # # A web browser has been opened at https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize. Please continue the login in the web browser. If no web browser is available or if the web browser fails to open, use device code flow with `az login --use-device-code`. # # Retrieving tenants and subscriptions for the selection... # # The following tenants don't contain accessible subscriptions. Use `az login --allow-no-subscriptions` to have tenant level access. # # 5784dc53-9279-4dc4-8b3d-cf6e8d4f9c50 'CASN' # # [Tenant and subscription selection] # # No Subscription name Subscription ID Tenant # # ----- ------------------------- ------------------------------------ ------------------------------------ # # [1] * N/A(tenant level account) 5784dc53-9279-4dc4-8b3d-cf6e8d4f9c50 5784dc53-9279-4dc4-8b3d-cf6e8d4f9c50 # # The default is marked with an *; the default tenant is '5784dc53-9279-4dc4-8b3d-cf6e8d4f9c50' and subscription is 'N/A(tenant level account)' (5784dc53-9279-4dc4-8b3d-cf6e8d4f9c50). # # Select a subscription and tenant (Type a number or Enter for no changes): 1 # # Tenant: 5784dc53-9279-4dc4-8b3d-cf6e8d4f9c50 # # Subscription: N/A(tenant level account) (5784dc53-9279-4dc4-8b3d-cf6e8d4f9c50) # # [Announcements] # # With the new Azure CLI login experience, you can select the subscription you want to use more easily. Learn more about it and its configuration at https://go.microsoft.com/fwlink/?linkid=2271236 # # If you encounter any problem, please open an issue at https://aka.ms/azclibug # # [Warning] The login output has been updated. Please be aware that it no longer displays the full list of available subscriptions by default. #EndRegion '.\Public\Grant-AdminConsentUsingAzCli.ps1' 131 #Region '.\Public\Import-CertificateIfNotExist.ps1' -1 function Import-CertificateIfNotExist { param ( [Parameter(Mandatory = $true)] [string]$CertPath, [Parameter(Mandatory = $true)] [string]$CertPassword ) try { Write-EnhancedLog -Message "Starting certificate import process." -Level "INFO" # Load the PFX file using the constructor $securePassword = ConvertTo-SecureString -String $CertPassword -AsPlainText -Force $cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($CertPath, $securePassword, [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::PersistKeySet) # Check if the certificate already exists in the local machine store $store = New-Object System.Security.Cryptography.X509Certificates.X509Store("My", "LocalMachine") $store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadOnly) $existingCert = $store.Certificates | Where-Object { $_.Thumbprint -eq $cert.Thumbprint } $store.Close() if ($existingCert) { Write-EnhancedLog -Message "Certificate already exists in the local machine store." -Level "INFO" } else { Write-EnhancedLog -Message "Certificate does not exist in the local machine store. Importing certificate..." -Level "INFO" # Open the store with write access and add the certificate $store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite) $store.Add($cert) $store.Close() Write-EnhancedLog -Message "Certificate imported successfully." -Level "INFO" } } catch { Write-EnhancedLog -Message "An error occurred during the certificate import process." -Level "ERROR" Handle-Error -ErrorRecord $_ throw $_ } } # Example usage # $params = @{ # CertPath = "C:\Path\To\Your\Certificate.pfx" # CertPassword = "YourPfxPassword" # } # Import-CertificateIfNotExist @params #EndRegion '.\Public\Import-CertificateIfNotExist.ps1' 49 #Region '.\Public\Invoke-EnhancedGraphAORequest.ps1' -1 function Invoke-EnhancedGraphAORequest { param ( [string]$Method, [string]$Uri, [string]$AccessToken, [string]$Body = $null ) $httpClient = New-Object System.Net.Http.HttpClient $httpClient.DefaultRequestHeaders.Authorization = New-Object System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", $AccessToken) try { if ($Body) { $content = New-Object System.Net.Http.StringContent($Body, [System.Text.Encoding]::UTF8, "application/json") } $response = $null switch ($Method) { "GET" { $response = $httpClient.GetAsync($Uri).Result } "POST" { $response = $httpClient.PostAsync($Uri, $content).Result } "PATCH" { $response = $httpClient.PatchAsync($Uri, $content).Result } "DELETE" { $response = $httpClient.DeleteAsync($Uri).Result } } if (-not $response) { throw "No response received from the server." } $responseContent = $response.Content.ReadAsStringAsync().Result $responseStatus = $response.IsSuccessStatusCode # Define the directory for response JSON files $responseDir = Join-Path -Path $PSScriptRoot -ChildPath "responses" if (-not (Test-Path -Path $responseDir)) { New-Item -ItemType Directory -Path $responseDir } # Log the full request and response in JSON format $logEntry = @{ RequestUri = $Uri RequestMethod = $Method RequestBody = $Body Response = $responseContent IsSuccess = $responseStatus TimeStamp = Get-Date -Format "yyyyMMddHHmmssfff" } $logFile = Join-Path -Path $responseDir -ChildPath ("Response_$($logEntry.TimeStamp).json") $logEntry | ConvertTo-Json | Set-Content -Path $logFile Write-EnhancedLog -Message "Response logged to $logFile" -Level "INFO" if ($response.IsSuccessStatusCode) { Write-EnhancedLog -Message "Successfully executed $Method request to $Uri." -Level "INFO" return $responseContent } else { $errorContent = $responseContent Write-EnhancedLog -Message "HTTP request failed with status code: $($response.StatusCode). Error content: $errorContent" -Level "ERROR" return $null } } catch { Write-EnhancedLog -Message "Failed to execute $Method request to $Uri $_" -Level "ERROR" return $null } finally { $httpClient.Dispose() } } #EndRegion '.\Public\Invoke-EnhancedGraphAORequest.ps1' 71 #Region '.\Public\Load-Certificate.ps1' -1 function Load-Certificate { param ( [Parameter(Mandatory = $true)] [string]$CertPath, [Parameter(Mandatory = $true)] [string]$CertPassword ) try { Write-EnhancedLog -Message "Attempting to load certificate from path: $CertPath" -Level "INFO" # Validate certificate path before loading $certExistsBefore = Validate-Certificate -CertPath $CertPath if (-not $certExistsBefore) { throw "Certificate path does not exist: $CertPath" } # Check the OS and convert the certificate path if running on Linux if ($PSVersionTable.PSVersion.Major -ge 7) { if ($PSVersionTable.Platform -eq 'Unix') { $CertPath = Convert-WindowsPathToLinuxPath -WindowsPath $CertPath } } else { $os = [System.Environment]::OSVersion.Platform if ($os -eq [System.PlatformID]::Unix) { $CertPath = Convert-WindowsPathToLinuxPath -WindowsPath $CertPath } } # Load the certificate directly from the file $cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($CertPath, $CertPassword) Write-EnhancedLog -Message "Successfully loaded certificate from path: $CertPath" -Level "INFO" # Validate certificate path after loading $certExistsAfter = Validate-Certificate -CertPath $CertPath if ($certExistsAfter) { Write-EnhancedLog -Message "Certificate path still exists after loading: $CertPath" -Level "INFO" } else { Write-EnhancedLog -Message "Certificate path does not exist after loading: $CertPath" -Level "WARNING" } return $cert } catch { Write-EnhancedLog -Message "Error loading certificate from path: $CertPath. Error: $_" -Level "ERROR" throw $_ } } #EndRegion '.\Public\Load-Certificate.ps1' 51 #Region '.\Public\Open-CertificateStore.ps1' -1 function Open-CertificateStore { if (Is-ServerCore) { Write-Output "Running on Windows Server Core. Skipping opening of certificate manager." } else { # Open the certificate store Start-Process certmgr.msc } } #EndRegion '.\Public\Open-CertificateStore.ps1' 9 #Region '.\Public\Output-secrets.ps1' -1 function Output-Secrets { param ( [Parameter(Mandatory = $false)] [string]$AppDisplayName, [Parameter(Mandatory = $false)] [string]$ApplicationID, [Parameter(Mandatory = $false)] [string]$Thumbprint, [Parameter(Mandatory = $false)] [string]$TenantID, [Parameter(Mandatory = $false)] [string]$SecretsFile, [Parameter(Mandatory = $false)] [string]$CertPassword, [Parameter(Mandatory = $false)] [string]$CertName, [Parameter(Mandatory = $false)] [string]$TenantName, [Parameter(Mandatory = $false)] [string]$TenantDomainName, [Parameter(Mandatory = $false)] [string]$OutputPath ) try { Write-EnhancedLog -Message "Starting to output secrets." -Level "INFO" $secrets = @{ AppDisplayName = $AppDisplayName ClientId = $ApplicationID Thumbprint = $Thumbprint TenantID = $TenantID CertPassword = $CertPassword CertName = $CertName TenantName = $TenantName TenantDomainName = $TenantDomainName OutputPath = $OutputPath } $secrets | ConvertTo-Json | Set-Content -Path $SecretsFile Write-EnhancedLog -Message "Secrets have been written to file: $SecretsFile" -Level "INFO" Write-Host "================ Secrets ================" Write-Host "`$AppDisplayName = $($AppDisplayName)" Write-Host "`$ClientId = $($ApplicationID)" Write-Host "`$Thumbprint = $($Thumbprint)" Write-Host "`$TenantID = $TenantID" Write-Host "`$CertPassword = $CertPassword" Write-Host "`$CertName = $CertName" Write-Host "`$TenantName = $TenantName" Write-Host "`$TenantDomainName = $TenantDomainName" Write-Host "`$OutputPath = $OutputPath" Write-Host "================ Secrets ================" Write-Host " SAVE THESE IN A SECURE LOCATION " Write-EnhancedLog -Message "Secrets have been output to the console." -Level "INFO" } catch { Write-EnhancedLog -Message "An error occurred while outputting secrets." -Level "ERROR" Handle-Error -ErrorRecord $_ throw $_ } } # # Example usage # $params = @{ # AppDisplayName = $app.DisplayName # ApplicationID = $app.AppId # TenantID = $tenantDetails.Id # SecretsFile = $secretsfile # CertName = $Certname # Thumbprint = $thumbprint # CertPassword = $CertPassword # TenantName = $tenantDetails.DisplayName # TenantDomainName = $tenantDetails.DomainName # OutputPath = $certexportDirectory # } # Output-Secrets @params #EndRegion '.\Public\Output-secrets.ps1' 90 #Region '.\Public\Remove-AppListJson.ps1' -1 function Remove-AppListJson { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$JsonPath ) begin { Write-EnhancedLog -Message "Starting Remove-AppListJson function" -Level "INFO" Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters } process { try { # Check if the file exists if (Test-Path -Path $JsonPath) { # Remove the file $removeParams = @{ Path = $JsonPath Force = $true } Remove-Item @removeParams Write-EnhancedLog -Message "The applist.json file has been removed successfully." -Level "INFO" } else { Write-EnhancedLog -Message "The file at path '$JsonPath' does not exist." -Level "WARNING" } } catch { Write-EnhancedLog -Message "An error occurred while removing the file: $_" -Level "ERROR" Handle-Error -ErrorRecord $_ throw $_ } } end { Write-EnhancedLog -Message "Remove-AppListJson function execution completed." -Level "INFO" } } # Example usage # Remove-AppListJson -JsonPath "C:\Path\To\Your\applist.json" #EndRegion '.\Public\Remove-AppListJson.ps1' 43 #Region '.\Public\Remove-AppRegistrationsAndDeletedItems.ps1' -1 function Remove-AppRegistrationsAndDeletedItems { param ( [Parameter(Mandatory = $true)] [string]$AppDisplayNamePattern ) try { Write-EnhancedLog -Message "Starting cleanup process for app registrations with display names like: $AppDisplayNamePattern" -Level "INFO" # Retrieve all applications with the specified display name pattern $apps = Get-MgApplication -Filter "startswith(DisplayName,'graphapp-test')" if ($apps.Count -eq 0) { Write-EnhancedLog -Message "No applications found with display names like: $AppDisplayNamePattern" -Level "WARNING" return } Write-EnhancedLog -Message "Applications to be deleted: $($apps.DisplayName -join ', ')" -Level "INFO" # Remove each application foreach ($app in $apps) { Remove-MgApplication -ApplicationId $app.Id -Confirm:$false Write-EnhancedLog -Message "Deleted application: $($app.DisplayName) with ID: $($app.Id)" -Level "INFO" } Write-EnhancedLog -Message "Cleanup process completed successfully." -Level "INFO" } catch { Write-EnhancedLog -Message "An error occurred during the cleanup process." -Level "ERROR" Handle-Error -ErrorRecord $_ throw $_ } } # # Example usage # $scopes = @("Application.ReadWrite.All", "Directory.ReadWrite.All") # Connect-MgGraph -Scopes $scopes # Remove-AppRegistrationsAndDeletedItems -AppDisplayNamePattern "*graphapp-test*" #EndRegion '.\Public\Remove-AppRegistrationsAndDeletedItems.ps1' 39 #Region '.\Public\Remove-MGApplication-Run-InterActivefromConsole.ps1' -1 # # Import the module # Import-Module Microsoft.Graph.Applications # # Connect to Microsoft Graph # Connect-MgGraph -Scopes "Application.ReadWrite.All" # # Get and remove applications starting with 'GraphApp-Test001' # Get-MgApplication -Filter "startswith(displayName, 'GraphApp-Test001')" | ForEach-Object { # Remove-MgApplication -ApplicationId $_.Id -Confirm:$false # } # # Disconnect the session # Disconnect-MgGraph #EndRegion '.\Public\Remove-MGApplication-Run-InterActivefromConsole.ps1' 14 #Region '.\Public\Update-ApplicationPermissions.ps1' -1 # function Update-ApplicationPermissions { # param ( # [string]$appId, # [string]$permissionsFile # ) # $resourceAppId = "00000003-0000-0000-c000-000000000000" # Microsoft Graph # # Load permissions from the JSON file # if (Test-Path -Path $permissionsFile) { # $permissions = Get-Content -Path $permissionsFile | ConvertFrom-Json # } # else { # Write-EnhancedLog -Message "Permissions file not found: $permissionsFile" -Level "ERROR" # throw "Permissions file not found: $permissionsFile" # } # # Retrieve the existing application (optional, uncomment if needed) # # $app = Get-MgApplication -ApplicationId $appId # # Prepare the required resource access # $requiredResourceAccess = @( # @{ # ResourceAppId = $resourceAppId # ResourceAccess = $permissions # } # ) # # Update the application # try { # Update-MgApplication -ApplicationId $appId -RequiredResourceAccess $requiredResourceAccess # Write-EnhancedLog -Message "Successfully updated application permissions for appId: $appId" -Level "INFO" # } # catch { # Write-EnhancedLog -Message "Failed to update application permissions for appId: $appId. Error: $_" -Level "ERROR" # throw $_ # } # } # function Update-ApplicationPermissions { # param ( # [string]$appId, # [string]$permissionsFile # ) # $resourceAppId = "00000003-0000-0000-c000-000000000000" # Microsoft Graph # # Load permissions from the JSON file # if (Test-Path -Path $permissionsFile) { # $permissions = Get-Content -Path $permissionsFile | ConvertFrom-Json # } # else { # Write-EnhancedLog -Message "Permissions file not found: $permissionsFile" -Level "ERROR" # throw "Permissions file not found: $permissionsFile" # } # # Convert permissions to the required type # $resourceAccess = @() # foreach ($permission in $permissions) { # $resourceAccess += [Microsoft.Graph.PowerShell.Models.IMicrosoftGraphResourceAccess]@{ # Id = [Guid]$permission.Id # Type = $permission.Type # } # } # # Prepare the required resource access # $requiredResourceAccess = @( # [Microsoft.Graph.PowerShell.Models.IMicrosoftGraphRequiredResourceAccess]@{ # ResourceAppId = [Guid]$resourceAppId # ResourceAccess = $resourceAccess # } # ) # # Update the application # try { # Update-MgApplication -ApplicationId $appId -RequiredResourceAccess $requiredResourceAccess # Write-EnhancedLog -Message "Successfully updated application permissions for appId: $appId" -Level "INFO" # } # catch { # Write-EnhancedLog -Message "Failed to update application permissions for appId: $appId. Error: $_" -Level "ERROR" # throw $_ # Handle-Error -ErrorRecord $_ # } # } # function Update-ApplicationPermissions { # param ( # [string]$appId, # [string]$permissionsFile # ) # $resourceAppId = "00000003-0000-0000-c000-000000000000" # Microsoft Graph # # Load permissions from the JSON file # if (Test-Path -Path $permissionsFile) { # $permissions = Get-Content -Path $permissionsFile | ConvertFrom-Json # } # else { # Write-EnhancedLog -Message "Permissions file not found: $permissionsFile" -Level "ERROR" # throw "Permissions file not found: $permissionsFile" # } # # Convert permissions to the required type # $resourceAccess = @() # foreach ($permission in $permissions) { # if ($null -eq $permission.Id) { # Write-EnhancedLog -Message "Permission Id is null. Skipping this entry." -Level "WARNING" # continue # } # try { # $resourceAccess += [Microsoft.Graph.PowerShell.Models.IMicrosoftGraphResourceAccess]@{ # Id = [Guid]$permission.Id # Type = $permission.Type # } # } # catch { # Write-EnhancedLog -Message "Failed to convert permission Id: $($permission.Id). Error: $_" -Level "ERROR" # throw $_ # } # } # if ($resourceAccess.Count -eq 0) { # Write-EnhancedLog -Message "No valid permissions found to update the application." -Level "ERROR" # throw "No valid permissions found to update the application." # } # # Prepare the required resource access # $requiredResourceAccess = @( # [Microsoft.Graph.PowerShell.Models.IMicrosoftGraphRequiredResourceAccess]@{ # ResourceAppId = [Guid]$resourceAppId # ResourceAccess = $resourceAccess # } # ) # # Update the application # try { # Update-MgApplication -ApplicationId $appId -RequiredResourceAccess $requiredResourceAccess # Write-EnhancedLog -Message "Successfully updated application permissions for appId: $appId" -Level "INFO" # } # catch { # Write-EnhancedLog -Message "Failed to update application permissions for appId: $appId. Error: $_" -Level "ERROR" # throw $_ # Handle-Error -ErrorRecord $_ # } # } #EndRegion '.\Public\Update-ApplicationPermissions.ps1' 150 #Region '.\Public\Validate-AppCreation.ps1' -1 function Validate-AppCreation { param ( [string]$AppName, [string]$JsonPath ) # Call the function to run the script in its own instance of pwsh # Example usage # $jsonPath = "C:\path\to\your\jsonfile.json" # $appInfo = Get-AppInfoFromJson -jsonPath $jsonPath Write-EnhancedLog -Message "validating AppName $AppName from $JsonPath" try { # Import application objects from JSON using Get-AppInfoFromJson function $allApps = Get-AppInfoFromJson -jsonPath $JsonPath # Output the extracted data # $allApps | Format-Table -AutoSize # # List all applications # Write-EnhancedLog -Message "Listing all applications:" # $allApps | Format-Table Id, DisplayName, AppId, SignInAudience, PublisherDomain -AutoSize # Filter the applications to find the one with the specified display name $app = $allApps | Where-Object { $_.DisplayName -eq $AppName } # Debug output # Write-EnhancedLog -Message "Filtered applications count: $($app.Count)" if ($app.Count -eq 0) { Write-EnhancedLog -Message "No applications found with the name $AppName" } else { # Write-EnhancedLog -Message "Filtered applications details:" # $app | Format-Table Id, DisplayName, AppId, SignInAudience, PublisherDomain -AutoSize } # Log the parameters and the retrieved application object $params = @{ AppName = $AppName AppCount = ($app | Measure-Object).Count AppDetails = $app } Log-Params -Params $params # Check if the application object is not null and has items if ($null -ne $app -and ($app | Measure-Object).Count -gt 0) { Write-EnhancedLog -Message "Application found." return $true } Write-EnhancedLog -Message "Application not found." return $false } catch { Write-EnhancedLog -Message "An error occurred: $_" throw $_ } } #EndRegion '.\Public\Validate-AppCreation.ps1' 62 #Region '.\Public\Validate-AppCreationWithRetry.ps1' -1 function Validate-AppCreationWithRetry { param ( [Parameter(Mandatory = $true)] [string]$AppName, [Parameter(Mandatory = $true)] [string]$JsonPath ) $maxDuration = 120 # Maximum duration in seconds (2 minutes) $interval = 2 # Interval in seconds $elapsed = 0 # Elapsed time counter while ($elapsed -lt $maxDuration) { try { # Validate the app creation Write-EnhancedLog -Message 'second validation' Remove-AppListJson -jsonPath $jsonPath # Start-Sleep -Seconds 30 Run-DumpAppListToJSON -JsonPath $JsonPath $appExists = Validate-AppCreation -AppName $AppName -JsonPath $JsonPath if (-not $appExists) { Write-EnhancedLog -Message "App creation validation failed" -Level "ERROR" -ForegroundColor ([ConsoleColor]::Red) throw "App creation validation failed" } # If the app validation passes, exit the loop break } catch { Write-EnhancedLog -Message "An error occurred during app creation validation: $_" -Level "ERROR" -ForegroundColor ([ConsoleColor]::Red) Start-Sleep -Seconds $interval $elapsed += $interval } } if ($elapsed -ge $maxDuration) { Write-EnhancedLog -Message "App creation validation failed after multiple retries" -Level "ERROR" -ForegroundColor ([ConsoleColor]::Red) throw "App creation validation failed after multiple retries" } } #EndRegion '.\Public\Validate-AppCreationWithRetry.ps1' 41 #Region '.\Public\Validate-CertCreation.ps1' -1 function Validate-CertCreation { param ( [string]$Thumbprint, [string[]]$StoreLocations = @("Cert:\LocalMachine", "Cert:\CurrentUser") ) foreach ($storeLocation in $StoreLocations) { $cert = Get-ChildItem -Path "$storeLocation\My" | Where-Object { $_.Thumbprint -eq $Thumbprint } if ($null -ne $cert) { Write-EnhancedLog -Message "Certificate validated successfully in $storeLocation" -Level "INFO" -ForegroundColor ([ConsoleColor]::Cyan) return $cert } } Write-EnhancedLog -Message "Certificate validation failed" -Level "ERROR" -ForegroundColor ([ConsoleColor]::Red) throw "Certificate not found" Handle-Error -ErrorRecord $_ } #EndRegion '.\Public\Validate-CertCreation.ps1' 19 #Region '.\Public\Validate-Certificate.ps1' -1 function Validate-Certificate { param ( [Parameter(Mandatory = $true)] [string]$CertPath ) try { if (Test-Path -Path $CertPath) { Write-EnhancedLog -Message "Certificate path exists: $CertPath" -Level "INFO" -ForegroundColor ([ConsoleColor]::Green) return $true } else { Write-EnhancedLog -Message "Certificate path does not exist: $CertPath" -Level "WARNING" -ForegroundColor ([ConsoleColor]::Yellow) return $false } } catch { Write-EnhancedLog -Message "Error validating certificate path: $CertPath. Error: $_" -Level "ERROR" -ForegroundColor ([ConsoleColor]::Red) throw $_ } } #EndRegion '.\Public\Validate-Certificate.ps1' 21 #Region '.\Public\Validate-UriAccess.ps1' -1 function Validate-UriAccess { param ( [string]$uri, [hashtable]$headers ) Write-EnhancedLog -Message "Validating access to URI: $uri" -Level "INFO" try { $response = Invoke-WebRequest -Uri $uri -Headers $headers -Method Get if ($response.StatusCode -eq 200) { Write-EnhancedLog -Message "Access to $uri PASS" -Level "INFO" return $true } else { Write-EnhancedLog -Message "Access to $uri FAIL" -Level "ERROR" return $false } } catch { Write-EnhancedLog -Message "Access to $uri FAIL - $_" -Level "ERROR" return $false } } # function Validate-UriAccess { # param ( # [string]$uri, # [hashtable]$headers # ) # Write-EnhancedLog -Message "Validating access to URI: $uri" -Level "INFO" # # Initialize the HttpClient with a short timeout # $httpClient = [System.Net.Http.HttpClient]::new() # $httpClient.Timeout = [System.TimeSpan]::FromSeconds(10) # # Add headers to HttpClient # foreach ($key in $headers.Keys) { # $httpClient.DefaultRequestHeaders.Add($key, $headers[$key]) # } # try { # $response = $httpClient.GetAsync($uri).Result # if ($response.StatusCode -eq [System.Net.HttpStatusCode]::OK) { # Write-EnhancedLog -Message "Access to $uri PASS" -Level "INFO" # return $true # } else { # Write-EnhancedLog -Message "Access to $uri FAIL (StatusCode: $($response.StatusCode))" -Level "ERROR" # return $false # } # } catch { # Write-EnhancedLog -Message "Access to $uri FAIL - $_" -Level "ERROR" # return $false # } finally { # # Dispose the HttpClient to free resources # $httpClient.Dispose() # } # } # function Validate-UriAccess { # param ( # [string]$uri, # [hashtable]$headers # ) # Write-EnhancedLog -Message "Validating access to URI: $uri" -Level "INFO" # # Initialize the HttpClient with a short timeout # $httpClient = [System.Net.Http.HttpClient]::new() # $httpClient.Timeout = [System.TimeSpan]::FromSeconds(10) # try { # # Add headers to HttpClient # foreach ($key in $headers.Keys) { # if ($key -notin @('Content-Type', 'Content-Length', 'Content-Disposition')) { # $httpClient.DefaultRequestHeaders.Add($key, $headers[$key]) # } # } # $response = $httpClient.GetAsync($uri).Result # if ($response.StatusCode -eq [System.Net.HttpStatusCode]::OK) { # Write-EnhancedLog -Message "Access to $uri PASS" -Level "INFO" # return $true # } else { # Write-EnhancedLog -Message "Access to $uri FAIL (StatusCode: $($response.StatusCode))" -Level "ERROR" # return $false # } # } catch { # Write-EnhancedLog -Message "Access to $uri FAIL - $_" -Level "ERROR" # return $false # } finally { # # Dispose the HttpClient to free resources # $httpClient.Dispose() # } # } #EndRegion '.\Public\Validate-UriAccess.ps1' 101 |