IdentityCommand.SecureAI.psm1
|
function Get-SAIApiHeader { <# .SYNOPSIS Returns the Accept header value for a Secure AI resource. .DESCRIPTION Every Secure AI endpoint is a Beta API and requires an explicit Accept header naming the resource it belongs to; a request without it, or with the wrong one, is refused with 406 Not Acceptable. The three values are held here so the commands do not each carry a copy. Pass the returned value to Invoke-IDRestMethod's -Accept parameter. .PARAMETER Resource The resource the request addresses - agents, targets or policies. .EXAMPLE Invoke-IDRestMethod -Uri $URI -Method GET -Accept $(Get-SAIApiHeader -Resource Agents) .OUTPUTS String #> [CmdletBinding()] [OutputType([string])] param( [parameter( Mandatory = $true, Position = 0 )] [ValidateSet('Agents', 'Targets', 'Policies')] [string]$Resource ) switch ($Resource) { 'Agents' { 'application/x.agents.beta+json' } 'Targets' { 'application/x.targets.beta+json' } 'Policies' { 'application/x.policies.beta+json' } } } # .ExternalHelp IdentityCommand.SecureAI-help.xml function Connect-SAITenant { [CmdletBinding(SupportsShouldProcess, DefaultParameterSetName = 'Subdomain')] param( #subdomain [parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'Subdomain')] [parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'SubdomainCredential')] [parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'SubdomainSAML')] [ValidateNotNullOrEmpty()] [Alias('subdomain')] [String]$tenant_subdomain, #tenant_url [parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'URL')] [parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'URLCredential')] [parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'URLSAML')] [ValidateNotNullOrEmpty()] [Alias('aigw_url')] [String]$tenant_url, #Credential used to authenticate to CyberArk Identity. Authentication is performed even if an active IdentityCommand session is found, replacing it [parameter(Mandatory = $true, ParameterSetName = 'SubdomainCredential')] [parameter(Mandatory = $true, ParameterSetName = 'URLCredential')] [ValidateNotNullOrEmpty()] [PSCredential]$Credential, #Authenticate as a service user via New-IDPlatformToken (OAuth client_credentials) instead of the interactive New-IDSession [parameter(ParameterSetName = 'SubdomainCredential')] [parameter(ParameterSetName = 'URLCredential')] [Switch]$PlatformToken, #SAML assertion used to authenticate to CyberArk Identity. Authentication is performed even if an active IdentityCommand session is found, replacing it [parameter(Mandatory = $true, ParameterSetName = 'SubdomainSAML')] [parameter(Mandatory = $true, ParameterSetName = 'URLSAML')] [ValidateNotNullOrEmpty()] [String]$SAMLResponse ) begin { $IDSession = Get-IDSession $HaveSession = $null -ne $IDSession.tenant_url $AuthRequested = $PSBoundParameters.ContainsKey('Credential') -or $PSBoundParameters.ContainsKey('SAMLResponse') if ($HaveSession -and $AuthRequested) { Write-Verbose 'Authentication parameters were supplied; authenticating and replacing the existing IdentityCommand session' } }#begin process { $UsingSubdomain = $PSCmdlet.ParameterSetName -like 'Subdomain*' #Resolve service URLs from platform discovery when a subdomain was supplied, or when #authentication is required and the CyberArk Identity URL must be discovered. $ServiceUrl = $null if ($UsingSubdomain) { $ServiceUrl = Resolve-ServiceUrl -Service aigw -Subdomain $tenant_subdomain $tenant_url = $ServiceUrl.ServiceUrl } else { #Ensure URL is in expected format - remove trailing slash if provided in Url $tenant_url = $tenant_url -replace '/$', '' if ($AuthRequested) { $ServiceUrl = Resolve-ServiceUrl -Service aigw -Url $tenant_url } } if ($AuthRequested -or (-not $HaveSession)) { if (-not $AuthRequested) { throw 'Authenticate with New-IDSession or New-IDPlatformToken, or supply -Credential, and try again' } $IdentityUrl = $ServiceUrl.IdentityUrl if ($PSCmdlet.ShouldProcess($IdentityUrl, 'Authenticate to CyberArk Identity')) { if ($PSCmdlet.ParameterSetName -like '*SAML') { $null = New-IDSession -tenant_url $IdentityUrl -SAMLResponse $SAMLResponse } elseif ($PlatformToken) { $null = New-IDPlatformToken -tenant_url $IdentityUrl -Credential $Credential } else { $null = New-IDSession -tenant_url $IdentityUrl -Credential $Credential } $IDSession = Get-IDSession } } #Make the CyberArk Identity Session available in the IdentityCommand.SecureAI scope foreach ($key in $IDSession.keys) { if ($null -ne $IDSession[$key]) { $ISPSSSession[$key] = $IDSession[$key] } } #Set the Access Requests URL in the session data $ISPSSSession.tenant_url = $tenant_url }#process end { }#end } # .ExternalHelp IdentityCommand.SecureAI-help.xml function Get-SAIAgent { [CmdletBinding(DefaultParameterSetName = 'All')] param( [parameter( Mandatory = $true, ValueFromPipelinebyPropertyName = $true, ParameterSetName = 'byId' )] [ValidateLength(1, 128)] [Alias('id')] [String]$agentId ) begin { }#begin process { $URI = "$($ISPSSSession.tenant_url)/api/agents" if ($PSCmdlet.ParameterSetName -eq 'byId') { $URI = "$URI/$agentId" #Send Request Invoke-IDRestMethod -Uri $URI -Method GET -Accept $(Get-SAIApiHeader -Resource Agents) } else { #Send Request $result = Invoke-IDRestMethod -Uri $URI -Method GET -Accept $(Get-SAIApiHeader -Resource Agents) if ($null -ne $result) { $result.agents } } }#process end { }#end } # .ExternalHelp IdentityCommand.SecureAI-help.xml function Get-SAIMcpServer { [CmdletBinding(DefaultParameterSetName = 'All')] param( [parameter( Mandatory = $true, ValueFromPipelinebyPropertyName = $true, ParameterSetName = 'byId' )] [ValidateNotNullOrEmpty()] [Alias('id')] [String]$mcpServerId, [parameter( Mandatory = $false, ValueFromPipelinebyPropertyName = $true, ParameterSetName = 'All' )] [ValidateRange(1, 2147483647)] [int]$pageSize ) begin { }#begin process { if ($PSCmdlet.ParameterSetName -eq 'byId') { $URI = "$($ISPSSSession.tenant_url)/api/targets/mcp-servers/$mcpServerId" #Send Request Invoke-IDRestMethod -Uri $URI -Method GET -Accept $(Get-SAIApiHeader -Resource Targets) } else { $URI = "$($ISPSSSession.tenant_url)/api/targets/mcp-servers" $URI = Add-QueryString -URI $URI -Parameter ($PSBoundParameters | Get-Parameter) #Send Request $result = Invoke-IDRestMethod -Uri $URI -Method GET -Accept $(Get-SAIApiHeader -Resource Targets) if ($null -ne $result) { Get-PagedResult -InitialResult $result -URI $URI -Style Cursor -ResultProperty 'mcpServers' -CursorRequestKey 'nextCursor' -CursorResponseKey 'nextCursor' } } }#process end { }#end } # .ExternalHelp IdentityCommand.SecureAI-help.xml function Get-SAIModuleData { [CmdletBinding()] param() begin { }#begin process { #Calculate the time elapsed since the start of the session and include in return data if ($null -ne $ISPSSSession.StartTime) { $ISPSSSession.ElapsedTime = '{0:HH:mm:ss}' -f ([datetime]$($(Get-Date) - $($ISPSSSession.StartTime)).Ticks) } else { $ISPSSSession.ElapsedTime = $null } #Deep Copy the $ISPSSSession session object and return as IdCmd Session type. Get-SessionClone -InputObject $ISPSSSession | Add-CustomType -Type IdCmd.Session }#process end { }#end } # .ExternalHelp IdentityCommand.SecureAI-help.xml function Get-SAIPolicy { [CmdletBinding(DefaultParameterSetName = 'All')] param( [parameter( Mandatory = $true, ValueFromPipelinebyPropertyName = $true, ParameterSetName = 'byId' )] [ValidateNotNullOrEmpty()] [Alias('id')] [String]$policyId, [parameter( Mandatory = $false, ValueFromPipelinebyPropertyName = $true, ParameterSetName = 'All' )] [ValidateRange(1, 2147483647)] [int]$pageSize ) begin { }#begin process { if ($PSCmdlet.ParameterSetName -eq 'byId') { $URI = "$($ISPSSSession.tenant_url)/api/policies/$policyId" #Send Request Invoke-IDRestMethod -Uri $URI -Method GET -Accept $(Get-SAIApiHeader -Resource Policies) } else { $URI = "$($ISPSSSession.tenant_url)/api/policies" $URI = Add-QueryString -URI $URI -Parameter ($PSBoundParameters | Get-Parameter) #Send Request $result = Invoke-IDRestMethod -Uri $URI -Method GET -Accept $(Get-SAIApiHeader -Resource Policies) if ($null -ne $result) { #The continuation token is returned as nextCursor and resent as cursor Get-PagedResult -InitialResult $result -URI $URI -Style Cursor -ResultProperty 'policies' -CursorRequestKey 'cursor' -CursorResponseKey 'nextCursor' } } }#process end { }#end } # .ExternalHelp IdentityCommand.SecureAI-help.xml function Get-SAIPredefinedMcpServer { [CmdletBinding(DefaultParameterSetName = 'All')] param( [parameter( Mandatory = $true, ValueFromPipelinebyPropertyName = $true, ParameterSetName = 'byId' )] [ValidateNotNullOrEmpty()] [Alias('id', 'predefinedTargetId')] [String]$templateId ) begin { }#begin process { $URI = "$($ISPSSSession.tenant_url)/api/targets/predefined/mcp-servers" if ($PSCmdlet.ParameterSetName -eq 'byId') { $URI = "$URI/$templateId" #Send Request Invoke-IDRestMethod -Uri $URI -Method GET -Accept $(Get-SAIApiHeader -Resource Targets) } else { #Send Request $result = Invoke-IDRestMethod -Uri $URI -Method GET -Accept $(Get-SAIApiHeader -Resource Targets) if ($null -ne $result) { $result.targets } } }#process end { }#end } # .ExternalHelp IdentityCommand.SecureAI-help.xml function New-SAIAgent { [CmdletBinding(SupportsShouldProcess)] param( [parameter( Mandatory = $true, ValueFromPipelinebyPropertyName = $true )] [ValidateLength(2, 256)] [ValidatePattern('^[A-Za-z0-9 _-]+$')] [String]$name, [parameter( Mandatory = $true, ValueFromPipelinebyPropertyName = $true )] [ValidateLength(2, 256)] [String]$type, [parameter( Mandatory = $false, ValueFromPipelinebyPropertyName = $true )] [ValidateCount(0, 10)] [String[]]$redirectCallbackUrls, [parameter( Mandatory = $false, ValueFromPipelinebyPropertyName = $true )] [ValidateLength(1, 500)] [String]$description, [parameter( Mandatory = $false, ValueFromPipelinebyPropertyName = $true )] [ValidateNotNullOrEmpty()] [psobject[]]$owners, [parameter( Mandatory = $false, ValueFromPipelinebyPropertyName = $true )] [ValidateNotNullOrEmpty()] [hashtable]$tags ) begin { }#begin process { $URI = "$($ISPSSSession.tenant_url)/api/agents" $body = $PSBoundParameters | Get-Parameter | ConvertTo-Json -Depth 8 if ($PSCmdlet.ShouldProcess($name, 'Register AI Agent')) { #Send Request Invoke-IDRestMethod -Uri $URI -Method POST -Body $body -Accept $(Get-SAIApiHeader -Resource Agents) } }#process end { }#end } # .ExternalHelp IdentityCommand.SecureAI-help.xml function New-SAIAgentConditionDefinition { [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'Function builds a definition object and does not change state')] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'Any', Justification = 'Used via $PSCmdlet.ParameterSetName')] [CmdletBinding(DefaultParameterSetName = 'In')] [OutputType('IdCmd.SecureAI.Definition.AgentCondition')] param( [parameter( Mandatory = $true, ValueFromPipelinebyPropertyName = $true, ParameterSetName = 'In' )] [ValidateNotNullOrEmpty()] [String[]]$id, [parameter( Mandatory = $true, ParameterSetName = 'Any' )] [switch]$Any, [parameter(Mandatory = $false)] [psobject[]]$ConditionDefinition ) begin { }#begin process { #Each group carries exactly one condition; groups are combined with or by the service $Condition = if ($PSCmdlet.ParameterSetName -eq 'Any') { [ordered]@{ op = 'any'; value = $null } } else { [ordered]@{ op = 'in'; key = 'id'; value = @($id) } } $Group = [pscustomobject]@{ conditions = @([pscustomobject]$Condition) } $Output = @($ConditionDefinition) + @($Group) | Where-Object { $null -ne $_ } $Output | Add-CustomType -Type 'IdCmd.SecureAI.Definition.AgentCondition' }#process end { }#end } # .ExternalHelp IdentityCommand.SecureAI-help.xml function New-SAIMcpServer { [CmdletBinding(SupportsShouldProcess, DefaultParameterSetName = 'Custom')] param( [parameter( Mandatory = $true, ValueFromPipelinebyPropertyName = $true, ParameterSetName = 'Custom' )] [ValidateLength(1, 256)] [String]$name, [parameter( Mandatory = $true, ValueFromPipelinebyPropertyName = $true, ParameterSetName = 'Custom' )] [ValidateLength(1, 500)] [String]$description, [parameter( Mandatory = $true, ValueFromPipelinebyPropertyName = $true, ParameterSetName = 'Custom' )] [ValidateSet('COMMUNICATION_AND_TEAM_CHAT', 'EMAIL_AND_SCHEDULING', 'KNOWLEDGE_BASES_AND_DOCS', 'FILE_STORAGE_AND_CONTENT_REPOS', 'DEVELOPER_TOOLS_AND_SOURCE_CONTROL', 'DATABASES_AND_DATA_STORES', 'OBSERVABILITY_MONITORING_AND_TELEMETRY', 'ITSM_AND_INCIDENT_RESPONSE', 'WEB_AND_BROWSER_AUTOMATION', 'CLOUD_AND_INFRASTRUCTURE_OPERATIONS')] [String]$category, [parameter( Mandatory = $true, ValueFromPipelinebyPropertyName = $true, ParameterSetName = 'Custom' )] [ValidateLength(1, 2048)] [String]$upstreamUrl, [parameter( Mandatory = $true, ValueFromPipelinebyPropertyName = $true, ParameterSetName = 'Predefined' )] [ValidateNotNullOrEmpty()] [String]$predefinedTargetId, [parameter( Mandatory = $false, ValueFromPipelinebyPropertyName = $true, ParameterSetName = 'Predefined' )] [ValidateLength(1, 500)] [Alias('predefinedDescription')] [String]$templateDescription, [parameter( Mandatory = $false, ValueFromPipelinebyPropertyName = $true )] [ValidateSet('OAUTH2.1', 'NONE')] [String]$authMethodType, [parameter( Mandatory = $false, ValueFromPipelinebyPropertyName = $true )] [ValidateNotNullOrEmpty()] [String]$authorizationServer, [parameter( Mandatory = $false, ValueFromPipelinebyPropertyName = $true )] [ValidateNotNullOrEmpty()] [String]$JWKS, [parameter( Mandatory = $false, ValueFromPipelinebyPropertyName = $true )] [ValidateLength(1, 512)] [String]$clientId, [parameter( Mandatory = $false, ValueFromPipelinebyPropertyName = $true )] [ValidateNotNullOrEmpty()] [securestring]$clientSecret, [parameter( Mandatory = $false, ValueFromPipelinebyPropertyName = $true )] [ValidateNotNullOrEmpty()] [String]$registrationEndpoint, [parameter( Mandatory = $false, ValueFromPipelinebyPropertyName = $true )] [ValidateNotNullOrEmpty()] [psobject[]]$owners, [parameter( Mandatory = $false, ValueFromPipelinebyPropertyName = $true )] [ValidateNotNullOrEmpty()] [hashtable]$tags ) begin { }#begin process { $URI = "$($ISPSSSession.tenant_url)/api/targets/mcp-servers" if ($PSBoundParameters.ContainsKey('clientSecret') -and (-not $PSBoundParameters.ContainsKey('clientId'))) { throw 'clientSecret cannot be provided without clientId' } if ($PSBoundParameters.ContainsKey('registrationEndpoint') -and ($PSBoundParameters.ContainsKey('clientId') -or $PSBoundParameters.ContainsKey('clientSecret'))) { throw 'registrationEndpoint cannot be combined with clientId or clientSecret - supply manual credentials or a registration endpoint for dynamic client registration, not both' } $Target = [ordered]@{ } if ($PSCmdlet.ParameterSetName -eq 'Predefined') { $Target['source'] = [ordered]@{ type = 'PREDEFINED'; predefinedTargetId = $predefinedTargetId } if ($PSBoundParameters.ContainsKey('templateDescription')) { $Target['description'] = $templateDescription } } else { $Target['source'] = [ordered]@{ type = 'CUSTOM' } $Target['name'] = $name $Target['description'] = $description $Target['category'] = $category $Target['upstream'] = [ordered]@{ url = $upstreamUrl } } if ($PSBoundParameters.ContainsKey('authMethodType')) { $AuthMethod = [ordered]@{ type = $authMethodType } foreach ($Field in 'authorizationServer', 'JWKS', 'clientId', 'registrationEndpoint') { if ($PSBoundParameters.ContainsKey($Field)) { $AuthMethod[$Field] = $PSBoundParameters[$Field] } } if ($PSBoundParameters.ContainsKey('clientSecret')) { $AuthMethod['clientSecret'] = $(ConvertTo-InsecureString -SecureString $clientSecret) } $Target['authMethod'] = $AuthMethod } foreach ($Field in 'owners', 'tags') { if ($PSBoundParameters.ContainsKey($Field)) { $Target[$Field] = $PSBoundParameters[$Field] } } #The body can carry an OAuth client secret, so it travels as UTF8 bytes $body = $Target | ConvertTo-SecretBody -Depth 8 if ($PSCmdlet.ShouldProcess($(if ($PSCmdlet.ParameterSetName -eq 'Predefined') { $predefinedTargetId } else { $name }), 'Register MCP Server')) { #Send Request Invoke-IDRestMethod -Uri $URI -Method POST -Body $body -Accept $(Get-SAIApiHeader -Resource Targets) } }#process end { }#end } # .ExternalHelp IdentityCommand.SecureAI-help.xml function New-SAIOwnerDefinition { [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'Function builds a definition object and does not change state')] [CmdletBinding()] [OutputType('IdCmd.SecureAI.Definition.Owner')] param( [parameter( Mandatory = $true, ValueFromPipelinebyPropertyName = $true )] [ValidateNotNullOrEmpty()] [String]$id, [parameter( Mandatory = $true, ValueFromPipelinebyPropertyName = $true )] [ValidateNotNullOrEmpty()] [String]$name, [parameter( Mandatory = $true, ValueFromPipelinebyPropertyName = $true )] [ValidateSet('USER', 'ROLE')] [String]$type, [parameter( Mandatory = $false, ValueFromPipelinebyPropertyName = $true )] [ValidateNotNullOrEmpty()] [String]$sourceDirectoryName, [parameter( Mandatory = $false, ValueFromPipelinebyPropertyName = $true )] [ValidateNotNullOrEmpty()] [String]$sourceDirectoryId, [parameter(Mandatory = $false)] [psobject[]]$OwnerDefinition ) begin { }#begin process { if (($type -eq 'USER') -and (-not ($PSBoundParameters.ContainsKey('sourceDirectoryName') -and $PSBoundParameters.ContainsKey('sourceDirectoryId')))) { throw 'sourceDirectoryName and sourceDirectoryId are required for a USER owner' } $Owner = $PSBoundParameters | Get-Parameter -ParametersToRemove OwnerDefinition $Output = @($OwnerDefinition) + @([pscustomobject]$Owner) | Where-Object { $null -ne $_ } $Output | Add-CustomType -Type 'IdCmd.SecureAI.Definition.Owner' }#process end { }#end } # .ExternalHelp IdentityCommand.SecureAI-help.xml function New-SAIPolicy { [CmdletBinding(SupportsShouldProcess)] param( [parameter( Mandatory = $true, ValueFromPipelinebyPropertyName = $true )] [ValidateLength(1, 256)] [String]$name, [parameter( Mandatory = $true, ValueFromPipelinebyPropertyName = $true )] [ValidateSet('ON_BEHALF_OF', 'AUTONOMOUS')] [String]$accessType, [parameter( Mandatory = $true, ValueFromPipelinebyPropertyName = $true )] [ValidateSet('ENABLED', 'DISABLED')] [String]$state, [parameter( Mandatory = $true, ValueFromPipelinebyPropertyName = $true )] [ValidateNotNullOrEmpty()] [psobject[]]$agent, [parameter( Mandatory = $true, ValueFromPipelinebyPropertyName = $true )] [ValidateNotNullOrEmpty()] [psobject[]]$resources, [parameter( Mandatory = $false, ValueFromPipelinebyPropertyName = $true )] [ValidateLength(1, 500)] [String]$description, [parameter( Mandatory = $false, ValueFromPipelinebyPropertyName = $true )] [ValidateNotNullOrEmpty()] [hashtable]$tags, [parameter( Mandatory = $false, ValueFromPipelinebyPropertyName = $true )] [ValidateNotNullOrEmpty()] [psobject[]]$owners, [parameter( Mandatory = $false, ValueFromPipelinebyPropertyName = $true )] [ValidateNotNullOrEmpty()] [psobject[]]$user ) begin { }#begin process { $URI = "$($ISPSSSession.tenant_url)/api/policies" #A user grant is required for an on-behalf-of policy and rejected for an autonomous one if (($accessType -eq 'ON_BEHALF_OF') -and (-not $PSBoundParameters.ContainsKey('user'))) { throw 'A user grant is required when accessType is ON_BEHALF_OF' } if (($accessType -eq 'AUTONOMOUS') -and $PSBoundParameters.ContainsKey('user')) { throw 'A user grant cannot be supplied when accessType is AUTONOMOUS' } $body = $PSBoundParameters | Get-Parameter | ConvertTo-Json -Depth 10 if ($PSCmdlet.ShouldProcess($name, 'Create Secure AI Access Policy')) { #Send Request Invoke-IDRestMethod -Uri $URI -Method POST -Body $body -Accept $(Get-SAIApiHeader -Resource Policies) } }#process end { }#end } # .ExternalHelp IdentityCommand.SecureAI-help.xml function New-SAIResourceConditionDefinition { [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'Function builds a definition object and does not change state')] [CmdletBinding(DefaultParameterSetName = 'MatchId')] [OutputType('IdCmd.SecureAI.Definition.ResourceCondition')] param( [parameter( Mandatory = $true, ValueFromPipelinebyPropertyName = $true, ParameterSetName = 'MatchId' )] [ValidateNotNullOrEmpty()] [String]$matchId, [parameter( Mandatory = $true, ValueFromPipelinebyPropertyName = $true, ParameterSetName = 'MatchTag' )] [ValidateNotNullOrEmpty()] [String]$matchTag, [parameter( Mandatory = $true, ValueFromPipelinebyPropertyName = $true, ParameterSetName = 'InId' )] [ValidateNotNullOrEmpty()] [String[]]$id, [parameter( Mandatory = $true, ValueFromPipelinebyPropertyName = $true, ParameterSetName = 'InTag' )] [ValidateNotNullOrEmpty()] [String[]]$tag, [parameter(Mandatory = $false)] [psobject[]]$ConditionDefinition ) begin { }#begin process { $Condition = switch ($PSCmdlet.ParameterSetName) { 'MatchTag' { [ordered]@{ op = 'match'; key = 'tag'; value = $matchTag } } 'InId' { [ordered]@{ op = 'in'; key = 'id'; value = @($id) } } 'InTag' { [ordered]@{ op = 'in'; key = 'tag'; value = @($tag) } } default { [ordered]@{ op = 'match'; key = 'id'; value = $matchId } } } $Group = [pscustomobject]@{ conditions = @([pscustomobject]$Condition) } $Output = @($ConditionDefinition) + @($Group) | Where-Object { $null -ne $_ } $Output | Add-CustomType -Type 'IdCmd.SecureAI.Definition.ResourceCondition' }#process end { }#end } # .ExternalHelp IdentityCommand.SecureAI-help.xml function New-SAIUserConditionDefinition { [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'Function builds a definition object and does not change state')] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'Any', Justification = 'Used via $PSCmdlet.ParameterSetName')] [CmdletBinding(DefaultParameterSetName = 'InId')] [OutputType('IdCmd.SecureAI.Definition.UserCondition')] param( [parameter( Mandatory = $true, ValueFromPipelinebyPropertyName = $true, ParameterSetName = 'InId' )] [ValidateNotNullOrEmpty()] [String[]]$id, [parameter( Mandatory = $true, ValueFromPipelinebyPropertyName = $true, ParameterSetName = 'InRole' )] [ValidateNotNullOrEmpty()] [String[]]$roleId, [parameter( Mandatory = $true, ParameterSetName = 'Any' )] [switch]$Any, [parameter(Mandatory = $false)] [psobject[]]$ConditionDefinition ) begin { }#begin process { $Condition = switch ($PSCmdlet.ParameterSetName) { 'Any' { [ordered]@{ op = 'any'; value = $null } } 'InRole' { [ordered]@{ op = 'in'; key = 'roleId'; value = @($roleId) } } default { [ordered]@{ op = 'in'; key = 'id'; value = @($id) } } } $Group = [pscustomobject]@{ conditions = @([pscustomobject]$Condition) } $Output = @($ConditionDefinition) + @($Group) | Where-Object { $null -ne $_ } $Output | Add-CustomType -Type 'IdCmd.SecureAI.Definition.UserCondition' }#process end { }#end } # .ExternalHelp IdentityCommand.SecureAI-help.xml function Remove-SAIAgent { [CmdletBinding(SupportsShouldProcess)] param( [parameter( Mandatory = $true, ValueFromPipelinebyPropertyName = $true )] [ValidateLength(1, 128)] [Alias('id')] [String]$agentId ) begin { }#begin process { $URI = "$($ISPSSSession.tenant_url)/api/agents/$agentId" if ($PSCmdlet.ShouldProcess($agentId, 'Delete AI Agent')) { #Send Request Invoke-IDRestMethod -Uri $URI -Method DELETE -Accept $(Get-SAIApiHeader -Resource Agents) } }#process end { }#end } # .ExternalHelp IdentityCommand.SecureAI-help.xml function Remove-SAIMcpServer { [CmdletBinding(SupportsShouldProcess)] param( [parameter( Mandatory = $true, ValueFromPipelinebyPropertyName = $true )] [ValidateNotNullOrEmpty()] [Alias('id')] [String]$mcpServerId ) begin { }#begin process { $URI = "$($ISPSSSession.tenant_url)/api/targets/mcp-servers/$mcpServerId" if ($PSCmdlet.ShouldProcess($mcpServerId, 'Delete MCP Server')) { #Send Request Invoke-IDRestMethod -Uri $URI -Method DELETE -Accept $(Get-SAIApiHeader -Resource Targets) } }#process end { }#end } # .ExternalHelp IdentityCommand.SecureAI-help.xml function Remove-SAIPolicy { [CmdletBinding(SupportsShouldProcess)] param( [parameter( Mandatory = $true, ValueFromPipelinebyPropertyName = $true )] [ValidateNotNullOrEmpty()] [Alias('id')] [String]$policyId ) begin { }#begin process { $URI = "$($ISPSSSession.tenant_url)/api/policies/$policyId" if ($PSCmdlet.ShouldProcess($policyId, 'Delete Secure AI Access Policy')) { #Send Request Invoke-IDRestMethod -Uri $URI -Method DELETE -Accept $(Get-SAIApiHeader -Resource Policies) } }#process end { }#end } # .ExternalHelp IdentityCommand.SecureAI-help.xml function Set-SAIAgent { [CmdletBinding(SupportsShouldProcess)] param( [parameter( Mandatory = $true, ValueFromPipelinebyPropertyName = $true )] [ValidateLength(1, 128)] [Alias('id')] [String]$agentId, [parameter( Mandatory = $false, ValueFromPipelinebyPropertyName = $true )] [ValidateLength(2, 256)] [ValidatePattern('^[A-Za-z0-9 _-]+$')] [String]$name, [parameter( Mandatory = $false, ValueFromPipelinebyPropertyName = $true )] [ValidateLength(1, 500)] [String]$description, [parameter( Mandatory = $false, ValueFromPipelinebyPropertyName = $true )] [ValidateNotNullOrEmpty()] [psobject[]]$owners, [parameter( Mandatory = $false, ValueFromPipelinebyPropertyName = $true )] [ValidateNotNullOrEmpty()] [hashtable]$tags ) begin { }#begin process { $URI = "$($ISPSSSession.tenant_url)/api/agents/$agentId" $body = $PSBoundParameters | Get-Parameter -ParametersToRemove agentId | ConvertTo-Json -Depth 8 if ($PSCmdlet.ShouldProcess($agentId, 'Update AI Agent')) { #Send Request Invoke-IDRestMethod -Uri $URI -Method PUT -Body $body -Accept $(Get-SAIApiHeader -Resource Agents) } }#process end { }#end } # .ExternalHelp IdentityCommand.SecureAI-help.xml function Set-SAIAgentState { [CmdletBinding(SupportsShouldProcess)] param( [parameter( Mandatory = $true, ValueFromPipelinebyPropertyName = $true )] [ValidateLength(1, 128)] [Alias('id')] [String]$agentId, [parameter( Mandatory = $true, ValueFromPipelinebyPropertyName = $true )] [ValidateSet('ACTIVE', 'SUSPENDED')] [String]$state ) begin { }#begin process { $URI = "$($ISPSSSession.tenant_url)/api/agents/$agentId/state" $body = [ordered]@{ state = $state } | ConvertTo-Json -Depth 8 if ($PSCmdlet.ShouldProcess($agentId, "Set AI Agent State: $state")) { #Send Request Invoke-IDRestMethod -Uri $URI -Method POST -Body $body -Accept $(Get-SAIApiHeader -Resource Agents) } }#process end { }#end } # .ExternalHelp IdentityCommand.SecureAI-help.xml function Set-SAIMcpServer { [CmdletBinding(SupportsShouldProcess)] param( [parameter( Mandatory = $true, ValueFromPipelinebyPropertyName = $true )] [ValidateNotNullOrEmpty()] [Alias('id')] [String]$mcpServerId, [parameter( Mandatory = $false, ValueFromPipelinebyPropertyName = $true )] [ValidateLength(1, 500)] [String]$description, [parameter( Mandatory = $false, ValueFromPipelinebyPropertyName = $true )] [ValidateSet('COMMUNICATION_AND_TEAM_CHAT', 'EMAIL_AND_SCHEDULING', 'KNOWLEDGE_BASES_AND_DOCS', 'FILE_STORAGE_AND_CONTENT_REPOS', 'DEVELOPER_TOOLS_AND_SOURCE_CONTROL', 'DATABASES_AND_DATA_STORES', 'OBSERVABILITY_MONITORING_AND_TELEMETRY', 'ITSM_AND_INCIDENT_RESPONSE', 'WEB_AND_BROWSER_AUTOMATION', 'CLOUD_AND_INFRASTRUCTURE_OPERATIONS')] [String]$category, [parameter( Mandatory = $false, ValueFromPipelinebyPropertyName = $true )] [ValidateNotNullOrEmpty()] [psobject[]]$owners, [parameter( Mandatory = $false, ValueFromPipelinebyPropertyName = $true )] [ValidateNotNullOrEmpty()] [hashtable]$tags ) begin { }#begin process { $URI = "$($ISPSSSession.tenant_url)/api/targets/mcp-servers/$mcpServerId" $body = $PSBoundParameters | Get-Parameter -ParametersToRemove mcpServerId | ConvertTo-Json -Depth 8 if ($PSCmdlet.ShouldProcess($mcpServerId, 'Update MCP Server')) { #Send Request Invoke-IDRestMethod -Uri $URI -Method PUT -Body $body -Accept $(Get-SAIApiHeader -Resource Targets) } }#process end { }#end } # .ExternalHelp IdentityCommand.SecureAI-help.xml function Set-SAIMcpServerState { [CmdletBinding(SupportsShouldProcess)] param( [parameter( Mandatory = $true, ValueFromPipelinebyPropertyName = $true )] [ValidateNotNullOrEmpty()] [Alias('id')] [String]$mcpServerId, [parameter( Mandatory = $true, ValueFromPipelinebyPropertyName = $true )] [ValidateSet('ENABLED', 'DISABLED')] [String]$state ) begin { }#begin process { $URI = "$($ISPSSSession.tenant_url)/api/targets/mcp-servers/$mcpServerId/state" $body = [ordered]@{ state = $state } | ConvertTo-Json -Depth 8 if ($PSCmdlet.ShouldProcess($mcpServerId, "Set MCP Server State: $state")) { #Send Request Invoke-IDRestMethod -Uri $URI -Method POST -Body $body -Accept $(Get-SAIApiHeader -Resource Targets) } }#process end { }#end } # .ExternalHelp IdentityCommand.SecureAI-help.xml function Set-SAIPolicy { [CmdletBinding(SupportsShouldProcess)] param( [parameter( Mandatory = $true, ValueFromPipelinebyPropertyName = $true )] [ValidateNotNullOrEmpty()] [Alias('id')] [String]$policyId, [parameter( Mandatory = $false, ValueFromPipelinebyPropertyName = $true )] [ValidateLength(1, 256)] [String]$name, [parameter( Mandatory = $false, ValueFromPipelinebyPropertyName = $true )] [ValidateSet('ENABLED', 'DISABLED')] [String]$state, [parameter( Mandatory = $false, ValueFromPipelinebyPropertyName = $true )] [ValidateNotNullOrEmpty()] [psobject[]]$agent, [parameter( Mandatory = $false, ValueFromPipelinebyPropertyName = $true )] [ValidateNotNullOrEmpty()] [psobject[]]$resources, [parameter( Mandatory = $false, ValueFromPipelinebyPropertyName = $true )] [ValidateLength(1, 500)] [String]$description, [parameter( Mandatory = $false, ValueFromPipelinebyPropertyName = $true )] [ValidateNotNullOrEmpty()] [hashtable]$tags, [parameter( Mandatory = $false, ValueFromPipelinebyPropertyName = $true )] [ValidateNotNullOrEmpty()] [psobject[]]$owners, [parameter( Mandatory = $false, ValueFromPipelinebyPropertyName = $true )] [ValidateNotNullOrEmpty()] [psobject[]]$user ) begin { }#begin process { $URI = "$($ISPSSSession.tenant_url)/api/policies/$policyId" #The service leaves omitted fields unchanged, so only what was supplied is sent $body = $PSBoundParameters | Get-Parameter -ParametersToRemove policyId | ConvertTo-Json -Depth 10 if ($PSCmdlet.ShouldProcess($policyId, 'Update Secure AI Access Policy')) { #Send Request Invoke-IDRestMethod -Uri $URI -Method PUT -Body $body -Accept $(Get-SAIApiHeader -Resource Policies) } }#process end { }#end } # .ExternalHelp IdentityCommand.SecureAI-help.xml function Set-SAIPolicyState { [CmdletBinding(SupportsShouldProcess)] param( [parameter( Mandatory = $true, ValueFromPipelinebyPropertyName = $true )] [ValidateNotNullOrEmpty()] [Alias('id')] [String]$policyId, [parameter( Mandatory = $true, ValueFromPipelinebyPropertyName = $true )] [ValidateSet('ENABLED', 'DISABLED')] [String]$state ) begin { }#begin process { $URI = "$($ISPSSSession.tenant_url)/api/policies/$policyId/state" $body = [ordered]@{ state = $state } | ConvertTo-Json -Depth 8 if ($PSCmdlet.ShouldProcess($policyId, "Set Secure AI Access Policy State: $state")) { #Send Request Invoke-IDRestMethod -Uri $URI -Method POST -Body $body -Accept $(Get-SAIApiHeader -Resource Policies) } }#process end { }#end } #Copy IdentityCommand's private helpers into this module: this module's functions call them, and #the argument completer registrations below do so at import time. #Each copy is created from the function definition, so it runs in this module's scope and uses this #module's $ISPSSSession, whether IdentityCommand loaded from source or from its combined psm1. #Resolve a single IdentityCommand module: with more than one version loaded, Get-Module returns #an array. $Module = Get-Module -Name IdentityCommand | Sort-Object Version -Descending | Select-Object -First 1 if ($null -eq $Module) { throw 'The IdentityCommand module is not loaded. Import IdentityCommand and try again.' } & $Module { Get-ChildItem -Path Function: } | Where-Object { $_.ModuleName -eq $Module.Name -and -not $Module.ExportedFunctions.ContainsKey($_.Name) } | ForEach-Object { . ([scriptblock]::Create("function $($_.Name) {$($_.Definition)}")) } #region Registration Register-ArgumentCompleter -ParameterName 'agentId' -ScriptBlock ( Get-ArgumentCompleter -RetrievalCommand 'Get-SAIAgent' -ValueProperty 'id' -LabelProperty 'name' ) -CommandName @( 'Get-SAIAgent' 'Remove-SAIAgent' 'Set-SAIAgent' 'Set-SAIAgentState' ) Register-ArgumentCompleter -ParameterName 'mcpServerId' -ScriptBlock ( Get-ArgumentCompleter -RetrievalCommand 'Get-SAIMcpServer' -ValueProperty 'id' -LabelProperty 'name' ) -CommandName @( 'Get-SAIMcpServer' 'Remove-SAIMcpServer' 'Set-SAIMcpServer' 'Set-SAIMcpServerState' ) #The predefined catalog is the source of the template id a registration is created from Register-ArgumentCompleter -ParameterName 'predefinedTargetId' -ScriptBlock ( Get-ArgumentCompleter -RetrievalCommand 'Get-SAIPredefinedMcpServer' -ValueProperty 'id' -LabelProperty 'name' ) -CommandName 'New-SAIMcpServer' Register-ArgumentCompleter -ParameterName 'templateId' -ScriptBlock ( Get-ArgumentCompleter -RetrievalCommand 'Get-SAIPredefinedMcpServer' -ValueProperty 'id' -LabelProperty 'name' ) -CommandName 'Get-SAIPredefinedMcpServer' Register-ArgumentCompleter -ParameterName 'policyId' -ScriptBlock ( Get-ArgumentCompleter -RetrievalCommand 'Get-SAIPolicy' -ValueProperty 'id' -LabelProperty 'name' ) -CommandName @( 'Get-SAIPolicy' 'Remove-SAIPolicy' 'Set-SAIPolicy' 'Set-SAIPolicyState' ) #endregion Registration # Script scope session object for session data $ISPSSSession = [ordered]@{ tenant_url = $null User = $null TenantId = $null SessionId = $null WebSession = $null StartTime = $null ElapsedTime = $null LastCommand = $null LastCommandTime = $null LastCommandResults = $null LastError = $null LastErrorTime = $null } | Add-CustomType -Type IdCmd.Session New-Variable -Name ISPSSSession -Value $ISPSSSession -Scope Script -Force |