forked from KelvinTegelaar/CIPP-API
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'KelvinTegelaar:master' into master
- Loading branch information
Showing
9 changed files
with
325 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
#requires -Version 7.2 | ||
|
||
[CmdletBinding(DefaultParameterSetName = 'interactive')] | ||
Param( | ||
[Parameter(Mandatory = $true, ParameterSetName = 'noninteractive')] | ||
[ValidateSet('readonly', 'editor', 'admin')] | ||
$Role, | ||
[Parameter(Mandatory = $true, ParameterSetName = 'noninteractive')] | ||
$SelectedUsers, | ||
[Parameter(ParameterSetName = 'noninteractive')] | ||
[Parameter(ParameterSetName = 'interactive')] | ||
$ExpirationHours = 1 | ||
) | ||
|
||
$ResourceGroup = '##RESOURCEGROUP##' | ||
$Subscription = '##SUBSCRIPTION##' | ||
|
||
if (!(Get-Module -ListAvailable Microsoft.PowerShell.ConsoleGuiTools)) { | ||
Install-Module Microsoft.PowerShell.ConsoleGuiTools -Force | ||
} | ||
|
||
$Context = Get-AzContext | ||
if (!$Context) { | ||
Write-Host "`n- Connecting to Azure" | ||
$Context = Connect-AzAccount -Subscription $Subscription | ||
} | ||
Write-Host "Connected to $($Context.Account)" | ||
|
||
$swa = Get-AzStaticWebApp -ResourceGroupName $ResourceGroup | ||
$Domain = $swa.CustomDomain | Select-Object -First 1 | ||
if ($Domain -eq $null) { $Domain = $swa.DefaultHostname } | ||
Write-Host "CIPP SWA - $($swa.name)" | ||
|
||
if (!$Role) { | ||
$Role = @('readonly', 'editor', 'admin') | Out-ConsoleGridView -OutputMode Single -Title 'Select CIPP Role' | ||
} | ||
|
||
$CurrentUsers = Get-AzStaticWebAppUser -Name $swa.name -ResourceGroupName $ResourceGroup -AuthProvider all | Select-Object DisplayName, Role | ||
|
||
$AllUsers = Get-AzADUser -Filter "userType eq 'Member' and accountEnabled eq true" | Select-Object DisplayName, UserPrincipalName | ||
|
||
|
||
$SelectedUsers = $AllUsers | Where-Object { $CurrentUsers.DisplayName -notcontains $_.UserPrincipalName } | Sort-Object -Property DisplayName | Out-ConsoleGridView -Title "Select users for role '$Role'" | ||
Write-Host "Selected users: $($SelectedUsers.UserPrincipalName -join ', ')" | ||
|
||
Write-Host 'Generating invite links...' | ||
$InviteList = foreach ($User in $SelectedUsers) { | ||
$UserInvite = @{ | ||
InputObject = $swa | ||
Domain = $Domain | ||
Provider = 'aad' | ||
UserDetail = $User.UserPrincipalName | ||
Role = $Role | ||
NumHoursToExpiration = $ExpirationHours | ||
} | ||
$Invite = New-AzStaticWebAppUserRoleInvitationLink @UserInvite | ||
|
||
[PSCustomObject]@{ | ||
User = $User.UserPrincipalName | ||
Role = $Role | ||
Link = $Invite.InvitationUrl | ||
Expires = $Invite.ExpiresOn | ||
} | ||
} | ||
$InviteList | ||
$InviteList | Export-Csv -Path '.\cipp-invites.csv' -Append | ||
Write-Host 'Invitations exported to .\cipp-invites.csv' |
38 changes: 38 additions & 0 deletions
38
ExecMaintenanceScripts/Scripts/Enable-FunctionAppGitHubActions.ps1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
$ResourceGroup = '##RESOURCEGROUP##' | ||
$Subscription = '##SUBSCRIPTION##' | ||
$FunctionName = '##FUNCTIONAPP##' | ||
|
||
$Logo = @' | ||
_____ _____ _____ _____ | ||
/ ____|_ _| __ \| __ \ | ||
| | | | | |__) | |__) | | ||
| | | | | ___/| ___/ | ||
| |____ _| |_| | | | | ||
\_____|_____|_| |_| | ||
'@ | ||
Write-Host $Logo | ||
|
||
Write-Host '- Connecting to Azure' | ||
Connect-AzAccount -Identity -Subscription $Subscription | Out-Null | ||
|
||
Write-Host 'Checking deployment settings' | ||
$DeploymentSettings = & az functionapp deployment source show --resource-group $ResourceGroup --name $FunctionName | ConvertFrom-Json | ||
|
||
if (!($DeploymentSettings.isGitHubAction)) { | ||
Write-Host 'Creating GitHub action, follow the prompts to log into GitHub' | ||
$GitHubRepo = ([uri]$DeploymentSettings.repoUrl).LocalPath.TrimStart('/') | ||
az functionapp deployment github-actions add --repo $GitHubRepo --branch $DeploymentSettings.branch --resource-group $ResourceGroup --name $FunctionName --login-with-github | ||
} | ||
|
||
$DeploymentSettings = & az functionapp deployment source show --resource-group $ResourceGroup --name $FunctionName | ConvertFrom-Json | ||
if ($DeploymentSettings.isGitHubAction) { | ||
$cipp = Get-AzFunctionApp -ResourceGroupName $ResourceGroup | ||
$cipp.ApplicationSettings['WEBSITE_RUN_FROM_PACKAGE'] = 1 | ||
$cipp | Update-AzFunctionAppSetting -AppSetting $cipp.ApplicationSettings | ||
|
||
Write-Host "GitHub action created and project set to run from package, navigate to $($DeploymentSettings.repoUrl)/actions and run the 'Build and deploy Powershell project to Azure Function App'" | ||
} | ||
else { | ||
Write-Host 'GitHub action not set up for deployment, try running the script again.' | ||
} |
122 changes: 122 additions & 0 deletions
122
ExecMaintenanceScripts/Scripts/Grant-CippConditionalAccess.ps1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
if (!(Get-Module -ListAvailable Microsoft.Graph)) { | ||
Install-Module Microsoft.Graph -Confirm:$false -Force -AllowPrerelease | ||
} | ||
|
||
$ResourceGroup = '##RESOURCEGROUP##' | ||
$Subscription = '##SUBSCRIPTION##' | ||
$FunctionName = '##FUNCTIONAPP##' | ||
$TokenIP = '##TOKENIP##' | ||
|
||
$Logo = @' | ||
_____ _____ _____ _____ | ||
/ ____|_ _| __ \| __ \ | ||
| | | | | |__) | |__) | | ||
| | | | | ___/| ___/ | ||
| |____ _| |_| | | | | ||
\_____|_____|_| |_| | ||
'@ | ||
Write-Host $Logo | ||
|
||
Write-Host '=== Conditional Access Management ===' | ||
if (Test-Path -Path '.\cipp-function-namedLocation.json') { | ||
$UseCache = Read-Host -Prompt 'Used cached Named Location for CIPP? (Y/n)' | ||
if ($UseCache -ne 'n') { | ||
$ipNamedLocation = Get-Content -Path '.\cipp-function-namedLocation.json' | ConvertFrom-Json -AsHashtable | ||
} | ||
} | ||
|
||
if (!($ipNamedLocation)) { | ||
Write-Host "`n- Connecting to Azure" | ||
Connect-AzAccount -Identity -Subscription $Subscription | Out-Null | ||
$Function = Get-AzFunctionApp -ResourceGroupName $ResourceGroup -Name $FunctionName | ||
|
||
Write-Host 'Getting Function App IP addresses' | ||
# Get possible IPs from function app | ||
$PossibleIpAddresses = (($Function | Select-Object -ExpandProperty PossibleOutboundIpAddress) + ',' + $TokenIP) -split ',' | ||
|
||
# Convert possible IP addresses to ipv4CidrRange list | ||
$ipRanges = foreach ($Ip in $PossibleIpAddresses) { | ||
$Cidr = '{0}/32' -f $Ip | ||
@{ | ||
'@odata.type' = '#microsoft.graph.iPv4CidrRange' | ||
'cidrAddress' = $Cidr | ||
} | ||
} | ||
|
||
# Return ipNamedLocation object | ||
$ipNamedLocation = @{ | ||
'@odata.type' = '#microsoft.graph.ipNamedLocation' | ||
displayName = ('CyberDrain Improved Partner Portal - {0}' -f $FunctionName) | ||
isTrusted = $true | ||
ipRanges = $ipRanges | ||
} | ||
|
||
$ipNamedLocation | ConvertTo-Json -Depth 10 | Out-File -Path '.\cipp-function-namedLocation.json' | ||
Write-Host 'Named location policy created and saved to .\cipp-function-namedLocation.json' | ||
} | ||
|
||
Write-Host "`n- Connecting to Customer Graph API, ensure you log in from a system that is allowed through the Conditional Access policy" | ||
Select-MgProfile -Name 'beta' | ||
$GraphOptions = @{ | ||
Scopes = @('Policy.Read.All', 'Policy.ReadWrite.ConditionalAccess', 'Application.Read.All') | ||
UseDeviceAuthentication = $true | ||
} | ||
|
||
do { | ||
Connect-MgGraph @GraphOptions | ||
$Context = Get-MgContext | ||
if ($Context) { | ||
Write-Host "Connected as $($Context.Account) ($($Context.TenantId))" | ||
$Switch = Read-Host -Prompt 'Switch Accounts? (y/N)' | ||
if ($Switch -eq 'y') { | ||
Disconnect-MgGraph | Out-Null | ||
} | ||
} | ||
} | ||
while (!(Get-MgContext)) | ||
|
||
Write-Host "`n- Getting existing policies" | ||
$Policies = Get-MgIdentityConditionalAccessPolicy | ||
Write-Host($Policies.displayName -join "`n") | ||
|
||
Write-Host "`n- Named Location Check" | ||
$NamedLocations = Get-MgIdentityConditionalAccessNamedLocation | ||
if ($NamedLocations.displayName -notcontains $ipNamedLocation.displayName) { | ||
Write-Host "Creating Named Location: '$($ipNamedLocation.displayName)'" | ||
$NamedLocation = New-MgIdentityConditionalAccessNamedLocation -BodyParameter $ipNamedLocation | ||
} | ||
else { | ||
$NamedLocation = $NamedLocations | Where-Object { $_.displayName -eq $ipNamedLocation.displayName } | ||
Write-Host "Named Location exists: '$($NamedLocation.displayName)'" | ||
Update-MgIdentityConditionalAccessNamedLocation -NamedLocationId $NamedLocation.Id -BodyParameter $ipNamedLocation | ||
} | ||
|
||
Write-Host "`n- Conditional access policy check" | ||
$ConfigPolicy = Read-Host -Prompt 'Exclude CIPP from existing CA policies? (Y/n)' | ||
if ($ConfigPolicy -ne 'n') { | ||
foreach ($Policy in $Policies) { | ||
Write-Host "- Policy: $($Policy.displayName)" | ||
$Conditions = $Policy.Conditions | ||
$ExcludeLocations = $Conditions.Locations.ExcludeLocations | ||
$IncludeLocations = $Conditions.Locations.IncludeLocations | ||
if ($ExcludeLocations -eq 'AllTrusted' -or $ExcludeLocations -contains $NamedLocation.Id) { | ||
Write-Host 'Named location already excluded' | ||
} | ||
elseif ($IncludeLocations -eq 'AllTrusted' -or $IncludeLocations -contains $NamedLocation.Id) { | ||
Write-Host 'Named location is already included' | ||
} | ||
else { | ||
Write-Host 'Adding exclusion for named location' | ||
$Locations = [system.collections.generic.list[string]]::new() | ||
foreach ($Location in $ExcludeLocations) { | ||
$Locations.Add($Location) | Out-Null | ||
} | ||
$Locations.Add($NamedLocation.Id) | Out-Null | ||
$Conditions.Locations.ExcludeLocations = [string[]]$Locations | ||
if (!($Conditions.Locations.IncludeLocations)) { $Conditions.Locations.IncludeLocations = 'All' } | ||
Update-MgIdentityConditionalAccessPolicy -ConditionalAccessPolicyId $Policy.Id -Conditions $Conditions | ||
} | ||
} | ||
Write-Host "`nDone." | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
{ | ||
"bindings": [ | ||
{ | ||
"name": "QueueItem", | ||
"type": "queueTrigger", | ||
"direction": "in", | ||
"queueName": "scheduledcommandprocessor" | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
# Input bindings are passed in via param block. | ||
param($QueueItem, $TriggerMetadata) | ||
|
||
$Table = Get-CippTable -tablename 'ScheduledTasks' | ||
$task = $QueueItem.TaskInfo | ||
$commandParameters = $QueueItem.Parameters | ||
|
||
$tenant = $QueueItem.Parameters['TenantFilter'] | ||
Write-Host 'started task' | ||
try { | ||
try { | ||
$results = & $QueueItem.command @commandParameters | ||
} | ||
catch { | ||
$results = "Task Failed: $($_.Exception.Message)" | ||
|
||
} | ||
|
||
Write-Host 'ran the command' | ||
if ($results -is [String]) { | ||
$results = @{ Results = $results } | ||
} | ||
if ($results -is [array]) { | ||
$results = $results | Where-Object { $_ -is [string] } | ||
$results = $results | ForEach-Object { @{ Results = $_ } } | ||
} | ||
|
||
$results = $results | Select-Object * -ExcludeProperty RowKey, PartitionKey | ||
|
||
$StoredResults = $results | ConvertTo-Json -Compress -Depth 20 | Out-String | ||
if ($StoredResults.Length -gt 64000 -or $task.Tenant -eq 'AllTenants') { | ||
$StoredResults = @{ Results = 'The results for this query are too long to store in this table, or the query was meant for All Tenants. Please use the options to send the results to another target to be able to view the results. ' } | ConvertTo-Json -Compress | ||
} | ||
} | ||
catch { | ||
$errorMessage = $_.Exception.Message | ||
if ($task.Recurrence -gt 0) { $State = 'Failed - Planned' } else { $State = 'Failed' } | ||
Update-AzDataTableEntity @Table -Entity @{ | ||
PartitionKey = $task.PartitionKey | ||
RowKey = $task.RowKey | ||
Results = "$errorMessage" | ||
TaskState = $State | ||
} | ||
Write-LogMessage -API 'Scheduler_UserTasks' -tenant $tenant -message "Failed to execute task $($task.Name): $errorMessage" -sev Error | ||
} | ||
|
||
|
||
$TableDesign = '<style>table.blueTable{border:1px solid #1C6EA4;background-color:#EEE;width:100%;text-align:left;border-collapse:collapse}table.blueTable td,table.blueTable th{border:1px solid #AAA;padding:3px 2px}table.blueTable tbody td{font-size:13px}table.blueTable tr:nth-child(even){background:#D0E4F5}table.blueTable thead{background:#1C6EA4;background:-moz-linear-gradient(top,#5592bb 0,#327cad 66%,#1C6EA4 100%);background:-webkit-linear-gradient(top,#5592bb 0,#327cad 66%,#1C6EA4 100%);background:linear-gradient(to bottom,#5592bb 0,#327cad 66%,#1C6EA4 100%);border-bottom:2px solid #444}table.blueTable thead th{font-size:15px;font-weight:700;color:#FFF;border-left:2px solid #D0E4F5}table.blueTable thead th:first-child{border-left:none}table.blueTable tfoot{font-size:14px;font-weight:700;color:#FFF;background:#D0E4F5;background:-moz-linear-gradient(top,#dcebf7 0,#d4e6f6 66%,#D0E4F5 100%);background:-webkit-linear-gradient(top,#dcebf7 0,#d4e6f6 66%,#D0E4F5 100%);background:linear-gradient(to bottom,#dcebf7 0,#d4e6f6 66%,#D0E4F5 100%);border-top:2px solid #444}table.blueTable tfoot td{font-size:14px}table.blueTable tfoot .links{text-align:right}table.blueTable tfoot .links a{display:inline-block;background:#1C6EA4;color:#FFF;padding:2px 8px;border-radius:5px}</style>' | ||
$HTML = ($results | Select-Object * -ExcludeProperty RowKey, PartitionKey | ConvertTo-Html -Fragment) -replace '<table>', "$TableDesign<table class=blueTable>" | Out-String | ||
$title = "Scheduled Task $($task.Name) - $($task.ExpectedRunTime)" | ||
Write-Host $title | ||
switch -wildcard ($task.PostExecution) { | ||
'*psa*' { Send-CIPPAlert -Type 'psa' -Title $title -HTMLContent $HTML } | ||
'*email*' { Send-CIPPAlert -Type 'email' -Title $title -HTMLContent $HTML } | ||
'*webhook*' { | ||
$Webhook = [PSCustomObject]@{ | ||
'Tenant' = $tenant | ||
'TaskInfo' = $QueueItem.TaskInfo | ||
'Results' = $Results | ||
} | ||
Send-CIPPAlert -Type 'webhook' -Title $title -JSONContent $($Webhook | ConvertTo-Json -Depth 20) | ||
} | ||
} | ||
|
||
Write-Host 'ran the command' | ||
|
||
if ($task.Recurrence -le '0' -or $task.Recurrence -eq $null) { | ||
Update-AzDataTableEntity @Table -Entity @{ | ||
PartitionKey = $task.PartitionKey | ||
RowKey = $task.RowKey | ||
Results = "$StoredResults" | ||
TaskState = 'Completed' | ||
} | ||
} | ||
else { | ||
$nextRun = (Get-Date).AddDays($task.Recurrence) | ||
$nextRunUnixTime = [int64]($nextRun - (Get-Date '1/1/1970')).TotalSeconds | ||
Update-AzDataTableEntity @Table -Entity @{ | ||
PartitionKey = $task.PartitionKey | ||
RowKey = $task.RowKey | ||
Results = "$StoredResults" | ||
TaskState = 'Planned' | ||
ScheduledTime = "$nextRunUnixTime" | ||
} | ||
} | ||
Write-LogMessage -API 'Scheduler_UserTasks' -tenant $tenant -message "Successfully executed task: $($task.name)" -sev Info |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
4.7.3 | ||
4.7.4 |