Public/cloud-securitygroup.ps1
|
function Get-CloudSecurityGroup { <# .SYNOPSIS Returns security groups from the Cloud Server. .DESCRIPTION Retrieves a list of security groups. Automatically handles token refresh. .PARAMETER Name Optional. Filter by security group name. .EXAMPLE # List all security groups Get-CloudSecurityGroup .EXAMPLE # List security groups matching a name string Get-CloudSecurityGroup -Name "WebServers" .EXAMPLE # Get a specific security group by ID Get-CloudSecurityGroup -ID 561 #> [CmdletBinding()] param( [Parameter(Mandatory = $false)] [string]$Name, [Parameter(Mandatory = $false)] [int]$ID ) # Build the URI - adjust this to match your actual API endpoint $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/security-group" # Use the helper function which handles token refresh automatically $response = Invoke-CloudApiRequest -Uri $uri -Method Get # Extract security groups from the response $securitygroups = $response.security_group # Filter by name if specified if ($Name) { $securitygroups = $securitygroups | Where-Object { $_.name -like "*$Name*" } } # Filter by ID if specified - use PSBoundParameters to check if parameter was provided elseif ($PSBoundParameters.ContainsKey('ID')) { $securitygroups = $securitygroups | Where-Object { ($_.id -eq $ID) -and ($null -ne $_.id) } } return $securitygroups } function New-CloudSecurityGroup { <# .SYNOPSIS Creates a new security group on the Cloud Server. .DESCRIPTION Creates a new security group with specified name, description, and rules. Automatically handles token refresh. .PARAMETER Name Required. Name of the new security group. .PARAMETER Description Optional. Description for the security group. .PARAMETER Rules Optional. Array of rule hashtables. Each rule should contain: - Protocol: ALL, TCP, UDP, ICMP, ICMPV6, IPSEC - RuleType: INBOUND, OUTBOUND - IP: Optional IP address (e.g., "192.168.1.0") - Size: Optional network size (e.g., "24") - Range: Optional port range (e.g., "80:80", "1000:2000") - IcmpType: Optional ICMP type for ICMP protocol .EXAMPLE # Create basic security group New-CloudSecurityGroup -Name "WebServer-SG" -Description "Security group for web servers" .EXAMPLE # Create security group with HTTP and HTTPS rules $rules = @( @{ Protocol = "ALL"; RuleType = "OUTBOUND" } @{ Protocol = "TCP"; RuleType = "INBOUND"; Range = "80:80" } @{ Protocol = "TCP"; RuleType = "INBOUND"; Range = "443:443" } ) New-CloudSecurityGroup -Name "WebServer-SG" -Description "Web server access" -Rules $rules .EXAMPLE # Create security group allowing SSH from specific subnet $rules = @( @{ Protocol = "ALL"; RuleType = "OUTBOUND" } @{ Protocol = "TCP"; RuleType = "INBOUND"; Range = "22:22"; IP = "10.0.0.0"; Size = "24" } ) New-CloudSecurityGroup -Name "SSH-Admin-SG" -Description "SSH access from admin subnet" -Rules $rules .EXAMPLE # Create security group with ICMP ping allowed $rules = @( @{ Protocol = "ALL"; RuleType = "OUTBOUND" } @{ Protocol = "ICMP"; RuleType = "INBOUND"; IcmpType = "8" } ) New-CloudSecurityGroup -Name "Monitoring-SG" -Description "Allow ping for monitoring" -Rules $rules .EXAMPLE # Create security group with multiple port ranges $rules = @( @{ Protocol = "ALL"; RuleType = "OUTBOUND" } @{ Protocol = "TCP"; RuleType = "INBOUND"; Range = "80:80" } @{ Protocol = "TCP"; RuleType = "INBOUND"; Range = "443:443" } @{ Protocol = "TCP"; RuleType = "INBOUND"; Range = "8080:8090" } ) New-CloudSecurityGroup -Name "AppServer-SG" -Rules $rules #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string]$Name, [Parameter(Mandatory = $false)] [string]$Description, [Parameter(Mandatory = $false)] [array]$Rules ) # Build the template string $templateParts = @() # Name is required (no quotes) $templateParts += "NAME = $Name" # Add description if provided (with quotes) if ($PSBoundParameters.ContainsKey('Description')) { $templateParts += "DESCRIPTION = `"$Description`"" } # Add rules if specified if ($PSBoundParameters.ContainsKey('Rules') -and $Rules.Count -gt 0) { foreach ($rule in $Rules) { $ruleParts = @() # Protocol is required if ($rule.Protocol) { $ruleParts += "PROTOCOL = $($rule.Protocol)" } else { Write-Warning "Rule missing Protocol, skipping rule" continue } # Rule type is required if ($rule.RuleType) { $ruleParts += "RULE_TYPE = $($rule.RuleType)" } else { Write-Warning "Rule missing RuleType, skipping rule" continue } # Optional: IP address if ($rule.IP) { $ruleParts += "IP = `"$($rule.IP)`"" } # Optional: Network size if ($rule.Size) { $ruleParts += "SIZE = `"$($rule.Size)`"" } # Optional: Port range if ($rule.Range) { $ruleParts += "RANGE = `"$($rule.Range)`"" } # Optional: ICMP type if ($rule.IcmpType) { $ruleParts += "ICMP_TYPE = `"$($rule.IcmpType)`"" } $templateParts += "RULE = [ $($ruleParts -join ', ') ]" } } # Join all parts with newlines $templateString = $templateParts -join "`n" # Build the configuration - template goes in "data" field per API spec $config = [PSCustomObject]@{ template = $templateString } # Build the URI $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/security-group" Write-Verbose "Creating security group '$Name'" Write-Verbose "Request body: $($config | ConvertTo-Json -Compress)" Write-Verbose "Template:`n$templateString" try { # Use the helper function which handles token refresh automatically $response = Invoke-CloudApiRequest -Uri $uri -Method Post -Body $config Write-Host "Security Group '$Name' created successfully (ID: $($response.securitygroup))." -ForegroundColor Green return $response } catch { Write-Error "Failed to create security group: $_" throw } } function Update-CloudSecurityGroupOwner { <# .SYNOPSIS Updates the ownership of a security group in the Cloud Server. .DESCRIPTION Changes the user and/or group ownership of a security group. Prompts for confirmation. .PARAMETER ID Required. ID of the security group. .PARAMETER UserID Required. ID of the user to own the security group. .PARAMETER GroupID Optional. ID of the group to own the security group. .EXAMPLE # Change the ownership of a security group to a specific user Update-CloudSecurityGroupOwner -ID 5 -UserID 2 .EXAMPLE # Change the ownership of a security group to a specific user and group Update-CloudSecurityGroupOwner -ID 5 -UserID 2 -GroupID 100 .EXAMPLE # Change the ownership of a security group to a specific user, bypassing confirmation prompt Update-CloudSecurityGroupOwner -ID 5 -UserID 2 -Confirm:$false #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact='High')] param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [int]$ID, [Parameter(Mandatory = $true)] [Alias('User')] [int]$UserID, [Parameter(Mandatory = $false)] [Alias('Group')] [int]$GroupID ) process { # Build the update body $body = [PSCustomObject]@{ user = $UserID } if ($PSBoundParameters.ContainsKey('GroupID')) { $body | Add-Member -NotePropertyName 'group' -NotePropertyValue $GroupID } $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/security-group/${ID}/chown" # Build action description for confirmation $actionParts = @("Change owner to User ID $UserID") if ($PSBoundParameters.ContainsKey('GroupID')) { $actionParts += "Group ID $GroupID" } $actionDescription = $actionParts -join " and " write-verbose "Body data: $body" # Use the helper function Invoke-CloudResourceUpdate ` -CallerPSCmdlet $PSCmdlet ` -ResourceType "Security Group" ` -ID $ID ` -Uri $uri ` -Body $body ` -Action $actionDescription ` -GetResourceScript { Get-CloudSecurityGroup -ID $ID } ` -SuccessMessage "Security Group $ID ownership updated successfully." } } function Update-CloudSecurityGroupPermissions { <# .SYNOPSIS Updates the permissions of a security group in the Cloud Server. .DESCRIPTION Changes the permission of a security group. Prompts for confirmation. .PARAMETER ID Required. ID of the security group. .PARAMETER OwnerUse Optional. True or false, enable OwnerUse .PARAMETER OwnerManage Optional. True or false, enable OwnerManage .PARAMETER OwnerAdmin Optional. True or false, enable OwnerAdmin .PARAMETER GroupUse Optional. True or false, enable GroupUse .PARAMETER GroupManage Optional. True or false, enable GroupManage .PARAMETER GroupAdmin Optional. True or false, enable GroupAdmin .PARAMETER OtherUse Optional. True or false, enable OtherUse .PARAMETER OtherManage Optional. True or false, enable OtherManage .PARAMETER OtherAdmin Optional. True or false, enable OtherManage .EXAMPLE # Give group users permission to use the security group Update-CloudSecurityGroupPermissions -ID 35 -GroupUse $true .EXAMPLE # Deny group admin permission to the security group Update-CloudSecurityGroupPermissions -ID 35 -GroupAdmin $false .EXAMPLE # Set multiple permissions at once Update-CloudSecurityGroupPermissions -ID 35 -GroupUse $true -GroupManage $true -OtherUse $true #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact='High')] param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [int]$ID, [Parameter(Mandatory = $false)] [bool]$OwnerUse, [Parameter(Mandatory = $false)] [bool]$OwnerManage, [Parameter(Mandatory = $false)] [bool]$OwnerAdmin, [Parameter(Mandatory = $false)] [bool]$GroupUse, [Parameter(Mandatory = $false)] [bool]$GroupManage, [Parameter(Mandatory = $false)] [bool]$GroupAdmin, [Parameter(Mandatory = $false)] [bool]$OtherUse, [Parameter(Mandatory = $false)] [bool]$OtherManage, [Parameter(Mandatory = $false)] [bool]$OtherAdmin ) process { # Build the permissions object structure as shown in the API spec $permissions = @{} if ($PSBoundParameters.ContainsKey('OwnerUse')) { $permissions['owner_use'] = $OwnerUse } if ($PSBoundParameters.ContainsKey('OwnerManage')) { $permissions['owner_manage'] = $OwnerManage } if ($PSBoundParameters.ContainsKey('OwnerAdmin')) { $permissions['owner_admin'] = $OwnerAdmin } if ($PSBoundParameters.ContainsKey('GroupUse')) { $permissions['group_use'] = $GroupUse } if ($PSBoundParameters.ContainsKey('GroupManage')) { $permissions['group_manage'] = $GroupManage } if ($PSBoundParameters.ContainsKey('GroupAdmin')) { $permissions['group_admin'] = $GroupAdmin } if ($PSBoundParameters.ContainsKey('OtherUse')) { $permissions['other_use'] = $OtherUse } if ($PSBoundParameters.ContainsKey('OtherManage')) { $permissions['other_manage'] = $OtherManage } if ($PSBoundParameters.ContainsKey('OtherAdmin')) { $permissions['other_admin'] = $OtherAdmin } # Create the body with the permissions nested structure $body = @{ perms = $permissions } $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/security-group/${ID}/chmod" Invoke-CloudResourceUpdate ` -CallerPSCmdlet $PSCmdlet ` -ResourceType "Security Group" ` -ID $ID ` -Uri $uri ` -Body $body ` -Action "Update permissions" ` -GetResourceScript { Get-CloudSecurityGroup -ID $ID } } } function Rename-CloudSecurityGroup { <# .SYNOPSIS Renames a security group on Cloud Server. .DESCRIPTION Renames a security group. Automatically handles token refresh. .PARAMETER Name Required. New name for the security group. .PARAMETER ID Required. ID of the security group security group name. .EXAMPLE # Rename a security group Rename-CloudSecurityGroup -ID 561 -Name "Updated Security Group" #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string]$Name, [Parameter(Mandatory = $true)] [int]$ID ) $body = @{ name = $Name } # Build the URI - adjust this to match your actual API endpoint $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/security-group/${ID}/rename" # Use the helper function which handles token refresh automatically $response = Invoke-CloudApiRequest -Uri $uri -Method PATCH -body $body # Extract security groups from the response $securitygroup = $response.security_group write-host "Group $securitygroup renamed to $Name" } function Copy-CloudSecurityGroup { <# .SYNOPSIS Clone a security group in the Cloud Server. .DESCRIPTION Clones a security group. Automatically handles token refresh. .PARAMETER Name Required. Name of the new security group .PARAMETER ID Required. ID of the the security group you wish to clone .EXAMPLE # Clone the security group with ID 5 Copy-CloudSecurityGroup -Name "RemoteUsers" -ID 5 #> [CmdletBinding(DefaultParameterSetName='Individual')] param( [Parameter(Mandatory = $true)] [string]$Name, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName=$true)] [int]$ID ) $sgData = [PSCustomObject]@{ name=$Name } $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/security-group/${ID}/clone" Write-Verbose "Request URI: $uri" Write-Verbose "SecurityGroup:`n$sgData" $response = Invoke-CloudApiRequest -Uri $uri -Method POST -Body $sgData return $response } function Update-CloudSecurityGroup { <# .SYNOPSIS Updates a security group on the Cloud Server. .DESCRIPTION Updates a security group's configuration including name, description, and rules. You can choose to merge with the existing configuration or replace it entirely. Merge is enabled by default. Automatically handles token refresh. .PARAMETER ID Required. ID of the security group to update. .PARAMETER Name Optional. New name for the security group. .PARAMETER Description Optional. Description for the security group. .PARAMETER Rules Optional. Array of rule hashtables. Each rule should contain: - Protocol: ALL, TCP, UDP, ICMP, ICMPV6, IPSEC - RuleType: INBOUND, OUTBOUND - IP: Optional IP address (e.g., "192.168.1.0") - Size: Optional network size (e.g., "24") - Range: Optional port range (e.g., "80:80", "1000:2000") - IcmpType: Optional ICMP type for ICMP protocol .PARAMETER Merge Optional. If true (default), merges with existing configuration. If false, replaces entirely. Use -Merge:$false to completely replace the security group configuration. .EXAMPLE # Update security group description Update-CloudSecurityGroup -ID 0 -Description "Updated default security group" .EXAMPLE # Add HTTP and HTTPS inbound rules $rules = @( @{ Protocol = "TCP"; RuleType = "INBOUND"; Range = "80:80" } @{ Protocol = "TCP"; RuleType = "INBOUND"; Range = "443:443" } ) Update-CloudSecurityGroup -ID 100 -Rules $rules .EXAMPLE # Allow all traffic from specific subnet $rules = @( @{ Protocol = "ALL"; RuleType = "INBOUND"; IP = "10.0.0.0"; Size = "24" } ) Update-CloudSecurityGroup -ID 100 -Rules $rules .EXAMPLE # Replace entire security group configuration $rules = @( @{ Protocol = "ALL"; RuleType = "OUTBOUND" } @{ Protocol = "TCP"; RuleType = "INBOUND"; Range = "22:22" } ) Update-CloudSecurityGroup -ID 100 -Name "SSH-Only" -Description "SSH access only" -Rules $rules -Merge:$false .EXAMPLE # Allow ICMP ping $rules = @( @{ Protocol = "ICMP"; RuleType = "INBOUND"; IcmpType = "8" } ) Update-CloudSecurityGroup -ID 100 -Rules $rules .EXAMPLE # Update without confirmation Update-CloudSecurityGroup -ID 100 -Description "New description" -Confirm:$false #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact='High')] param( [Parameter(Mandatory = $true)] [int]$ID, [Parameter(Mandatory = $false)] [string]$Name, [Parameter(Mandatory = $false)] [string]$Description, [Parameter(Mandatory = $false)] [array]$Rules, [Parameter()] [bool]$Merge = $true ) # Build the template string - only include specified parameters $templateParts = @() # Only add parameters that were actually specified if ($PSBoundParameters.ContainsKey('Name')) { $templateParts += "NAME = `"$Name`"" } if ($PSBoundParameters.ContainsKey('Description')) { $templateParts += "DESCRIPTION = `"$Description`"" } # Add rules if specified foreach ($rule in $Rules) { $ruleParts = @() # Protocol is required if ($rule.Protocol) { $ruleParts += "PROTOCOL = $($rule.Protocol)" } else { Write-Warning "Rule missing Protocol, skipping rule" continue } # Rule type is required if ($rule.RuleType) { $ruleParts += "RULE_TYPE = $($rule.RuleType)" } else { Write-Warning "Rule missing RuleType, skipping rule" continue } # Optional: IP address if ($rule.IP) { $ruleParts += "IP = `"$($rule.IP)`"" } # Optional: Network size if ($rule.Size) { $ruleParts += "SIZE = `"$($rule.Size)`"" } # Optional: Port range if ($rule.Range) { $ruleParts += "RANGE = `"$($rule.Range)`"" } # Optional: ICMP type if ($rule.IcmpType) { $ruleParts += "ICMP_TYPE = `"$($rule.IcmpType)`"" } $templateParts += "RULE = [ $($ruleParts -join ', ') ]" } # Only proceed if there are changes to make if ($templateParts.Count -eq 0) { Write-Warning "No parameters specified for update. Please specify at least one parameter to update." return } # Join all parts with newlines $templateString = $templateParts -join "`n" # Build the request body $body = @{ merge = $Merge template = $templateString } # Build the URI $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/security-group/${ID}" Write-Verbose "Request URI: $uri" Write-Verbose "Merge: $Merge" Write-Verbose "Template:`n$templateString" try { Invoke-CloudResourceUpdate ` -CallerPSCmdlet $PSCmdlet ` -ResourceType "Security Group" ` -ID $ID ` -Uri $uri ` -Body $body ` -Action "Update" ` -GetResourceScript { Get-CloudSecurityGroup -ID $ID } Write-Verbose "Successfully updated security group ID: $ID" } catch { Write-Error "Failed to update security group '$ID': $_" throw } } function Invoke-CloudSecurityGroup { <# .SYNOPSIS Commit security group changes to associated VMs on the Cloud server. .DESCRIPTION Commit security group changes to associated VMs. Automatically handles token refresh. .PARAMETER ID Required. ID of the the security group you wish to commit .EXAMPLE # Clone the security group with ID 5 and prompt for confirmation Invoke-CloudSecurityGroup -ID 5 .EXAMPLE # Clone the security group with ID 5 and bypass confirmation Invoke-CloudSecurityGroup -ID 5 -confirm:$false #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact='High')] param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName=$true)] [int]$ID ) $body = [PSCustomObject]@{ all=$True } $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/security-group/${ID}/commit" try { Invoke-CloudResourceUpdate ` -CallerPSCmdlet $PSCmdlet ` -ResourceType "Security Group" ` -ID $ID ` -Uri $uri ` -Body $body ` -Action "Commit" ` -GetResourceScript { Get-CloudSecurityGroup -ID $ID } Write-Verbose "Successfully updated security group ID: $ID" } catch { Write-Error "Failed to commit security group '$ID': $_" throw } } function Remove-CloudSecurityGroup { <# .SYNOPSIS Removes a security group from the Cloud Server. .DESCRIPTION Removes a security group. Automatically handles token refresh. .PARAMETER ID Required. Security group ID. .EXAMPLE # Remove security group with confirmation prompt (default behavior): Remove-CloudSecurityGroup -ID 5 Confirm Are you sure you want to perform this action? Performing the operation "Remove Security Group" on target "Security group 5". [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"): Y .EXAMPLE # Remove security group without confirmation prompt: Remove-CloudSecurityGroup -ID 5 -Confirm:$false #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact='High')] param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [int]$ID ) process { $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/security-group/${ID}" Invoke-CloudResourceRemoval ` -CallerPSCmdlet $PSCmdlet ` -ResourceType "Security group" ` -ID $ID ` -Uri $uri ` -GetResourceScript { Get-CloudSecurityGroup -ID $ID } } } |