diff --git a/src/Identity.SignIns/beta/custom/ConvertTo-EntraXTAPFlatOutput.ps1 b/src/Identity.SignIns/beta/custom/ConvertTo-EntraXTAPFlatOutput.ps1 new file mode 100644 index 00000000000..286f975c142 --- /dev/null +++ b/src/Identity.SignIns/beta/custom/ConvertTo-EntraXTAPFlatOutput.ps1 @@ -0,0 +1,195 @@ +# ---------------------------------------------------------------------------------- +# +# Copyright Microsoft Corporation +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ---------------------------------------------------------------------------------- + +<# +.Synopsis + Internal helper: projects a CrossTenantAccessPolicy API response into the flat + parameter-aligned output shape shared by the *-DefaultEntraXTAP and + *-PartnerEntraXTAP cmdlets. + +.Description + Decodes the nested TargetConfiguration model back into the flat property names + that match the new cmdlet input parameters: + + Default mode (IsPartner = $false): emits Id + flat properties. + Partner mode (IsPartner = $true): emits PartnerTenantId + flat properties. + + Output property mapping: + M365CollaborationInbound.Users.accessType → M365CollaborationInbound ("Allowed"|"Blocked") + M365CollaborationInbound.Users.targets[user] → M365CollaborationInboundTargetUsers + M365CollaborationOutbound.UsersAndGroups.accessType → M365CollaborationOutbound ("Allowed"|"Blocked") + M365CollaborationOutbound.UsersAndGroups.targets[user] → M365CollaborationOutboundTargetUsers + M365CollaborationOutbound.UsersAndGroups.targets[group] → M365CollaborationOutboundTargetGroups + AppServiceConnectInbound.Applications.accessType → AppServiceConnectInbound ("Allowed"|"Blocked") + AppServiceConnectInbound.Applications.targets[application] → AppServiceConnectInboundTargetApplications +#> +function ConvertTo-EntraXTAPFlatOutput { + param( + [Parameter(Mandatory = $true)] + $Result, + + [Parameter()] + [switch] + $IsPartner + ) + + # Helper: capitalise first letter of accessType for enum output ("allowed" → "Allowed") + function Format-AccessType { + param([string]$Value) + if ([string]::IsNullOrEmpty($Value)) { return $null } + return [System.Globalization.CultureInfo]::InvariantCulture.TextInfo.ToTitleCase($Value.ToLower()) + } + + # Helper: extract target IDs from a TargetConfiguration for a given targetType. + function Get-TargetIds { + param($Config, [string]$TargetType) + if ($null -eq $Config -or $null -eq $Config.Targets) { return $null } + $ids = @($Config.Targets | Where-Object { $_.TargetType -eq $TargetType } | ForEach-Object { $_.Target }) + if ($ids.Count -eq 0) { return $null } + return $ids + } + + # ------------------------------------------------------------------ + # M365CollaborationInbound → .Users (user targets only) + # ------------------------------------------------------------------ + $inboundConfig = if ($null -ne $Result.M365CollaborationInbound) { $Result.M365CollaborationInbound.Users } else { $null } + $inboundAccessType = if ($null -ne $inboundConfig) { Format-AccessType $inboundConfig.AccessType } else { $null } + $inboundUsers = if ($null -ne $inboundConfig) { Get-TargetIds -Config $inboundConfig -TargetType 'user' } else { $null } + + # ------------------------------------------------------------------ + # M365CollaborationOutbound → .UsersAndGroups (user + group) + # ------------------------------------------------------------------ + $outboundConfig = if ($null -ne $Result.M365CollaborationOutbound) { $Result.M365CollaborationOutbound.UsersAndGroups } else { $null } + $outboundAccessType = if ($null -ne $outboundConfig) { Format-AccessType $outboundConfig.AccessType } else { $null } + $outboundUsers = if ($null -ne $outboundConfig) { Get-TargetIds -Config $outboundConfig -TargetType 'user' } else { $null } + $outboundGroups = if ($null -ne $outboundConfig) { Get-TargetIds -Config $outboundConfig -TargetType 'group' } else { $null } + + # ------------------------------------------------------------------ + # AppServiceConnectInbound → .Applications (application targets) + # ------------------------------------------------------------------ + $appConfig = if ($null -ne $Result.AppServiceConnectInbound) { $Result.AppServiceConnectInbound.Applications } else { $null } + $appAccessType = if ($null -ne $appConfig) { Format-AccessType $appConfig.AccessType } else { $null } + $appIds = if ($null -ne $appConfig) { Get-TargetIds -Config $appConfig -TargetType 'application' } else { $null } + + # ------------------------------------------------------------------ + # Emit flat output — property names match cmdlet input parameters. + # ------------------------------------------------------------------ + if ($IsPartner) { + [PSCustomObject]@{ + PartnerTenantId = $Result.TenantId + M365CollaborationInbound = $inboundAccessType + M365CollaborationInboundTargetUsers = $inboundUsers + M365CollaborationOutbound = $outboundAccessType + M365CollaborationOutboundTargetUsers = $outboundUsers + M365CollaborationOutboundTargetGroups = $outboundGroups + AppServiceConnectInbound = $appAccessType + AppServiceConnectInboundTargetApplications = $appIds + } + } else { + [PSCustomObject]@{ + Id = $Result.Id + IsServiceDefault = $Result.IsServiceDefault + M365CollaborationInbound = $inboundAccessType + M365CollaborationInboundTargetUsers = $inboundUsers + M365CollaborationOutbound = $outboundAccessType + M365CollaborationOutboundTargetUsers = $outboundUsers + M365CollaborationOutboundTargetGroups = $outboundGroups + AppServiceConnectInbound = $appAccessType + AppServiceConnectInboundTargetApplications = $appIds + } + } +} + +<# +.Synopsis + Internal helper: projects a M365CapabilityBase API response into the flat + parameter-aligned output shape shared by the *-DefaultM365XTAPCapability and + *-PartnerM365XTAPCapability cmdlets. + +.Description + Decodes the nested M365CapabilityInboundAccess model back into the flat + property names that match the cmdlet input parameters: + + InboundAccess.IsAllowed → IsAllowed + InboundAccess.ResourceScopes + .Included[ResourceType=user] → IncludedUsers + .Included[ResourceType=group] → IncludedGroups + .Excluded[ResourceType=user] → ExcludedUsers + .Excluded[ResourceType=group] → ExcludedGroups + + Default mode (IsPartner = $false): + Emits CapabilityId, LastModifiedDateTime, IsAllowed, Included/Excluded Users/Groups. + + Partner mode (IsPartner = $true): + Prepends PartnerTenantId before CapabilityId. +#> +function ConvertTo-EntraXTAPM365CapabilityFlatOutput { + param( + [Parameter(Mandatory = $true)] + $Result, + + [Parameter()] + [switch] + $IsPartner + ) + + # ------------------------------------------------------------------ + # Helper: extract resource IDs from a scope array for a given type. + # ------------------------------------------------------------------ + function Get-ScopeIds { + param($Scopes, [string]$ResourceType) + if ($null -eq $Scopes) { return $null } + $ids = @($Scopes | Where-Object { $_.ResourceType -eq $ResourceType } | ForEach-Object { $_.ResourceId }) + if ($ids.Count -eq 0) { return $null } + return $ids + } + + $inbound = $Result.InboundAccess + $isAllowed = if ($null -ne $inbound) { $inbound.IsAllowed } else { $null } + $includedUsers = $null + $includedGroups = $null + $excludedUsers = $null + $excludedGroups = $null + + if ($null -ne $inbound -and $null -ne $inbound.ResourceScopes) { + $includedUsers = Get-ScopeIds -Scopes $inbound.ResourceScopes.Included -ResourceType 'user' + $includedGroups = Get-ScopeIds -Scopes $inbound.ResourceScopes.Included -ResourceType 'group' + $excludedUsers = Get-ScopeIds -Scopes $inbound.ResourceScopes.Excluded -ResourceType 'user' + $excludedGroups = Get-ScopeIds -Scopes $inbound.ResourceScopes.Excluded -ResourceType 'group' + } + + if ($IsPartner) { + [PSCustomObject]@{ + PartnerTenantId = $Result.AdditionalProperties['tenantId'] + CapabilityId = $Result.Name + LastModifiedDateTime = $Result.LastModifiedDateTime + IsAllowed = $isAllowed + IncludedUsers = $includedUsers + IncludedGroups = $includedGroups + ExcludedUsers = $excludedUsers + ExcludedGroups = $excludedGroups + } + } else { + [PSCustomObject]@{ + CapabilityId = $Result.Name + LastModifiedDateTime = $Result.LastModifiedDateTime + IsAllowed = $isAllowed + IncludedUsers = $includedUsers + IncludedGroups = $includedGroups + ExcludedUsers = $excludedUsers + ExcludedGroups = $excludedGroups + } + } +} + diff --git a/src/Identity.SignIns/beta/custom/Get-DefaultEntraXTAP.ps1 b/src/Identity.SignIns/beta/custom/Get-DefaultEntraXTAP.ps1 new file mode 100644 index 00000000000..cbc7d7f9120 --- /dev/null +++ b/src/Identity.SignIns/beta/custom/Get-DefaultEntraXTAP.ps1 @@ -0,0 +1,107 @@ +# ---------------------------------------------------------------------------------- +# +# Copyright Microsoft Corporation +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ---------------------------------------------------------------------------------- + +<# +.Synopsis + Gets the M365 Collaboration and App Service Connect settings from the tenant-wide + default Cross-Tenant Access Policy (XTAP) configuration. + +.Description + Provides a flattened, user-friendly interface over + Get-MgBetaPolicyCrossTenantAccessPolicyDefault. + + The default configuration is a singleton — there is exactly one per tenant. + This cmdlet scopes the output to the three properties that are configurable + via Update-DefaultEntraXTAP: + + - M365CollaborationInbound (inbound user access) + - M365CollaborationOutbound (outbound users and groups access) + - AppServiceConnectInbound (inbound application access) + + All other properties (B2B, InboundTrust, TenantRestrictions, etc.) are excluded + from both the API request ($select) and the output object. + +.Example + # Get the default M365 Collaboration and App Service Connect settings + Get-DefaultEntraXTAP + +.Outputs + Microsoft.Graph.Beta.PowerShell.Models.IMicrosoftGraphCrossTenantAccessPolicyConfigurationDefault + +.Link + https://learn.microsoft.com/en-us/graph/api/crosstenantaccesspolicydefaultconfiguration-get + https://learn.microsoft.com/en-us/powershell/module/microsoft.graph.beta.identity.signins/get-mgbetapolicycrosstenantaccesspolicydefault +#> +function Get-DefaultEntraXTAP { + [OutputType([Microsoft.Graph.Beta.PowerShell.Models.IMicrosoftGraphCrossTenantAccessPolicyConfigurationDefault])] + [CmdletBinding(DefaultParameterSetName = 'Get', + PositionalBinding = $false)] + param( + + # ── Pipeline / runtime ──────────────────────────────────────────── + [Parameter(DontShow)] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Management.Automation.SwitchParameter] + ${Break}, + + [Parameter(DontShow)] + [ValidateNotNull()] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [Microsoft.Graph.Beta.PowerShell.Runtime.SendAsyncStep[]] + ${HttpPipelineAppend}, + + [Parameter(DontShow)] + [ValidateNotNull()] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [Microsoft.Graph.Beta.PowerShell.Runtime.SendAsyncStep[]] + ${HttpPipelinePrepend}, + + [Parameter(DontShow)] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Uri] + ${Proxy}, + + [Parameter(DontShow)] + [ValidateNotNull()] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Management.Automation.PSCredential] + ${ProxyCredential}, + + [Parameter(DontShow)] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Management.Automation.SwitchParameter] + ${ProxyUseDefaultCredentials} + ) + + begin { + } + + process { + # Request only the three properties exposed by Update-DefaultEntraXTAP. + $selectProps = 'id', 'isServiceDefault', 'm365CollaborationInbound', 'm365CollaborationOutbound', 'appServiceConnectInbound' + + Write-Verbose "Getting default XTAP configuration (scoped to M365Collaboration and AppServiceConnect)." + + $result = Get-MgBetaPolicyCrossTenantAccessPolicyDefault ` + -Property $selectProps ` + @PSBoundParameters + + if ($null -eq $result) { return } + + ConvertTo-EntraXTAPFlatOutput -Result $result + } + + end { + } +} diff --git a/src/Identity.SignIns/beta/custom/Get-DefaultM365XTAPCapability.ps1 b/src/Identity.SignIns/beta/custom/Get-DefaultM365XTAPCapability.ps1 new file mode 100644 index 00000000000..a98436a242b --- /dev/null +++ b/src/Identity.SignIns/beta/custom/Get-DefaultM365XTAPCapability.ps1 @@ -0,0 +1,151 @@ +# ---------------------------------------------------------------------------------- +# +# Copyright Microsoft Corporation +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ---------------------------------------------------------------------------------- + +<# +.Synopsis + Gets one or all Microsoft 365 capability entries from the default Cross-Tenant + Access Policy (XTAP) configuration for the tenant. + +.Description + Provides a flattened, user-friendly interface over + Get-MgBetaPolicyCrossTenantAccessPolicyDefaultM365Capability. + + When -CapabilityId is omitted, all capability entries in the default policy + are returned. When -CapabilityId is supplied, only that specific entry is returned. + +.Parameter CapabilityId + The OData type name / key of the specific M365 capability to retrieve + (e.g. "crossTenantCalendarAvailabilityBasic"). + When omitted, all capabilities in the default policy are returned. + +.Example + # List all default M365 capabilities + Get-DefaultM365XTAPCapability + +.Example + # Get a specific default capability + Get-DefaultM365XTAPCapability -CapabilityId "crossTenantCalendarAvailabilityBasic" + +.Outputs + Microsoft.Graph.Beta.PowerShell.Models.IMicrosoftGraphM365CapabilityBase + +.Link + https://learn.microsoft.com/en-us/graph/api/crosstenantaccesspolicydefaultconfiguration-list-m365capabilities + https://learn.microsoft.com/en-us/powershell/module/microsoft.graph.beta.identity.signins/get-mgbetapolicycrosstenantaccesspolicydefaultm365capability +#> +function Get-DefaultM365XTAPCapability { + [OutputType([Microsoft.Graph.Beta.PowerShell.Models.IMicrosoftGraphM365CapabilityBase])] + [CmdletBinding(DefaultParameterSetName = 'List', + PositionalBinding = $false)] + param( + + [Parameter(Mandatory = $true, ParameterSetName = 'Get')] + [System.String] + # The OData type name / key of the specific M365 capability to retrieve. + ${CapabilityId}, + + # ── Pass-through list/query parameters ──────────────────────────── + [Parameter(ParameterSetName = 'List')] + [System.String] + # OData $filter expression. + ${Filter}, + + [Parameter(ParameterSetName = 'List')] + [System.String[]] + # Properties to sort by (OData $orderby). + ${Sort}, + + [Parameter(ParameterSetName = 'List')] + [System.Int32] + # Maximum number of items to return per page. + ${Top}, + + [Parameter(ParameterSetName = 'List')] + [System.Int32] + # Number of items to skip. + ${Skip}, + + [Parameter(ParameterSetName = 'List')] + [System.Management.Automation.SwitchParameter] + # Return all pages of results. + ${All}, + + [Parameter(ParameterSetName = 'List')] + [System.String] + # Variable to store the total item count. + ${CountVariable}, + + [Parameter(ParameterSetName = 'List')] + [System.Int32] + # Page size for automatic pagination. + ${PageSize}, + + # ── Pipeline / runtime ──────────────────────────────────────────── + [Parameter(DontShow)] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Management.Automation.SwitchParameter] + ${Break}, + + [Parameter(DontShow)] + [ValidateNotNull()] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [Microsoft.Graph.Beta.PowerShell.Runtime.SendAsyncStep[]] + ${HttpPipelineAppend}, + + [Parameter(DontShow)] + [ValidateNotNull()] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [Microsoft.Graph.Beta.PowerShell.Runtime.SendAsyncStep[]] + ${HttpPipelinePrepend}, + + [Parameter(DontShow)] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Uri] + ${Proxy}, + + [Parameter(DontShow)] + [ValidateNotNull()] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Management.Automation.PSCredential] + ${ProxyCredential}, + + [Parameter(DontShow)] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Management.Automation.SwitchParameter] + ${ProxyUseDefaultCredentials} + ) + + begin { + } + + process { + $null = $PSBoundParameters.Remove('CapabilityId') + + if ($PSCmdlet.ParameterSetName -eq 'Get') { + Write-Verbose "Getting default XTAP M365 capability '$CapabilityId'." + $result = Get-MgBetaPolicyCrossTenantAccessPolicyDefaultM365Capability ` + -M365CapabilityBaseName $CapabilityId ` + @PSBoundParameters + if ($null -ne $result) { ConvertTo-EntraXTAPM365CapabilityFlatOutput -Result $result } + } else { + Write-Verbose "Listing all default XTAP M365 capabilities." + Get-MgBetaPolicyCrossTenantAccessPolicyDefaultM365Capability @PSBoundParameters | ForEach-Object { + ConvertTo-EntraXTAPM365CapabilityFlatOutput -Result $_ + } + } + } + + end { + } +} diff --git a/src/Identity.SignIns/beta/custom/Get-PartnerEntraXTAP.ps1 b/src/Identity.SignIns/beta/custom/Get-PartnerEntraXTAP.ps1 new file mode 100644 index 00000000000..9bc5feb6a3a --- /dev/null +++ b/src/Identity.SignIns/beta/custom/Get-PartnerEntraXTAP.ps1 @@ -0,0 +1,153 @@ +# ---------------------------------------------------------------------------------- +# +# Copyright Microsoft Corporation +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ---------------------------------------------------------------------------------- + +<# +.Synopsis + Gets one or all Cross-Tenant Access Policy (XTAP) partner configurations. + +.Description + Provides a flattened, user-friendly interface over + Get-MgBetaPolicyCrossTenantAccessPolicyPartner. + + When -PartnerTenantId is omitted all partner configurations are returned. + When -PartnerTenantId is supplied only that specific partner entry is returned. + +.Parameter PartnerTenantId + The tenant ID (GUID) of the partner whose XTAP configuration is to be retrieved. + When omitted, all partner configurations are returned. + +.Example + # List all partner XTAP configurations + Get-PartnerEntraXTAP + +.Example + # Get a specific partner XTAP configuration + Get-PartnerEntraXTAP -PartnerTenantId "3d0f5dec-5d3d-455c-8016-e2af1ae4d31a" + +.Outputs + Microsoft.Graph.Beta.PowerShell.Models.IMicrosoftGraphCrossTenantAccessPolicyConfigurationPartner + +.Link + https://learn.microsoft.com/en-us/graph/api/crosstenantaccesspolicy-list-partners + https://learn.microsoft.com/en-us/powershell/module/microsoft.graph.beta.identity.signins/get-mgbetapolicycrosstenantaccesspolicypartner +#> +function Get-PartnerEntraXTAP { + [OutputType([Microsoft.Graph.Beta.PowerShell.Models.IMicrosoftGraphCrossTenantAccessPolicyConfigurationPartner])] + [CmdletBinding(DefaultParameterSetName = 'List', + PositionalBinding = $false)] + param( + + [Parameter(Mandatory = $true, ParameterSetName = 'Get')] + [ValidateScript({ + [System.Guid]::TryParse($_, [ref][System.Guid]::Empty) -or + $(throw "'$_' is not a valid GUID. PartnerTenantId must be a valid GUID.") + })] + [System.String] + # The partner tenant ID (GUID) to retrieve. + ${PartnerTenantId}, + + # ── List query parameters ───────────────────────────────────────── + [Parameter(ParameterSetName = 'List')] + [System.String] + # OData $filter expression. + ${Filter}, + + [Parameter(ParameterSetName = 'List')] + [System.String[]] + # Properties to sort by (OData $orderby). + ${Sort}, + + [Parameter(ParameterSetName = 'List')] + [System.Int32] + # Maximum number of items to return per page. + ${Top}, + + [Parameter(ParameterSetName = 'List')] + [System.Int32] + # Number of items to skip. + ${Skip}, + + [Parameter(ParameterSetName = 'List')] + [System.Management.Automation.SwitchParameter] + # Return all pages of results. + ${All}, + + [Parameter(ParameterSetName = 'List')] + [System.String] + # Variable to store the total item count. + ${CountVariable}, + + [Parameter(ParameterSetName = 'List')] + [System.Int32] + # Page size for automatic pagination. + ${PageSize}, + + # ── Pipeline / runtime ──────────────────────────────────────────── + [Parameter(DontShow)] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Management.Automation.SwitchParameter] + ${Break}, + + [Parameter(DontShow)] + [ValidateNotNull()] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [Microsoft.Graph.Beta.PowerShell.Runtime.SendAsyncStep[]] + ${HttpPipelineAppend}, + + [Parameter(DontShow)] + [ValidateNotNull()] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [Microsoft.Graph.Beta.PowerShell.Runtime.SendAsyncStep[]] + ${HttpPipelinePrepend}, + + [Parameter(DontShow)] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Uri] + ${Proxy}, + + [Parameter(DontShow)] + [ValidateNotNull()] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Management.Automation.PSCredential] + ${ProxyCredential}, + + [Parameter(DontShow)] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Management.Automation.SwitchParameter] + ${ProxyUseDefaultCredentials} + ) + + begin { + } + + process { + $null = $PSBoundParameters.Remove('PartnerTenantId') + + if ($PSCmdlet.ParameterSetName -eq 'Get') { + Write-Verbose "Getting XTAP partner configuration for tenant '$PartnerTenantId'." + $result = Get-MgBetaPolicyCrossTenantAccessPolicyPartner ` + -CrossTenantAccessPolicyConfigurationPartnerTenantId $PartnerTenantId ` + @PSBoundParameters + if ($null -ne $result) { ConvertTo-EntraXTAPFlatOutput -Result $result -IsPartner } + } else { + Write-Verbose "Listing all XTAP partner configurations." + Get-MgBetaPolicyCrossTenantAccessPolicyPartner @PSBoundParameters | ForEach-Object { + ConvertTo-EntraXTAPFlatOutput -Result $_ -IsPartner + } + } + } + + end { + } +} diff --git a/src/Identity.SignIns/beta/custom/Get-PartnerM365XTAPCapability.ps1 b/src/Identity.SignIns/beta/custom/Get-PartnerM365XTAPCapability.ps1 new file mode 100644 index 00000000000..c6a935372ae --- /dev/null +++ b/src/Identity.SignIns/beta/custom/Get-PartnerM365XTAPCapability.ps1 @@ -0,0 +1,170 @@ +# ---------------------------------------------------------------------------------- +# +# Copyright Microsoft Corporation +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ---------------------------------------------------------------------------------- + +<# +.Synopsis + Gets one or all Microsoft 365 capability entries on a Cross-Tenant Access Policy + (XTAP) partner configuration. + +.Description + Provides a flattened, user-friendly interface over + Get-MgBetaPolicyCrossTenantAccessPolicyPartnerM365Capability. + + When -CapabilityId is omitted, all capability entries for the specified partner + tenant are returned. When -CapabilityId is supplied, only that specific entry + is returned. + +.Parameter PartnerTenantId + The partner tenant ID (GUID) that identifies the cross-tenant access policy + partner entry whose M365 capabilities are to be retrieved. + +.Parameter CapabilityId + The OData type name / key of the specific M365 capability to retrieve + (e.g. "crossTenantCalendarAvailabilityBasic"). + When omitted, all capabilities for the partner are returned. + +.Example + # List all M365 capabilities for a partner tenant + Get-PartnerM365XTAPCapability -PartnerTenantId "3d0f5dec-5d3d-455c-8016-e2af1ae4d31a" + +.Example + # Get a specific capability + Get-PartnerM365XTAPCapability ` + -PartnerTenantId "3d0f5dec-5d3d-455c-8016-e2af1ae4d31a" ` + -CapabilityId "crossTenantCalendarAvailabilityBasic" + +.Outputs + Microsoft.Graph.Beta.PowerShell.Models.IMicrosoftGraphM365CapabilityBase + +.Link + https://learn.microsoft.com/en-us/graph/api/crosstenantaccesspolicyconfigurationpartner-list-m365capabilities + https://learn.microsoft.com/en-us/powershell/module/microsoft.graph.beta.identity.signins/get-mgbetapolicycrosstenantaccesspolicypartnerm365capability +#> +function Get-PartnerM365XTAPCapability { + [OutputType([Microsoft.Graph.Beta.PowerShell.Models.IMicrosoftGraphM365CapabilityBase])] + [CmdletBinding(DefaultParameterSetName = 'List', + PositionalBinding = $false)] + param( + + [Parameter(Mandatory = $true, ParameterSetName = 'List')] + [Parameter(Mandatory = $true, ParameterSetName = 'Get')] + [ValidateScript({ + [System.Guid]::TryParse($_, [ref][System.Guid]::Empty) -or + $(throw "'$_' is not a valid GUID. PartnerTenantId must be a valid GUID.") + })] + [System.String] + # The partner tenant ID (GUID) for the cross-tenant access policy entry. + ${PartnerTenantId}, + + [Parameter(Mandatory = $true, ParameterSetName = 'Get')] + [System.String] + # The OData type name / key of the specific M365 capability to retrieve. + ${CapabilityId}, + + # ── Pass-through list/query parameters ──────────────────────────── + [Parameter(ParameterSetName = 'List')] + [System.String] + # OData $filter expression. + ${Filter}, + + [Parameter(ParameterSetName = 'List')] + [System.String[]] + # Properties to sort by (OData $orderby). + ${Sort}, + + [Parameter(ParameterSetName = 'List')] + [System.Int32] + # Maximum number of items to return per page. + ${Top}, + + [Parameter(ParameterSetName = 'List')] + [System.Int32] + # Number of items to skip. + ${Skip}, + + [Parameter(ParameterSetName = 'List')] + [System.Management.Automation.SwitchParameter] + # Return all pages of results. + ${All}, + + [Parameter(ParameterSetName = 'List')] + [System.String] + # Variable to store the total item count. + ${CountVariable}, + + [Parameter(ParameterSetName = 'List')] + [System.Int32] + # Page size for automatic pagination. + ${PageSize}, + + # ── Pipeline / runtime ──────────────────────────────────────────── + [Parameter(DontShow)] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Management.Automation.SwitchParameter] + ${Break}, + + [Parameter(DontShow)] + [ValidateNotNull()] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [Microsoft.Graph.Beta.PowerShell.Runtime.SendAsyncStep[]] + ${HttpPipelineAppend}, + + [Parameter(DontShow)] + [ValidateNotNull()] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [Microsoft.Graph.Beta.PowerShell.Runtime.SendAsyncStep[]] + ${HttpPipelinePrepend}, + + [Parameter(DontShow)] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Uri] + ${Proxy}, + + [Parameter(DontShow)] + [ValidateNotNull()] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Management.Automation.PSCredential] + ${ProxyCredential}, + + [Parameter(DontShow)] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Management.Automation.SwitchParameter] + ${ProxyUseDefaultCredentials} + ) + + begin { + } + + process { + $null = $PSBoundParameters.Remove('PartnerTenantId') + $null = $PSBoundParameters.Remove('CapabilityId') + + $splat = @{ + CrossTenantAccessPolicyConfigurationPartnerTenantId = $PartnerTenantId + } + + if ($PSCmdlet.ParameterSetName -eq 'Get') { + $splat['M365CapabilityBaseName'] = $CapabilityId + } + + Write-Verbose "Getting XTAP M365 capability $(if ($CapabilityId) { "'$CapabilityId' " })for partner tenant '$PartnerTenantId'." + + Get-MgBetaPolicyCrossTenantAccessPolicyPartnerM365Capability @splat @PSBoundParameters | ForEach-Object { + ConvertTo-EntraXTAPM365CapabilityFlatOutput -Result $_ -IsPartner + } + } + + end { + } +} diff --git a/src/Identity.SignIns/beta/custom/New-DefaultM365XTAPCapability.ps1 b/src/Identity.SignIns/beta/custom/New-DefaultM365XTAPCapability.ps1 new file mode 100644 index 00000000000..3ff5b3b295d --- /dev/null +++ b/src/Identity.SignIns/beta/custom/New-DefaultM365XTAPCapability.ps1 @@ -0,0 +1,260 @@ +# ---------------------------------------------------------------------------------- +# +# Copyright Microsoft Corporation +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ---------------------------------------------------------------------------------- + +<# +.Synopsis + Creates a new Microsoft 365 capability entry on the default Cross-Tenant Access + Policy (XTAP) configuration for the tenant. + +.Description + Provides a flattened, user-friendly interface over + New-MgBetaPolicyCrossTenantAccessPolicyDefaultM365Capability. + + Instead of building the nested payload manually, callers supply discrete parameters + for the capability ID, inbound access flag, and the users and groups to include or + exclude. The cmdlet assembles the correct Graph API body, constructs the + strongly-typed model objects, and delegates to the auto-generated cmdlet. + + The default policy applies tenant-wide and does not target a specific partner. + The 'name' field (Key) corresponds to the OData type of the capability. + + Known CapabilityId values (from graph.microsoft.com/beta/$metadata): + Calendar: + crossTenantCalendarAvailabilityBasic + crossTenantCalendarAvailabilityLimitedDetails + crossTenantCalendarSharingFreeBusyDetail + crossTenantCalendarSharingFreeBusyReviewer + crossTenantCalendarSharingFreeBusySimple + Mail: + crossTenantMailTipsAll + crossTenantMailTipsLimited + Other: + crossTenantMigration + crossTenantOpenProfileCard + crossTenantPlacesDeskBooking + crossTenantPlacesRoomBooking + +.Parameter CapabilityId + The OData type discriminator and key for the M365 capability to configure. + This becomes both the '@odata.type' and the 'name' field in the request body. + +.Parameter IsAllowed + Whether inbound access is allowed ($true) or blocked ($false) for the capability. + +.Parameter IncludedUsers + User object IDs or the special value "All" to include in the inbound access scope. + +.Parameter ExcludedUsers + User object IDs to exclude from the inbound access scope. + +.Parameter IncludedGroups + Group object IDs or the special value "All" to include in the inbound access scope. + +.Parameter ExcludedGroups + Group object IDs to exclude from the inbound access scope. + +.Example + # Allow basic calendar availability inbound for all users by default + New-DefaultM365XTAPCapability ` + -CapabilityId "crossTenantCalendarAvailabilityBasic" ` + -IsAllowed $true ` + -IncludedUsers "All" + +.Example + # Allow free/busy detail sharing for specific users, exclude a group + New-DefaultM365XTAPCapability ` + -CapabilityId "crossTenantCalendarSharingFreeBusyDetail" ` + -IsAllowed $true ` + -IncludedUsers "6f546279-4da5-4b53-a095-09ea0cef9971","11111111-2222-3333-4444-555555555555" ` + -ExcludedGroups "0be493dc-cb56-4a53-936f-9cf64410b8b0" + +.Example + # Block all inbound MailTips by default + New-DefaultM365XTAPCapability ` + -CapabilityId "crossTenantMailTipsAll" ` + -IsAllowed $false ` + -IncludedUsers "All" + +.Outputs + Microsoft.Graph.Beta.PowerShell.Models.IMicrosoftGraphM365CapabilityBase + +.Link + https://learn.microsoft.com/en-us/graph/api/crosstenantaccesspolicydefaultconfiguration-post-m365capabilities + https://learn.microsoft.com/en-us/powershell/module/microsoft.graph.beta.identity.signins/new-mgbetapolicycrosstenantaccesspolicydefaultm365capability +#> +function New-DefaultM365XTAPCapability { + [OutputType([Microsoft.Graph.Beta.PowerShell.Models.IMicrosoftGraphM365CapabilityBase])] + [CmdletBinding(DefaultParameterSetName = 'CreateExpanded', + PositionalBinding = $false, + SupportsShouldProcess, + ConfirmImpact = 'Medium')] + param( + + # ── Capability ID ───────────────────────────────────────────────── + [Parameter(Mandatory = $true, ParameterSetName = 'CreateExpanded')] + [System.String] + # OData type discriminator and key for the M365 capability to configure. + ${CapabilityId}, + + # ── Inbound access ──────────────────────────────────────────────── + [Parameter(Mandatory = $true, ParameterSetName = 'CreateExpanded')] + [System.Boolean] + # Whether inbound access is allowed ($true) or blocked ($false). + ${IsAllowed}, + + [Parameter(ParameterSetName = 'CreateExpanded')] + [ValidateScript({ + foreach ($item in $_) { + if ($item -ne 'All' -and -not [System.Guid]::TryParse($item, [ref][System.Guid]::Empty)) { + throw "'$item' is not valid. Each value must be a GUID or 'All'." + } + } + $true + })] + [System.String[]] + # User object IDs or "All" to include in the inbound access scope. + ${IncludedUsers}, + + [Parameter(ParameterSetName = 'CreateExpanded')] + [ValidateScript({ + foreach ($item in $_) { + if ($item -ne 'All' -and -not [System.Guid]::TryParse($item, [ref][System.Guid]::Empty)) { + throw "'$item' is not valid. Each value must be a GUID or 'All'." + } + } + $true + })] + [System.String[]] + # User object IDs to exclude from the inbound access scope. + ${ExcludedUsers}, + + [Parameter(ParameterSetName = 'CreateExpanded')] + [ValidateScript({ + foreach ($item in $_) { + if ($item -ne 'All' -and -not [System.Guid]::TryParse($item, [ref][System.Guid]::Empty)) { + throw "'$item' is not valid. Each value must be a GUID or 'All'." + } + } + $true + })] + [System.String[]] + # Group object IDs or "All" to include in the inbound access scope. + ${IncludedGroups}, + + [Parameter(ParameterSetName = 'CreateExpanded')] + [ValidateScript({ + foreach ($item in $_) { + if ($item -ne 'All' -and -not [System.Guid]::TryParse($item, [ref][System.Guid]::Empty)) { + throw "'$item' is not valid. Each value must be a GUID or 'All'." + } + } + $true + })] + [System.String[]] + # Group object IDs to exclude from the inbound access scope. + ${ExcludedGroups}, + + # ── Pipeline / runtime ──────────────────────────────────────────── + [Parameter(DontShow)] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Management.Automation.SwitchParameter] + ${Break}, + + [Parameter(DontShow)] + [ValidateNotNull()] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [Microsoft.Graph.Beta.PowerShell.Runtime.SendAsyncStep[]] + ${HttpPipelineAppend}, + + [Parameter(DontShow)] + [ValidateNotNull()] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [Microsoft.Graph.Beta.PowerShell.Runtime.SendAsyncStep[]] + ${HttpPipelinePrepend}, + + [Parameter(DontShow)] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Uri] + ${Proxy}, + + [Parameter(DontShow)] + [ValidateNotNull()] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Management.Automation.PSCredential] + ${ProxyCredential}, + + [Parameter(DontShow)] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Management.Automation.SwitchParameter] + ${ProxyUseDefaultCredentials} + ) + + begin { + } + + process { + # ------------------------------------------------------------------ + # Helper: build MicrosoftGraphM365CapabilityResourceScope objects + # from a plain array of IDs and the implied resourceType string. + # ------------------------------------------------------------------ + function Build-ResourceScopes { + param( + [string[]] $Ids, + [string] $ResourceType + ) + $results = @() + foreach ($id in $Ids) { + if ([string]::IsNullOrWhiteSpace($id)) { continue } + $scope = New-Object Microsoft.Graph.Beta.PowerShell.Models.MicrosoftGraphM365CapabilityResourceScope + $scope.ResourceId = $id.Trim() + $scope.ResourceType = $ResourceType + $results += $scope + } + return ,$results + } + + $includedUserScopes = if ($null -ne $IncludedUsers -and $IncludedUsers.Count -gt 0) { Build-ResourceScopes -Ids $IncludedUsers -ResourceType 'user' } else { @() } + $includedGroupScopes = if ($null -ne $IncludedGroups -and $IncludedGroups.Count -gt 0) { Build-ResourceScopes -Ids $IncludedGroups -ResourceType 'group' } else { @() } + $excludedUserScopes = if ($null -ne $ExcludedUsers -and $ExcludedUsers.Count -gt 0) { Build-ResourceScopes -Ids $ExcludedUsers -ResourceType 'user' } else { @() } + $excludedGroupScopes = if ($null -ne $ExcludedGroups -and $ExcludedGroups.Count -gt 0) { Build-ResourceScopes -Ids $ExcludedGroups -ResourceType 'group' } else { @() } + + $resourceScopes = New-Object Microsoft.Graph.Beta.PowerShell.Models.MicrosoftGraphM365CapabilityResourceScopes + $resourceScopes.Included = @($includedUserScopes + $includedGroupScopes) + $resourceScopes.Excluded = @($excludedUserScopes + $excludedGroupScopes) + + $inboundAccess = New-Object Microsoft.Graph.Beta.PowerShell.Models.MicrosoftGraphM365CapabilityInboundAccess + $inboundAccess.IsAllowed = $IsAllowed + $inboundAccess.ResourceScopes = $resourceScopes + + Write-Verbose "Creating default XTAP M365 capability '$CapabilityId'." + Write-Verbose "IsAllowed: $IsAllowed | IncludedUsers: $($IncludedUsers -join ', ') | IncludedGroups: $($IncludedGroups -join ', ') | ExcludedUsers: $($ExcludedUsers -join ', ') | ExcludedGroups: $($ExcludedGroups -join ', ')" + + foreach ($key in @('CapabilityId','IsAllowed', + 'IncludedUsers','ExcludedUsers','IncludedGroups','ExcludedGroups')) { + $null = $PSBoundParameters.Remove($key) + } + + if ($PSCmdlet.ShouldProcess($CapabilityId, "New-DefaultM365XTAPCapability")) { + $result = New-MgBetaPolicyCrossTenantAccessPolicyDefaultM365Capability ` + -InboundAccess $inboundAccess ` + -Name $CapabilityId ` + -AdditionalProperties @{ '@odata.type' = "microsoft.graph.$CapabilityId" } ` + @PSBoundParameters + if ($null -ne $result) { ConvertTo-EntraXTAPM365CapabilityFlatOutput -Result $result } + } + } + + end { + } +} diff --git a/src/Identity.SignIns/beta/custom/New-PartnerEntraXTAP.ps1 b/src/Identity.SignIns/beta/custom/New-PartnerEntraXTAP.ps1 new file mode 100644 index 00000000000..7da597d19c7 --- /dev/null +++ b/src/Identity.SignIns/beta/custom/New-PartnerEntraXTAP.ps1 @@ -0,0 +1,131 @@ +# ---------------------------------------------------------------------------------- +# Copyright Microsoft Corporation - Licensed under the Apache License, Version 2.0 +# ---------------------------------------------------------------------------------- + +function New-PartnerEntraXTAP { + [OutputType([Microsoft.Graph.Beta.PowerShell.Models.IMicrosoftGraphCrossTenantAccessPolicyConfigurationPartner])] + [CmdletBinding(DefaultParameterSetName = 'Expanded', + PositionalBinding = $false, SupportsShouldProcess, ConfirmImpact = 'Medium')] + param( + [Parameter(Mandatory = $true, ParameterSetName = 'Expanded')] + [ValidateScript({ + [System.Guid]::TryParse($_, [ref][System.Guid]::Empty) -or + $(throw "'$_' is not a valid GUID. PartnerTenantId must be a valid GUID.") + })] + [System.String] + ${PartnerTenantId}, + + [Parameter(ParameterSetName = 'Expanded')] + [ValidateSet('Allowed', 'Blocked')] + [System.String] + ${M365CollaborationInbound}, + + [Parameter(ParameterSetName = 'Expanded')] + [System.String[]] + ${M365CollaborationInboundTargetUsers}, + + [Parameter(ParameterSetName = 'Expanded')] + [ValidateSet('Allowed', 'Blocked')] + [System.String] + ${M365CollaborationOutbound}, + + [Parameter(ParameterSetName = 'Expanded')] + [System.String[]] + ${M365CollaborationOutboundTargetUsers}, + + [Parameter(ParameterSetName = 'Expanded')] + [System.String[]] + ${M365CollaborationOutboundTargetGroups}, + + [Parameter(ParameterSetName = 'Expanded')] + [ValidateSet('Allowed', 'Blocked')] + [System.String] + ${AppServiceConnectInbound}, + + [Parameter(ParameterSetName = 'Expanded')] + [System.String[]] + ${AppServiceConnectInboundTargetApplications}, + + [Parameter(DontShow)] [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] [System.Management.Automation.SwitchParameter] ${Break}, + [Parameter(DontShow)] [ValidateNotNull()] [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] [Microsoft.Graph.Beta.PowerShell.Runtime.SendAsyncStep[]] ${HttpPipelineAppend}, + [Parameter(DontShow)] [ValidateNotNull()] [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] [Microsoft.Graph.Beta.PowerShell.Runtime.SendAsyncStep[]] ${HttpPipelinePrepend}, + [Parameter(DontShow)] [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] [System.Uri] ${Proxy}, + [Parameter(DontShow)] [ValidateNotNull()] [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] [System.Management.Automation.PSCredential] ${ProxyCredential}, + [Parameter(DontShow)] [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] [System.Management.Automation.SwitchParameter] ${ProxyUseDefaultCredentials} + ) + + begin {} + + process { + function Build-TargetConfiguration { + param([string]$AccessType, [string[]]$Ids, [string]$TargetType) + if ([string]::IsNullOrEmpty($AccessType) -or $null -eq $Ids -or $Ids.Count -eq 0) { return $null } + $targets = @() + foreach ($id in $Ids) { + $t = New-Object Microsoft.Graph.Beta.PowerShell.Models.MicrosoftGraphCrossTenantAccessPolicyTarget + $t.Target = $id.Trim(); $t.TargetType = $TargetType; $targets += $t + } + $config = New-Object Microsoft.Graph.Beta.PowerShell.Models.MicrosoftGraphCrossTenantAccessPolicyTargetConfiguration + $config.AccessType = $AccessType.ToLower(); $config.Targets = $targets + return $config + } + + foreach ($key in @('PartnerTenantId', 'M365CollaborationInbound', 'M365CollaborationInboundTargetUsers', 'M365CollaborationOutbound', 'M365CollaborationOutboundTargetUsers', 'M365CollaborationOutboundTargetGroups', 'AppServiceConnectInbound', 'AppServiceConnectInboundTargetApplications')) { $null = $PSBoundParameters.Remove($key) } + + # At least one flag must be provided + if (-not $M365CollaborationInbound -and -not $M365CollaborationOutbound -and -not $AppServiceConnectInbound) { + throw 'At least one of -M365CollaborationInbound, -M365CollaborationOutbound, or -AppServiceConnectInbound must be specified.' + } + # Companion validations + if ($M365CollaborationInbound -and (-not $M365CollaborationInboundTargetUsers -or $M365CollaborationInboundTargetUsers.Count -eq 0)) { + throw '-M365CollaborationInboundTargetUsers is required when -M365CollaborationInbound is specified.' + } + if ($M365CollaborationOutbound -and + (-not $M365CollaborationOutboundTargetUsers -or $M365CollaborationOutboundTargetUsers.Count -eq 0) -and + (-not $M365CollaborationOutboundTargetGroups -or $M365CollaborationOutboundTargetGroups.Count -eq 0)) { + throw 'At least one of -M365CollaborationOutboundTargetUsers or -M365CollaborationOutboundTargetGroups is required when -M365CollaborationOutbound is specified.' + } + if ($AppServiceConnectInbound -and (-not $AppServiceConnectInboundTargetApplications -or $AppServiceConnectInboundTargetApplications.Count -eq 0)) { + throw '-AppServiceConnectInboundTargetApplications is required when -AppServiceConnectInbound is specified.' + } + + # Build M365 inbound + $inboundUserConfig = Build-TargetConfiguration -AccessType $M365CollaborationInbound -Ids $M365CollaborationInboundTargetUsers -TargetType 'user' + + # Build M365 outbound (merge users + groups) + $outboundConfig = $null + if ($M365CollaborationOutbound) { + $userConfig = Build-TargetConfiguration -AccessType $M365CollaborationOutbound -Ids $M365CollaborationOutboundTargetUsers -TargetType 'user' + $groupConfig = Build-TargetConfiguration -AccessType $M365CollaborationOutbound -Ids $M365CollaborationOutboundTargetGroups -TargetType 'group' + $mergedTargets = @() + if ($null -ne $userConfig) { $mergedTargets += $userConfig.Targets } + if ($null -ne $groupConfig) { $mergedTargets += $groupConfig.Targets } + $outboundConfig = New-Object Microsoft.Graph.Beta.PowerShell.Models.MicrosoftGraphCrossTenantAccessPolicyTargetConfiguration + $outboundConfig.AccessType = $M365CollaborationOutbound.ToLower() + $outboundConfig.Targets = [Microsoft.Graph.Beta.PowerShell.Models.IMicrosoftGraphCrossTenantAccessPolicyTarget[]]$mergedTargets + } + + # Build App Service Connect + $appServiceConnect = $null + if ($AppServiceConnectInbound) { + $appConfig = Build-TargetConfiguration -AccessType $AppServiceConnectInbound -Ids $AppServiceConnectInboundTargetApplications -TargetType 'application' + $appServiceConnect = New-Object Microsoft.Graph.Beta.PowerShell.Models.MicrosoftGraphCrossTenantAccessPolicyAppServiceConnectSetting + $appServiceConnect.Applications = $appConfig + } + + $m365Inbound = $null; $m365Outbound = $null + if ($null -ne $inboundUserConfig) { $m365Inbound = New-Object Microsoft.Graph.Beta.PowerShell.Models.MicrosoftGraphCrossTenantAccessPolicyM365CollaborationInboundSetting; $m365Inbound.Users = $inboundUserConfig } + if ($null -ne $outboundConfig) { $m365Outbound = New-Object Microsoft.Graph.Beta.PowerShell.Models.MicrosoftGraphCrossTenantAccessPolicyM365CollaborationOutboundSetting; $m365Outbound.UsersAndGroups = $outboundConfig } + + if ($PSCmdlet.ShouldProcess($PartnerTenantId, 'New-PartnerEntraXTAP')) { + $splat = @{ TenantId = $PartnerTenantId } + if ($null -ne $m365Inbound) { $splat['M365CollaborationInbound'] = $m365Inbound } + if ($null -ne $m365Outbound) { $splat['M365CollaborationOutbound'] = $m365Outbound } + if ($null -ne $appServiceConnect) { $splat['AppServiceConnectInbound'] = $appServiceConnect } + $result = New-MgBetaPolicyCrossTenantAccessPolicyPartner @splat @PSBoundParameters + if ($null -ne $result) { ConvertTo-EntraXTAPFlatOutput -Result $result -IsPartner } + } + } + + end {} +} \ No newline at end of file diff --git a/src/Identity.SignIns/beta/custom/New-PartnerM365XTAPCapability.ps1 b/src/Identity.SignIns/beta/custom/New-PartnerM365XTAPCapability.ps1 new file mode 100644 index 00000000000..9d4fbff3c44 --- /dev/null +++ b/src/Identity.SignIns/beta/custom/New-PartnerM365XTAPCapability.ps1 @@ -0,0 +1,301 @@ +# ---------------------------------------------------------------------------------- +# +# Copyright Microsoft Corporation +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ---------------------------------------------------------------------------------- + +<# +.Synopsis + Creates a new Microsoft 365 capability entry on a Cross-Tenant Access Policy (XTAP) + partner configuration. + +.Description + Provides a flattened, user-friendly interface over + New-MgBetaPolicyCrossTenantAccessPolicyPartnerM365Capability. + + Instead of building the nested payload manually, callers supply discrete parameters + for the capability ID, inbound access flag, and the users and groups to include or + exclude. The cmdlet assembles the correct Graph API body, constructs the + strongly-typed model objects, and delegates to the auto-generated cmdlet. + + The Graph API m365CapabilityBase type supports inbound access only. + The 'name' field (Key) corresponds to the OData type of the capability. + + Known CapabilityId values (from graph.microsoft.com/beta/$metadata): + Calendar: + crossTenantCalendarAvailabilityBasic + crossTenantCalendarAvailabilityLimitedDetails + crossTenantCalendarSharingFreeBusyDetail + crossTenantCalendarSharingFreeBusyReviewer + crossTenantCalendarSharingFreeBusySimple + Mail: + crossTenantMailTipsAll + crossTenantMailTipsLimited + Other: + crossTenantMigration + crossTenantOpenProfileCard + crossTenantPlacesDeskBooking + crossTenantPlacesRoomBooking + +.Parameter PartnerTenantId + The partner tenant ID (GUID) that identifies the cross-tenant access policy + partner entry to which this M365 capability will be added. + +.Parameter CapabilityId + The OData type discriminator and key for the M365 capability to configure. + This becomes both the '@odata.type' and the 'name' field in the request body. + +.Parameter IsAllowed + Whether inbound access is allowed ($true) or blocked ($false) for the capability. + +.Parameter IncludedUsers + User object IDs or the special value "All" whose inbound access is configured + by this capability entry. + +.Parameter ExcludedUsers + User object IDs to explicitly exclude from the inbound access scope. + +.Parameter IncludedGroups + Group object IDs or the special value "All" whose inbound access is configured + by this capability entry. + +.Parameter ExcludedGroups + Group object IDs to explicitly exclude from the inbound access scope. + +.Example + # Allow basic calendar availability inbound for all users from a partner tenant + New-PartnerM365XTAPCapability ` + -PartnerTenantId "3d0f5dec-5d3d-455c-8016-e2af1ae4d31a" ` + -CapabilityId "crossTenantCalendarAvailabilityBasic" ` + -IsAllowed $true ` + -IncludedUsers "All" + +.Example + # Allow free/busy detail sharing inbound for specific users, exclude a group + New-PartnerM365XTAPCapability ` + -PartnerTenantId "3d0f5dec-5d3d-455c-8016-e2af1ae4d31a" ` + -CapabilityId "crossTenantCalendarSharingFreeBusyDetail" ` + -IsAllowed $true ` + -IncludedUsers "6f546279-4da5-4b53-a095-09ea0cef9971","11111111-2222-3333-4444-555555555555" ` + -ExcludedGroups "0be493dc-cb56-4a53-936f-9cf64410b8b0" + +.Example + # Block all inbound MailTips for a partner tenant + New-PartnerM365XTAPCapability ` + -PartnerTenantId "3d0f5dec-5d3d-455c-8016-e2af1ae4d31a" ` + -CapabilityId "crossTenantMailTipsAll" ` + -IsAllowed $false ` + -IncludedUsers "All" + +.Example + # Allow open profile card inbound for a specific group + New-PartnerM365XTAPCapability ` + -PartnerTenantId "3d0f5dec-5d3d-455c-8016-e2af1ae4d31a" ` + -CapabilityId "crossTenantOpenProfileCard" ` + -IsAllowed $true ` + -IncludedGroups "0be493dc-cb56-4a53-936f-9cf64410b8b0" + +.Outputs + Microsoft.Graph.Beta.PowerShell.Models.IMicrosoftGraphM365CapabilityBase + +.Link + https://learn.microsoft.com/en-us/graph/api/crosstenantaccesspolicyconfigurationpartner-post-m365capabilities + https://learn.microsoft.com/en-us/powershell/module/microsoft.graph.beta.identity.signins/new-mgbetapolicycrosstenantaccesspolicypartnerm365capability +#> +function New-PartnerM365XTAPCapability { + [OutputType([Microsoft.Graph.Beta.PowerShell.Models.IMicrosoftGraphM365CapabilityBase])] + [CmdletBinding(DefaultParameterSetName = 'CreateExpanded', + PositionalBinding = $false, + SupportsShouldProcess, + ConfirmImpact = 'Medium')] + param( + + # ── Identity ────────────────────────────────────────────────────── + [Parameter(Mandatory = $true, ParameterSetName = 'CreateExpanded')] + [ValidateScript({ + [System.Guid]::TryParse($_, [ref][System.Guid]::Empty) -or + $(throw "'$_' is not a valid GUID. PartnerTenantId must be a valid GUID.") + })] + [System.String] + # The partner tenant ID (GUID) for the cross-tenant access policy entry. + ${PartnerTenantId}, + + # ── Capability ID ───────────────────────────────────────────────── + [Parameter(Mandatory = $true, ParameterSetName = 'CreateExpanded')] + [System.String] + # OData type discriminator and key for the M365 capability to configure. + ${CapabilityId}, + + # ── Inbound access ──────────────────────────────────────────────── + [Parameter(Mandatory = $true, ParameterSetName = 'CreateExpanded')] + [System.Boolean] + # Whether inbound access is allowed ($true) or blocked ($false). + ${IsAllowed}, + + [Parameter(ParameterSetName = 'CreateExpanded')] + [ValidateScript({ + foreach ($item in $_) { + if ($item -ne 'All' -and -not [System.Guid]::TryParse($item, [ref][System.Guid]::Empty)) { + throw "'$item' is not valid. Each value must be a GUID or 'All'." + } + } + $true + })] + [System.String[]] + # User object IDs or "All" to include in the inbound access scope. + ${IncludedUsers}, + + [Parameter(ParameterSetName = 'CreateExpanded')] + [ValidateScript({ + foreach ($item in $_) { + if ($item -ne 'All' -and -not [System.Guid]::TryParse($item, [ref][System.Guid]::Empty)) { + throw "'$item' is not valid. Each value must be a GUID or 'All'." + } + } + $true + })] + [System.String[]] + # User object IDs to exclude from the inbound access scope. + ${ExcludedUsers}, + + [Parameter(ParameterSetName = 'CreateExpanded')] + [ValidateScript({ + foreach ($item in $_) { + if ($item -ne 'All' -and -not [System.Guid]::TryParse($item, [ref][System.Guid]::Empty)) { + throw "'$item' is not valid. Each value must be a GUID or 'All'." + } + } + $true + })] + [System.String[]] + # Group object IDs or "All" to include in the inbound access scope. + ${IncludedGroups}, + + [Parameter(ParameterSetName = 'CreateExpanded')] + [ValidateScript({ + foreach ($item in $_) { + if ($item -ne 'All' -and -not [System.Guid]::TryParse($item, [ref][System.Guid]::Empty)) { + throw "'$item' is not valid. Each value must be a GUID or 'All'." + } + } + $true + })] + [System.String[]] + # Group object IDs to exclude from the inbound access scope. + ${ExcludedGroups}, + + # ── Pipeline / runtime (standard Graph module params) ───────────── + [Parameter(DontShow)] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Management.Automation.SwitchParameter] + # Wait for .NET debugger to attach. + ${Break}, + + [Parameter(DontShow)] + [ValidateNotNull()] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [Microsoft.Graph.Beta.PowerShell.Runtime.SendAsyncStep[]] + # SendAsync Pipeline Steps to be appended to the front of the pipeline. + ${HttpPipelineAppend}, + + [Parameter(DontShow)] + [ValidateNotNull()] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [Microsoft.Graph.Beta.PowerShell.Runtime.SendAsyncStep[]] + # SendAsync Pipeline Steps to be prepended to the front of the pipeline. + ${HttpPipelinePrepend}, + + [Parameter(DontShow)] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Uri] + # The URI for the proxy server to use. + ${Proxy}, + + [Parameter(DontShow)] + [ValidateNotNull()] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Management.Automation.PSCredential] + # Credentials for a proxy server to use for the remote call. + ${ProxyCredential}, + + [Parameter(DontShow)] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Management.Automation.SwitchParameter] + # Use the default credentials for the proxy. + ${ProxyUseDefaultCredentials} + ) + + begin { + } + + process { + # ------------------------------------------------------------------ + # Helper: build MicrosoftGraphM365CapabilityResourceScope objects + # from a plain array of IDs and the implied resourceType string. + # ------------------------------------------------------------------ + function Build-ResourceScopes { + param( + [string[]] $Ids, + [string] $ResourceType + ) + $results = @() + foreach ($id in $Ids) { + if ([string]::IsNullOrWhiteSpace($id)) { continue } + $scope = New-Object Microsoft.Graph.Beta.PowerShell.Models.MicrosoftGraphM365CapabilityResourceScope + $scope.ResourceId = $id.Trim() + $scope.ResourceType = $ResourceType + $results += $scope + } + return ,$results + } + + # ------------------------------------------------------------------ + # Merge included users + groups into one included scopes array, and + # excluded users + groups into one excluded scopes array. + # ------------------------------------------------------------------ + $includedUserScopes = if ($null -ne $IncludedUsers -and $IncludedUsers.Count -gt 0) { Build-ResourceScopes -Ids $IncludedUsers -ResourceType 'user' } else { @() } + $includedGroupScopes = if ($null -ne $IncludedGroups -and $IncludedGroups.Count -gt 0) { Build-ResourceScopes -Ids $IncludedGroups -ResourceType 'group' } else { @() } + $excludedUserScopes = if ($null -ne $ExcludedUsers -and $ExcludedUsers.Count -gt 0) { Build-ResourceScopes -Ids $ExcludedUsers -ResourceType 'user' } else { @() } + $excludedGroupScopes = if ($null -ne $ExcludedGroups -and $ExcludedGroups.Count -gt 0) { Build-ResourceScopes -Ids $ExcludedGroups -ResourceType 'group' } else { @() } + + $resourceScopes = New-Object Microsoft.Graph.Beta.PowerShell.Models.MicrosoftGraphM365CapabilityResourceScopes + $resourceScopes.Included = @($includedUserScopes + $includedGroupScopes) + $resourceScopes.Excluded = @($excludedUserScopes + $excludedGroupScopes) + + $inboundAccess = New-Object Microsoft.Graph.Beta.PowerShell.Models.MicrosoftGraphM365CapabilityInboundAccess + $inboundAccess.IsAllowed = $IsAllowed + $inboundAccess.ResourceScopes = $resourceScopes + + Write-Verbose "Creating XTAP M365 capability '$CapabilityId' for partner tenant '$PartnerTenantId'." + Write-Verbose "IsAllowed: $IsAllowed | IncludedUsers: $($IncludedUsers -join ', ') | IncludedGroups: $($IncludedGroups -join ', ') | ExcludedUsers: $($ExcludedUsers -join ', ') | ExcludedGroups: $($ExcludedGroups -join ', ')" + + # ------------------------------------------------------------------ + # Strip custom parameters; forward only pipeline/runtime params. + # ------------------------------------------------------------------ + foreach ($key in @('PartnerTenantId','CapabilityId','IsAllowed', + 'IncludedUsers','ExcludedUsers','IncludedGroups','ExcludedGroups')) { + $null = $PSBoundParameters.Remove($key) + } + + if ($PSCmdlet.ShouldProcess($PartnerTenantId, "New-PartnerM365XTAPCapability ($CapabilityId)")) { + $result = New-MgBetaPolicyCrossTenantAccessPolicyPartnerM365Capability ` + -CrossTenantAccessPolicyConfigurationPartnerTenantId $PartnerTenantId ` + -InboundAccess $inboundAccess ` + -Name $CapabilityId ` + -AdditionalProperties @{ '@odata.type' = "microsoft.graph.$CapabilityId" } ` + @PSBoundParameters + if ($null -ne $result) { ConvertTo-EntraXTAPM365CapabilityFlatOutput -Result $result -IsPartner } + } + } + + end { + } +} diff --git a/src/Identity.SignIns/beta/custom/Remove-PartnerEntraXTAP.ps1 b/src/Identity.SignIns/beta/custom/Remove-PartnerEntraXTAP.ps1 new file mode 100644 index 00000000000..87f10bcce05 --- /dev/null +++ b/src/Identity.SignIns/beta/custom/Remove-PartnerEntraXTAP.ps1 @@ -0,0 +1,111 @@ +# ---------------------------------------------------------------------------------- +# +# Copyright Microsoft Corporation +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ---------------------------------------------------------------------------------- + +<# +.Synopsis + Removes a Cross-Tenant Access Policy (XTAP) partner configuration. + +.Description + Provides a flattened, user-friendly interface over + Remove-MgBetaPolicyCrossTenantAccessPolicyPartner. + +.Parameter PartnerTenantId + The tenant ID (GUID) of the partner whose XTAP configuration is to be removed. + +.Example + # Remove a specific partner XTAP configuration + Remove-PartnerEntraXTAP -PartnerTenantId "3d0f5dec-5d3d-455c-8016-e2af1ae4d31a" + +.Example + # Remove with PassThru to confirm deletion + Remove-PartnerEntraXTAP -PartnerTenantId "3d0f5dec-5d3d-455c-8016-e2af1ae4d31a" -PassThru + +.Link + https://learn.microsoft.com/en-us/graph/api/crosstenantaccesspolicyconfigurationpartner-delete + https://learn.microsoft.com/en-us/powershell/module/microsoft.graph.beta.identity.signins/remove-mgbetapolicycrosstenantaccesspolicypartner +#> +function Remove-PartnerEntraXTAP { + [CmdletBinding(DefaultParameterSetName = 'Delete', + PositionalBinding = $false, + SupportsShouldProcess, + ConfirmImpact = 'High')] + param( + + [Parameter(Mandatory = $true, ParameterSetName = 'Delete')] + [ValidateScript({ + [System.Guid]::TryParse($_, [ref][System.Guid]::Empty) -or + $(throw "'$_' is not a valid GUID. PartnerTenantId must be a valid GUID.") + })] + [System.String] + # The partner tenant ID (GUID) of the XTAP configuration to remove. + ${PartnerTenantId}, + + [Parameter(ParameterSetName = 'Delete')] + [System.Management.Automation.SwitchParameter] + # Returns $true on successful deletion. + ${PassThru}, + + # ── Pipeline / runtime ──────────────────────────────────────────── + [Parameter(DontShow)] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Management.Automation.SwitchParameter] + ${Break}, + + [Parameter(DontShow)] + [ValidateNotNull()] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [Microsoft.Graph.Beta.PowerShell.Runtime.SendAsyncStep[]] + ${HttpPipelineAppend}, + + [Parameter(DontShow)] + [ValidateNotNull()] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [Microsoft.Graph.Beta.PowerShell.Runtime.SendAsyncStep[]] + ${HttpPipelinePrepend}, + + [Parameter(DontShow)] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Uri] + ${Proxy}, + + [Parameter(DontShow)] + [ValidateNotNull()] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Management.Automation.PSCredential] + ${ProxyCredential}, + + [Parameter(DontShow)] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Management.Automation.SwitchParameter] + ${ProxyUseDefaultCredentials} + ) + + begin { + } + + process { + $null = $PSBoundParameters.Remove('PartnerTenantId') + + Write-Verbose "Removing XTAP partner configuration for tenant '$PartnerTenantId'." + + if ($PSCmdlet.ShouldProcess($PartnerTenantId, "Remove-PartnerEntraXTAP")) { + Remove-MgBetaPolicyCrossTenantAccessPolicyPartner ` + -CrossTenantAccessPolicyConfigurationPartnerTenantId $PartnerTenantId ` + @PSBoundParameters + } + } + + end { + } +} diff --git a/src/Identity.SignIns/beta/custom/Remove-PartnerM365XTAPCapability.ps1 b/src/Identity.SignIns/beta/custom/Remove-PartnerM365XTAPCapability.ps1 new file mode 100644 index 00000000000..928704a79ef --- /dev/null +++ b/src/Identity.SignIns/beta/custom/Remove-PartnerM365XTAPCapability.ps1 @@ -0,0 +1,129 @@ +# ---------------------------------------------------------------------------------- +# +# Copyright Microsoft Corporation +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ---------------------------------------------------------------------------------- + +<# +.Synopsis + Removes a Microsoft 365 capability entry from a Cross-Tenant Access Policy (XTAP) + partner configuration. + +.Description + Provides a flattened, user-friendly interface over + Remove-MgBetaPolicyCrossTenantAccessPolicyPartnerM365Capability. + +.Parameter PartnerTenantId + The partner tenant ID (GUID) that identifies the cross-tenant access policy + partner entry from which the M365 capability will be removed. + +.Parameter CapabilityId + The OData type name / key of the M365 capability to remove + (e.g. "crossTenantCalendarAvailabilityBasic"). + +.Example + # Remove a specific M365 capability from a partner tenant configuration + Remove-PartnerM365XTAPCapability ` + -PartnerTenantId "3d0f5dec-5d3d-455c-8016-e2af1ae4d31a" ` + -CapabilityId "crossTenantCalendarAvailabilityBasic" + +.Example + # Remove with PassThru to confirm deletion + Remove-PartnerM365XTAPCapability ` + -PartnerTenantId "3d0f5dec-5d3d-455c-8016-e2af1ae4d31a" ` + -CapabilityId "crossTenantMailTipsAll" ` + -PassThru + +.Link + https://learn.microsoft.com/en-us/graph/api/crosstenantaccesspolicyconfigurationpartner-delete-m365capabilities + https://learn.microsoft.com/en-us/powershell/module/microsoft.graph.beta.identity.signins/remove-mgbetapolicycrosstenantaccesspolicypartnerm365capability +#> +function Remove-PartnerM365XTAPCapability { + [CmdletBinding(DefaultParameterSetName = 'Delete', + PositionalBinding = $false, + SupportsShouldProcess, + ConfirmImpact = 'High')] + param( + + [Parameter(Mandatory = $true, ParameterSetName = 'Delete')] + [ValidateScript({ + [System.Guid]::TryParse($_, [ref][System.Guid]::Empty) -or + $(throw "'$_' is not a valid GUID. PartnerTenantId must be a valid GUID.") + })] + [System.String] + # The partner tenant ID (GUID) for the cross-tenant access policy entry. + ${PartnerTenantId}, + + [Parameter(Mandatory = $true, ParameterSetName = 'Delete')] + [System.String] + # The OData type name / key of the M365 capability to remove. + ${CapabilityId}, + + [Parameter(ParameterSetName = 'Delete')] + [System.Management.Automation.SwitchParameter] + # Returns $true on successful deletion. + ${PassThru}, + + # ── Pipeline / runtime ──────────────────────────────────────────── + [Parameter(DontShow)] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Management.Automation.SwitchParameter] + ${Break}, + + [Parameter(DontShow)] + [ValidateNotNull()] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [Microsoft.Graph.Beta.PowerShell.Runtime.SendAsyncStep[]] + ${HttpPipelineAppend}, + + [Parameter(DontShow)] + [ValidateNotNull()] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [Microsoft.Graph.Beta.PowerShell.Runtime.SendAsyncStep[]] + ${HttpPipelinePrepend}, + + [Parameter(DontShow)] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Uri] + ${Proxy}, + + [Parameter(DontShow)] + [ValidateNotNull()] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Management.Automation.PSCredential] + ${ProxyCredential}, + + [Parameter(DontShow)] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Management.Automation.SwitchParameter] + ${ProxyUseDefaultCredentials} + ) + + begin { + } + + process { + $null = $PSBoundParameters.Remove('PartnerTenantId') + $null = $PSBoundParameters.Remove('CapabilityId') + + Write-Verbose "Removing XTAP M365 capability '$CapabilityId' from partner tenant '$PartnerTenantId'." + + if ($PSCmdlet.ShouldProcess("$PartnerTenantId/$CapabilityId", "Remove-PartnerM365XTAPCapability")) { + Remove-MgBetaPolicyCrossTenantAccessPolicyPartnerM365Capability ` + -CrossTenantAccessPolicyConfigurationPartnerTenantId $PartnerTenantId ` + -M365CapabilityBaseName $CapabilityId ` + @PSBoundParameters + } + } + + end { + } +} diff --git a/src/Identity.SignIns/beta/custom/Reset-DefaultEntraXTAPToSystemDefault.ps1 b/src/Identity.SignIns/beta/custom/Reset-DefaultEntraXTAPToSystemDefault.ps1 new file mode 100644 index 00000000000..12663323239 --- /dev/null +++ b/src/Identity.SignIns/beta/custom/Reset-DefaultEntraXTAPToSystemDefault.ps1 @@ -0,0 +1,101 @@ +# ---------------------------------------------------------------------------------- +# +# Copyright Microsoft Corporation +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ---------------------------------------------------------------------------------- + +<# +.Synopsis + Resets the tenant-wide default Cross-Tenant Access Policy (XTAP) configuration + to system defaults. + +.Description + Provides a flattened, user-friendly interface over + Reset-MgBetaPolicyCrossTenantAccessPolicyDefaultToSystemDefault. + + The default configuration is a singleton — there is exactly one per tenant. + This cmdlet invokes the Graph API `resetToSystemDefault` action, which restores + all default XTAP settings (B2B collaboration, M365 Collaboration, App Service + Connect, InboundTrust, etc.) to the Microsoft-defined system defaults. + +.Example + # Reset the default XTAP configuration to system defaults + Reset-DefaultEntraXTAPToSystemDefault + +.Example + # Reset with PassThru to confirm the operation succeeded + Reset-DefaultEntraXTAPToSystemDefault -PassThru + +.Link + https://learn.microsoft.com/en-us/graph/api/crosstenantaccesspolicydefaultconfiguration-resettosystemdefault + https://learn.microsoft.com/en-us/powershell/module/microsoft.graph.beta.identity.signins/reset-mgbetapolicycrosstenantaccesspolicydefaulttosystemdefault +#> +function Reset-DefaultEntraXTAPToSystemDefault { + [CmdletBinding(DefaultParameterSetName = 'Reset', + PositionalBinding = $false, + SupportsShouldProcess, + ConfirmImpact = 'High')] + param( + + [Parameter(ParameterSetName = 'Reset')] + [System.Management.Automation.SwitchParameter] + # Returns $true on successful reset. + ${PassThru}, + + # ── Pipeline / runtime ──────────────────────────────────────────── + [Parameter(DontShow)] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Management.Automation.SwitchParameter] + ${Break}, + + [Parameter(DontShow)] + [ValidateNotNull()] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [Microsoft.Graph.Beta.PowerShell.Runtime.SendAsyncStep[]] + ${HttpPipelineAppend}, + + [Parameter(DontShow)] + [ValidateNotNull()] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [Microsoft.Graph.Beta.PowerShell.Runtime.SendAsyncStep[]] + ${HttpPipelinePrepend}, + + [Parameter(DontShow)] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Uri] + ${Proxy}, + + [Parameter(DontShow)] + [ValidateNotNull()] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Management.Automation.PSCredential] + ${ProxyCredential}, + + [Parameter(DontShow)] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Management.Automation.SwitchParameter] + ${ProxyUseDefaultCredentials} + ) + + begin { + } + + process { + Write-Verbose "Resetting default XTAP configuration to system defaults." + + if ($PSCmdlet.ShouldProcess("Default XTAP Configuration", "Reset-DefaultEntraXTAPToSystemDefault")) { + Reset-MgBetaPolicyCrossTenantAccessPolicyDefaultToSystemDefault @PSBoundParameters + } + } + + end { + } +} diff --git a/src/Identity.SignIns/beta/custom/Set-DefaultEntraXTAP.ps1 b/src/Identity.SignIns/beta/custom/Set-DefaultEntraXTAP.ps1 new file mode 100644 index 00000000000..fc9e38269be --- /dev/null +++ b/src/Identity.SignIns/beta/custom/Set-DefaultEntraXTAP.ps1 @@ -0,0 +1,119 @@ +# ---------------------------------------------------------------------------------- +# Copyright Microsoft Corporation - Licensed under the Apache License, Version 2.0 +# ---------------------------------------------------------------------------------- + +function Set-DefaultEntraXTAP { + [OutputType([Microsoft.Graph.Beta.PowerShell.Models.IMicrosoftGraphCrossTenantAccessPolicyConfigurationDefault])] + [CmdletBinding(DefaultParameterSetName = 'Expanded', + PositionalBinding = $false, SupportsShouldProcess, ConfirmImpact = 'Medium')] + param( + + [Parameter(ParameterSetName = 'Expanded')] + [ValidateSet('Allowed', 'Blocked')] + [System.String] + ${M365CollaborationInbound}, + + [Parameter(ParameterSetName = 'Expanded')] + [System.String[]] + ${M365CollaborationInboundTargetUsers}, + + [Parameter(ParameterSetName = 'Expanded')] + [ValidateSet('Allowed', 'Blocked')] + [System.String] + ${M365CollaborationOutbound}, + + [Parameter(ParameterSetName = 'Expanded')] + [System.String[]] + ${M365CollaborationOutboundTargetUsers}, + + [Parameter(ParameterSetName = 'Expanded')] + [System.String[]] + ${M365CollaborationOutboundTargetGroups}, + + [Parameter(ParameterSetName = 'Expanded')] + [ValidateSet('Allowed', 'Blocked')] + [System.String] + ${AppServiceConnectInbound}, + + [Parameter(ParameterSetName = 'Expanded')] + [System.String[]] + ${AppServiceConnectInboundTargetApplications}, + + [Parameter(DontShow)] [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] [System.Management.Automation.SwitchParameter] ${Break}, + [Parameter(DontShow)] [ValidateNotNull()] [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] [Microsoft.Graph.Beta.PowerShell.Runtime.SendAsyncStep[]] ${HttpPipelineAppend}, + [Parameter(DontShow)] [ValidateNotNull()] [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] [Microsoft.Graph.Beta.PowerShell.Runtime.SendAsyncStep[]] ${HttpPipelinePrepend}, + [Parameter(DontShow)] [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] [System.Uri] ${Proxy}, + [Parameter(DontShow)] [ValidateNotNull()] [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] [System.Management.Automation.PSCredential] ${ProxyCredential}, + [Parameter(DontShow)] [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] [System.Management.Automation.SwitchParameter] ${ProxyUseDefaultCredentials} + ) + + begin {} + + process { + function Build-TargetConfiguration { + param([string]$AccessType, [string[]]$Ids, [string]$TargetType) + if ([string]::IsNullOrEmpty($AccessType) -or $null -eq $Ids -or $Ids.Count -eq 0) { return $null } + $targets = @() + foreach ($id in $Ids) { + $t = New-Object Microsoft.Graph.Beta.PowerShell.Models.MicrosoftGraphCrossTenantAccessPolicyTarget + $t.Target = $id.Trim(); $t.TargetType = $TargetType; $targets += $t + } + $config = New-Object Microsoft.Graph.Beta.PowerShell.Models.MicrosoftGraphCrossTenantAccessPolicyTargetConfiguration + $config.AccessType = $AccessType.ToLower(); $config.Targets = $targets + return $config + } + + foreach ($key in @('M365CollaborationInbound', 'M365CollaborationInboundTargetUsers', 'M365CollaborationOutbound', 'M365CollaborationOutboundTargetUsers', 'M365CollaborationOutboundTargetGroups', 'AppServiceConnectInbound', 'AppServiceConnectInboundTargetApplications')) { $null = $PSBoundParameters.Remove($key) } + + if (-not $M365CollaborationInbound -and -not $M365CollaborationOutbound -and -not $AppServiceConnectInbound) { + throw 'At least one of -M365CollaborationInbound, -M365CollaborationOutbound, or -AppServiceConnectInbound must be specified.' + } + if ($M365CollaborationInbound -and (-not $M365CollaborationInboundTargetUsers -or $M365CollaborationInboundTargetUsers.Count -eq 0)) { + throw '-M365CollaborationInboundTargetUsers is required when -M365CollaborationInbound is specified.' + } + if ($M365CollaborationOutbound -and + (-not $M365CollaborationOutboundTargetUsers -or $M365CollaborationOutboundTargetUsers.Count -eq 0) -and + (-not $M365CollaborationOutboundTargetGroups -or $M365CollaborationOutboundTargetGroups.Count -eq 0)) { + throw 'At least one of -M365CollaborationOutboundTargetUsers or -M365CollaborationOutboundTargetGroups is required when -M365CollaborationOutbound is specified.' + } + if ($AppServiceConnectInbound -and (-not $AppServiceConnectInboundTargetApplications -or $AppServiceConnectInboundTargetApplications.Count -eq 0)) { + throw '-AppServiceConnectInboundTargetApplications is required when -AppServiceConnectInbound is specified.' + } + + $inboundUserConfig = Build-TargetConfiguration -AccessType $M365CollaborationInbound -Ids $M365CollaborationInboundTargetUsers -TargetType 'user' + + $outboundConfig = $null + if ($M365CollaborationOutbound) { + $userConfig = Build-TargetConfiguration -AccessType $M365CollaborationOutbound -Ids $M365CollaborationOutboundTargetUsers -TargetType 'user' + $groupConfig = Build-TargetConfiguration -AccessType $M365CollaborationOutbound -Ids $M365CollaborationOutboundTargetGroups -TargetType 'group' + $mergedTargets = @() + if ($null -ne $userConfig) { $mergedTargets += $userConfig.Targets } + if ($null -ne $groupConfig) { $mergedTargets += $groupConfig.Targets } + $outboundConfig = New-Object Microsoft.Graph.Beta.PowerShell.Models.MicrosoftGraphCrossTenantAccessPolicyTargetConfiguration + $outboundConfig.AccessType = $M365CollaborationOutbound.ToLower() + $outboundConfig.Targets = [Microsoft.Graph.Beta.PowerShell.Models.IMicrosoftGraphCrossTenantAccessPolicyTarget[]]$mergedTargets + } + + $appServiceConnect = $null + if ($AppServiceConnectInbound) { + $appConfig = Build-TargetConfiguration -AccessType $AppServiceConnectInbound -Ids $AppServiceConnectInboundTargetApplications -TargetType 'application' + $appServiceConnect = New-Object Microsoft.Graph.Beta.PowerShell.Models.MicrosoftGraphCrossTenantAccessPolicyAppServiceConnectSetting + $appServiceConnect.Applications = $appConfig + } + + $m365Inbound = $null; $m365Outbound = $null + if ($null -ne $inboundUserConfig) { $m365Inbound = New-Object Microsoft.Graph.Beta.PowerShell.Models.MicrosoftGraphCrossTenantAccessPolicyM365CollaborationInboundSetting; $m365Inbound.Users = $inboundUserConfig } + if ($null -ne $outboundConfig) { $m365Outbound = New-Object Microsoft.Graph.Beta.PowerShell.Models.MicrosoftGraphCrossTenantAccessPolicyM365CollaborationOutboundSetting; $m365Outbound.UsersAndGroups = $outboundConfig } + + if ($PSCmdlet.ShouldProcess('Default XTAP Configuration', 'Set-DefaultEntraXTAP')) { + $splat = @{} + if ($null -ne $m365Inbound) { $splat['M365CollaborationInbound'] = $m365Inbound } + if ($null -ne $m365Outbound) { $splat['M365CollaborationOutbound'] = $m365Outbound } + if ($null -ne $appServiceConnect) { $splat['AppServiceConnectInbound'] = $appServiceConnect } + $result = Update-MgBetaPolicyCrossTenantAccessPolicyDefault @splat @PSBoundParameters + if ($null -ne $result) { ConvertTo-EntraXTAPFlatOutput -Result $result } + } + } + + end {} +} \ No newline at end of file diff --git a/src/Identity.SignIns/beta/custom/Set-DefaultM365XTAPCapability.ps1 b/src/Identity.SignIns/beta/custom/Set-DefaultM365XTAPCapability.ps1 new file mode 100644 index 00000000000..a9c7c311fc4 --- /dev/null +++ b/src/Identity.SignIns/beta/custom/Set-DefaultM365XTAPCapability.ps1 @@ -0,0 +1,242 @@ +# ---------------------------------------------------------------------------------- +# +# Copyright Microsoft Corporation +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ---------------------------------------------------------------------------------- + +<# +.Synopsis + Updates an existing Microsoft 365 capability entry on the default Cross-Tenant + Access Policy (XTAP) configuration for the tenant. + +.Description + Provides a flattened, user-friendly interface over + Update-MgBetaPolicyCrossTenantAccessPolicyDefaultM365Capability. + + Instead of building the nested payload manually, callers supply discrete parameters + for the inbound access flag and the users and groups to include or exclude. + The cmdlet assembles the correct Graph API body, constructs the strongly-typed + model objects, and delegates to the auto-generated cmdlet. + +.Parameter CapabilityId + The OData type name / key of the M365 capability to update + (e.g. "crossTenantCalendarAvailabilityBasic"). + +.Parameter IsAllowed + Whether inbound access is allowed ($true) or blocked ($false) for the capability. + +.Parameter IncludedUsers + User object IDs or the special value "All" to include in the inbound access scope. + +.Parameter ExcludedUsers + User object IDs or "All" to exclude from the inbound access scope. + +.Parameter IncludedGroups + Group object IDs or the special value "All" to include in the inbound access scope. + +.Parameter ExcludedGroups + Group object IDs or "All" to exclude from the inbound access scope. + +.Example + # Update default calendar availability to allow all users + Set-DefaultM365XTAPCapability ` + -CapabilityId "crossTenantCalendarAvailabilityBasic" ` + -IsAllowed $true ` + -IncludedUsers "All" + +.Example + # Restrict default MailTips to a specific group, exclude individual users + Set-DefaultM365XTAPCapability ` + -CapabilityId "crossTenantMailTipsAll" ` + -IsAllowed $true ` + -IncludedGroups "0be493dc-cb56-4a53-936f-9cf64410b8b0" ` + -ExcludedUsers "6f546279-4da5-4b53-a095-09ea0cef9971" + +.Example + # Block all inbound open profile card access by default + Set-DefaultM365XTAPCapability ` + -CapabilityId "crossTenantOpenProfileCard" ` + -IsAllowed $false ` + -IncludedUsers "All" + +.Outputs + Microsoft.Graph.Beta.PowerShell.Models.IMicrosoftGraphM365CapabilityBase + +.Link + https://learn.microsoft.com/en-us/graph/api/crosstenantaccesspolicydefaultconfiguration-update-m365capabilities + https://learn.microsoft.com/en-us/powershell/module/microsoft.graph.beta.identity.signins/update-mgbetapolicycrosstenantaccesspolicydefaultm365capability +#> +function Set-DefaultM365XTAPCapability { + [OutputType([Microsoft.Graph.Beta.PowerShell.Models.IMicrosoftGraphM365CapabilityBase])] + [CmdletBinding(DefaultParameterSetName = 'UpdateExpanded', + PositionalBinding = $false, + SupportsShouldProcess, + ConfirmImpact = 'Medium')] + param( + + # ── Capability ID ───────────────────────────────────────────────── + [Parameter(Mandatory = $true, ParameterSetName = 'UpdateExpanded')] + [System.String] + # The OData type name / key of the M365 capability to update. + ${CapabilityId}, + + # ── Inbound access ──────────────────────────────────────────────── + [Parameter(Mandatory = $true, ParameterSetName = 'UpdateExpanded')] + [System.Boolean] + # Whether inbound access is allowed ($true) or blocked ($false). + ${IsAllowed}, + + [Parameter(ParameterSetName = 'UpdateExpanded')] + [ValidateScript({ + foreach ($item in $_) { + if ($item -ne 'All' -and -not [System.Guid]::TryParse($item, [ref][System.Guid]::Empty)) { + throw "'$item' is not valid. Each value must be a GUID or 'All'." + } + } + $true + })] + [System.String[]] + # User object IDs or "All" to include in the inbound access scope. + ${IncludedUsers}, + + [Parameter(ParameterSetName = 'UpdateExpanded')] + [ValidateScript({ + foreach ($item in $_) { + if ($item -ne 'All' -and -not [System.Guid]::TryParse($item, [ref][System.Guid]::Empty)) { + throw "'$item' is not valid. Each value must be a GUID or 'All'." + } + } + $true + })] + [System.String[]] + # User object IDs or "All" to exclude from the inbound access scope. + ${ExcludedUsers}, + + [Parameter(ParameterSetName = 'UpdateExpanded')] + [ValidateScript({ + foreach ($item in $_) { + if ($item -ne 'All' -and -not [System.Guid]::TryParse($item, [ref][System.Guid]::Empty)) { + throw "'$item' is not valid. Each value must be a GUID or 'All'." + } + } + $true + })] + [System.String[]] + # Group object IDs or "All" to include in the inbound access scope. + ${IncludedGroups}, + + [Parameter(ParameterSetName = 'UpdateExpanded')] + [ValidateScript({ + foreach ($item in $_) { + if ($item -ne 'All' -and -not [System.Guid]::TryParse($item, [ref][System.Guid]::Empty)) { + throw "'$item' is not valid. Each value must be a GUID or 'All'." + } + } + $true + })] + [System.String[]] + # Group object IDs or "All" to exclude from the inbound access scope. + ${ExcludedGroups}, + + # ── Pipeline / runtime ──────────────────────────────────────────── + [Parameter(DontShow)] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Management.Automation.SwitchParameter] + ${Break}, + + [Parameter(DontShow)] + [ValidateNotNull()] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [Microsoft.Graph.Beta.PowerShell.Runtime.SendAsyncStep[]] + ${HttpPipelineAppend}, + + [Parameter(DontShow)] + [ValidateNotNull()] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [Microsoft.Graph.Beta.PowerShell.Runtime.SendAsyncStep[]] + ${HttpPipelinePrepend}, + + [Parameter(DontShow)] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Uri] + ${Proxy}, + + [Parameter(DontShow)] + [ValidateNotNull()] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Management.Automation.PSCredential] + ${ProxyCredential}, + + [Parameter(DontShow)] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Management.Automation.SwitchParameter] + ${ProxyUseDefaultCredentials} + ) + + begin { + } + + process { + # ------------------------------------------------------------------ + # Helper: build MicrosoftGraphM365CapabilityResourceScope objects + # from a plain array of IDs and the implied resourceType string. + # ------------------------------------------------------------------ + function Build-ResourceScopes { + param( + [string[]] $Ids, + [string] $ResourceType + ) + $results = @() + foreach ($id in $Ids) { + if ([string]::IsNullOrWhiteSpace($id)) { continue } + $scope = New-Object Microsoft.Graph.Beta.PowerShell.Models.MicrosoftGraphM365CapabilityResourceScope + $scope.ResourceId = $id.Trim() + $scope.ResourceType = $ResourceType + $results += $scope + } + return ,$results + } + + $includedUserScopes = if ($null -ne $IncludedUsers -and $IncludedUsers.Count -gt 0) { Build-ResourceScopes -Ids $IncludedUsers -ResourceType 'user' } else { @() } + $includedGroupScopes = if ($null -ne $IncludedGroups -and $IncludedGroups.Count -gt 0) { Build-ResourceScopes -Ids $IncludedGroups -ResourceType 'group' } else { @() } + $excludedUserScopes = if ($null -ne $ExcludedUsers -and $ExcludedUsers.Count -gt 0) { Build-ResourceScopes -Ids $ExcludedUsers -ResourceType 'user' } else { @() } + $excludedGroupScopes = if ($null -ne $ExcludedGroups -and $ExcludedGroups.Count -gt 0) { Build-ResourceScopes -Ids $ExcludedGroups -ResourceType 'group' } else { @() } + + $resourceScopes = New-Object Microsoft.Graph.Beta.PowerShell.Models.MicrosoftGraphM365CapabilityResourceScopes + $resourceScopes.Included = @($includedUserScopes + $includedGroupScopes) + $resourceScopes.Excluded = @($excludedUserScopes + $excludedGroupScopes) + + $inboundAccess = New-Object Microsoft.Graph.Beta.PowerShell.Models.MicrosoftGraphM365CapabilityInboundAccess + $inboundAccess.IsAllowed = $IsAllowed + $inboundAccess.ResourceScopes = $resourceScopes + + Write-Verbose "Updating default XTAP M365 capability '$CapabilityId'." + Write-Verbose "IsAllowed: $IsAllowed | IncludedUsers: $($IncludedUsers -join ', ') | IncludedGroups: $($IncludedGroups -join ', ') | ExcludedUsers: $($ExcludedUsers -join ', ') | ExcludedGroups: $($ExcludedGroups -join ', ')" + + foreach ($key in @('CapabilityId','IsAllowed', + 'IncludedUsers','ExcludedUsers','IncludedGroups','ExcludedGroups')) { + $null = $PSBoundParameters.Remove($key) + } + + if ($PSCmdlet.ShouldProcess($CapabilityId, "Set-DefaultM365XTAPCapability")) { + $result = Update-MgBetaPolicyCrossTenantAccessPolicyDefaultM365Capability ` + -M365CapabilityBaseName $CapabilityId ` + -InboundAccess $inboundAccess ` + -Name $CapabilityId ` + -AdditionalProperties @{ '@odata.type' = "microsoft.graph.$CapabilityId" } ` + @PSBoundParameters + if ($null -ne $result) { ConvertTo-EntraXTAPM365CapabilityFlatOutput -Result $result } + } + } + + end { + } +} diff --git a/src/Identity.SignIns/beta/custom/Set-PartnerEntraXTAP.ps1 b/src/Identity.SignIns/beta/custom/Set-PartnerEntraXTAP.ps1 new file mode 100644 index 00000000000..d18dc84c0a1 --- /dev/null +++ b/src/Identity.SignIns/beta/custom/Set-PartnerEntraXTAP.ps1 @@ -0,0 +1,126 @@ +# ---------------------------------------------------------------------------------- +# Copyright Microsoft Corporation - Licensed under the Apache License, Version 2.0 +# ---------------------------------------------------------------------------------- + +function Set-PartnerEntraXTAP { + [OutputType([Microsoft.Graph.Beta.PowerShell.Models.IMicrosoftGraphCrossTenantAccessPolicyConfigurationPartner])] + [CmdletBinding(DefaultParameterSetName = 'Expanded', + PositionalBinding = $false, SupportsShouldProcess, ConfirmImpact = 'Medium')] + param( + [Parameter(Mandatory = $true, ParameterSetName = 'Expanded')] + [ValidateScript({ + [System.Guid]::TryParse($_, [ref][System.Guid]::Empty) -or + $(throw "'$_' is not a valid GUID. PartnerTenantId must be a valid GUID.") + })] + [System.String] + ${PartnerTenantId}, + + [Parameter(ParameterSetName = 'Expanded')] + [ValidateSet('Allowed', 'Blocked')] + [System.String] + ${M365CollaborationInbound}, + + [Parameter(ParameterSetName = 'Expanded')] + [System.String[]] + ${M365CollaborationInboundTargetUsers}, + + [Parameter(ParameterSetName = 'Expanded')] + [ValidateSet('Allowed', 'Blocked')] + [System.String] + ${M365CollaborationOutbound}, + + [Parameter(ParameterSetName = 'Expanded')] + [System.String[]] + ${M365CollaborationOutboundTargetUsers}, + + [Parameter(ParameterSetName = 'Expanded')] + [System.String[]] + ${M365CollaborationOutboundTargetGroups}, + + [Parameter(ParameterSetName = 'Expanded')] + [ValidateSet('Allowed', 'Blocked')] + [System.String] + ${AppServiceConnectInbound}, + + [Parameter(ParameterSetName = 'Expanded')] + [System.String[]] + ${AppServiceConnectInboundTargetApplications}, + + [Parameter(DontShow)] [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] [System.Management.Automation.SwitchParameter] ${Break}, + [Parameter(DontShow)] [ValidateNotNull()] [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] [Microsoft.Graph.Beta.PowerShell.Runtime.SendAsyncStep[]] ${HttpPipelineAppend}, + [Parameter(DontShow)] [ValidateNotNull()] [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] [Microsoft.Graph.Beta.PowerShell.Runtime.SendAsyncStep[]] ${HttpPipelinePrepend}, + [Parameter(DontShow)] [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] [System.Uri] ${Proxy}, + [Parameter(DontShow)] [ValidateNotNull()] [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] [System.Management.Automation.PSCredential] ${ProxyCredential}, + [Parameter(DontShow)] [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] [System.Management.Automation.SwitchParameter] ${ProxyUseDefaultCredentials} + ) + + begin {} + + process { + function Build-TargetConfiguration { + param([string]$AccessType, [string[]]$Ids, [string]$TargetType) + if ([string]::IsNullOrEmpty($AccessType) -or $null -eq $Ids -or $Ids.Count -eq 0) { return $null } + $targets = @() + foreach ($id in $Ids) { + $t = New-Object Microsoft.Graph.Beta.PowerShell.Models.MicrosoftGraphCrossTenantAccessPolicyTarget + $t.Target = $id.Trim(); $t.TargetType = $TargetType; $targets += $t + } + $config = New-Object Microsoft.Graph.Beta.PowerShell.Models.MicrosoftGraphCrossTenantAccessPolicyTargetConfiguration + $config.AccessType = $AccessType.ToLower(); $config.Targets = $targets + return $config + } + + foreach ($key in @('PartnerTenantId', 'M365CollaborationInbound', 'M365CollaborationInboundTargetUsers', 'M365CollaborationOutbound', 'M365CollaborationOutboundTargetUsers', 'M365CollaborationOutboundTargetGroups', 'AppServiceConnectInbound', 'AppServiceConnectInboundTargetApplications')) { $null = $PSBoundParameters.Remove($key) } + + if (-not $M365CollaborationInbound -and -not $M365CollaborationOutbound -and -not $AppServiceConnectInbound) { + throw 'At least one of -M365CollaborationInbound, -M365CollaborationOutbound, or -AppServiceConnectInbound must be specified.' + } + if ($M365CollaborationInbound -and (-not $M365CollaborationInboundTargetUsers -or $M365CollaborationInboundTargetUsers.Count -eq 0)) { + throw '-M365CollaborationInboundTargetUsers is required when -M365CollaborationInbound is specified.' + } + if ($M365CollaborationOutbound -and + (-not $M365CollaborationOutboundTargetUsers -or $M365CollaborationOutboundTargetUsers.Count -eq 0) -and + (-not $M365CollaborationOutboundTargetGroups -or $M365CollaborationOutboundTargetGroups.Count -eq 0)) { + throw 'At least one of -M365CollaborationOutboundTargetUsers or -M365CollaborationOutboundTargetGroups is required when -M365CollaborationOutbound is specified.' + } + if ($AppServiceConnectInbound -and (-not $AppServiceConnectInboundTargetApplications -or $AppServiceConnectInboundTargetApplications.Count -eq 0)) { + throw '-AppServiceConnectInboundTargetApplications is required when -AppServiceConnectInbound is specified.' + } + + $inboundUserConfig = Build-TargetConfiguration -AccessType $M365CollaborationInbound -Ids $M365CollaborationInboundTargetUsers -TargetType 'user' + + $outboundConfig = $null + if ($M365CollaborationOutbound) { + $userConfig = Build-TargetConfiguration -AccessType $M365CollaborationOutbound -Ids $M365CollaborationOutboundTargetUsers -TargetType 'user' + $groupConfig = Build-TargetConfiguration -AccessType $M365CollaborationOutbound -Ids $M365CollaborationOutboundTargetGroups -TargetType 'group' + $mergedTargets = @() + if ($null -ne $userConfig) { $mergedTargets += $userConfig.Targets } + if ($null -ne $groupConfig) { $mergedTargets += $groupConfig.Targets } + $outboundConfig = New-Object Microsoft.Graph.Beta.PowerShell.Models.MicrosoftGraphCrossTenantAccessPolicyTargetConfiguration + $outboundConfig.AccessType = $M365CollaborationOutbound.ToLower() + $outboundConfig.Targets = [Microsoft.Graph.Beta.PowerShell.Models.IMicrosoftGraphCrossTenantAccessPolicyTarget[]]$mergedTargets + } + + $appServiceConnect = $null + if ($AppServiceConnectInbound) { + $appConfig = Build-TargetConfiguration -AccessType $AppServiceConnectInbound -Ids $AppServiceConnectInboundTargetApplications -TargetType 'application' + $appServiceConnect = New-Object Microsoft.Graph.Beta.PowerShell.Models.MicrosoftGraphCrossTenantAccessPolicyAppServiceConnectSetting + $appServiceConnect.Applications = $appConfig + } + + $m365Inbound = $null; $m365Outbound = $null + if ($null -ne $inboundUserConfig) { $m365Inbound = New-Object Microsoft.Graph.Beta.PowerShell.Models.MicrosoftGraphCrossTenantAccessPolicyM365CollaborationInboundSetting; $m365Inbound.Users = $inboundUserConfig } + if ($null -ne $outboundConfig) { $m365Outbound = New-Object Microsoft.Graph.Beta.PowerShell.Models.MicrosoftGraphCrossTenantAccessPolicyM365CollaborationOutboundSetting; $m365Outbound.UsersAndGroups = $outboundConfig } + + if ($PSCmdlet.ShouldProcess($PartnerTenantId, 'Set-PartnerEntraXTAP')) { + $splat = @{ CrossTenantAccessPolicyConfigurationPartnerTenantId = $PartnerTenantId } + if ($null -ne $m365Inbound) { $splat['M365CollaborationInbound'] = $m365Inbound } + if ($null -ne $m365Outbound) { $splat['M365CollaborationOutbound'] = $m365Outbound } + if ($null -ne $appServiceConnect) { $splat['AppServiceConnectInbound'] = $appServiceConnect } + $result = Update-MgBetaPolicyCrossTenantAccessPolicyPartner @splat @PSBoundParameters + if ($null -ne $result) { ConvertTo-EntraXTAPFlatOutput -Result $result -IsPartner } + } + } + + end {} +} \ No newline at end of file diff --git a/src/Identity.SignIns/beta/custom/Set-PartnerM365XTAPCapability.ps1 b/src/Identity.SignIns/beta/custom/Set-PartnerM365XTAPCapability.ps1 new file mode 100644 index 00000000000..37a3f936ae0 --- /dev/null +++ b/src/Identity.SignIns/beta/custom/Set-PartnerM365XTAPCapability.ps1 @@ -0,0 +1,264 @@ +# ---------------------------------------------------------------------------------- +# +# Copyright Microsoft Corporation +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ---------------------------------------------------------------------------------- + +<# +.Synopsis + Updates an existing Microsoft 365 capability entry on a Cross-Tenant Access Policy + (XTAP) partner configuration. + +.Description + Provides a flattened, user-friendly interface over + Update-MgBetaPolicyCrossTenantAccessPolicyPartnerM365Capability. + + Instead of building the nested payload manually, callers supply discrete parameters + for the inbound access flag and the users and groups to include or exclude. + The cmdlet assembles the correct Graph API body, constructs the strongly-typed + model objects, and delegates to the auto-generated cmdlet. + +.Parameter PartnerTenantId + The partner tenant ID (GUID) that identifies the cross-tenant access policy + partner entry containing the M365 capability to update. + +.Parameter CapabilityId + The OData type name / key of the M365 capability to update + (e.g. "crossTenantCalendarAvailabilityBasic"). + +.Parameter IsAllowed + Whether inbound access is allowed ($true) or blocked ($false) for the capability. + +.Parameter IncludedUsers + User object IDs or the special value "All" to include in the inbound access scope. + +.Parameter ExcludedUsers + User object IDs to exclude from the inbound access scope. + +.Parameter IncludedGroups + Group object IDs or the special value "All" to include in the inbound access scope. + +.Parameter ExcludedGroups + Group object IDs or "All" to exclude from the inbound access scope. + +.Example + # Update calendar availability to allow all users + Set-PartnerM365XTAPCapability ` + -PartnerTenantId "3d0f5dec-5d3d-455c-8016-e2af1ae4d31a" ` + -CapabilityId "crossTenantCalendarAvailabilityBasic" ` + -IsAllowed $true ` + -IncludedUsers "All" + +.Example + # Restrict MailTips to a specific group, exclude individual users + Set-PartnerM365XTAPCapability ` + -PartnerTenantId "3d0f5dec-5d3d-455c-8016-e2af1ae4d31a" ` + -CapabilityId "crossTenantMailTipsAll" ` + -IsAllowed $true ` + -IncludedGroups "0be493dc-cb56-4a53-936f-9cf64410b8b0" ` + -ExcludedUsers "6f546279-4da5-4b53-a095-09ea0cef9971" + +.Example + # Block all inbound open profile card access + Set-PartnerM365XTAPCapability ` + -PartnerTenantId "3d0f5dec-5d3d-455c-8016-e2af1ae4d31a" ` + -CapabilityId "crossTenantOpenProfileCard" ` + -IsAllowed $false ` + -IncludedUsers "All" + +.Outputs + Microsoft.Graph.Beta.PowerShell.Models.IMicrosoftGraphM365CapabilityBase + +.Link + https://learn.microsoft.com/en-us/graph/api/crosstenantaccesspolicyconfigurationpartner-update-m365capabilities + https://learn.microsoft.com/en-us/powershell/module/microsoft.graph.beta.identity.signins/update-mgbetapolicycrosstenantaccesspolicypartnerm365capability +#> +function Set-PartnerM365XTAPCapability { + [OutputType([Microsoft.Graph.Beta.PowerShell.Models.IMicrosoftGraphM365CapabilityBase])] + [CmdletBinding(DefaultParameterSetName = 'UpdateExpanded', + PositionalBinding = $false, + SupportsShouldProcess, + ConfirmImpact = 'Medium')] + param( + + [Parameter(Mandatory = $true, ParameterSetName = 'UpdateExpanded')] + [ValidateScript({ + [System.Guid]::TryParse($_, [ref][System.Guid]::Empty) -or + $(throw "'$_' is not a valid GUID. PartnerTenantId must be a valid GUID.") + })] + [System.String] + # The partner tenant ID (GUID) for the cross-tenant access policy entry. + ${PartnerTenantId}, + + [Parameter(Mandatory = $true, ParameterSetName = 'UpdateExpanded')] + [System.String] + # The OData type name / key of the M365 capability to update. + ${CapabilityId}, + + # ── Inbound access ──────────────────────────────────────────────── + [Parameter(Mandatory = $true, ParameterSetName = 'UpdateExpanded')] + [System.Boolean] + # Whether inbound access is allowed ($true) or blocked ($false). + ${IsAllowed}, + + [Parameter(ParameterSetName = 'UpdateExpanded')] + [ValidateScript({ + foreach ($item in $_) { + if ($item -ne 'All' -and -not [System.Guid]::TryParse($item, [ref][System.Guid]::Empty)) { + throw "'$item' is not valid. Each value must be a GUID or 'All'." + } + } + $true + })] + [System.String[]] + # User object IDs or "All" to include in the inbound access scope. + ${IncludedUsers}, + + [Parameter(ParameterSetName = 'UpdateExpanded')] + [ValidateScript({ + foreach ($item in $_) { + if ($item -ne 'All' -and -not [System.Guid]::TryParse($item, [ref][System.Guid]::Empty)) { + throw "'$item' is not valid. Each value must be a GUID or 'All'." + } + } + $true + })] + [System.String[]] + # User object IDs or "All" to exclude from the inbound access scope. + ${ExcludedUsers}, + + [Parameter(ParameterSetName = 'UpdateExpanded')] + [ValidateScript({ + foreach ($item in $_) { + if ($item -ne 'All' -and -not [System.Guid]::TryParse($item, [ref][System.Guid]::Empty)) { + throw "'$item' is not valid. Each value must be a GUID or 'All'." + } + } + $true + })] + [System.String[]] + # Group object IDs or "All" to include in the inbound access scope. + ${IncludedGroups}, + + [Parameter(ParameterSetName = 'UpdateExpanded')] + [ValidateScript({ + foreach ($item in $_) { + if ($item -ne 'All' -and -not [System.Guid]::TryParse($item, [ref][System.Guid]::Empty)) { + throw "'$item' is not valid. Each value must be a GUID or 'All'." + } + } + $true + })] + [System.String[]] + # Group object IDs or "All" to exclude from the inbound access scope. + ${ExcludedGroups}, + + # ── Pipeline / runtime ──────────────────────────────────────────── + [Parameter(DontShow)] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Management.Automation.SwitchParameter] + ${Break}, + + [Parameter(DontShow)] + [ValidateNotNull()] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [Microsoft.Graph.Beta.PowerShell.Runtime.SendAsyncStep[]] + ${HttpPipelineAppend}, + + [Parameter(DontShow)] + [ValidateNotNull()] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [Microsoft.Graph.Beta.PowerShell.Runtime.SendAsyncStep[]] + ${HttpPipelinePrepend}, + + [Parameter(DontShow)] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Uri] + ${Proxy}, + + [Parameter(DontShow)] + [ValidateNotNull()] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Management.Automation.PSCredential] + ${ProxyCredential}, + + [Parameter(DontShow)] + [Microsoft.Graph.Beta.PowerShell.Category('Runtime')] + [System.Management.Automation.SwitchParameter] + ${ProxyUseDefaultCredentials} + ) + + begin { + } + + process { + # ------------------------------------------------------------------ + # Helper: build MicrosoftGraphM365CapabilityResourceScope objects + # from a plain array of IDs and the implied resourceType string. + # ------------------------------------------------------------------ + function Build-ResourceScopes { + param( + [string[]] $Ids, + [string] $ResourceType + ) + $results = @() + foreach ($id in $Ids) { + if ([string]::IsNullOrWhiteSpace($id)) { continue } + $scope = New-Object Microsoft.Graph.Beta.PowerShell.Models.MicrosoftGraphM365CapabilityResourceScope + $scope.ResourceId = $id.Trim() + $scope.ResourceType = $ResourceType + $results += $scope + } + return ,$results + } + + # ------------------------------------------------------------------ + # Merge included/excluded users and groups into scope arrays. + # ------------------------------------------------------------------ + $includedUserScopes = if ($null -ne $IncludedUsers -and $IncludedUsers.Count -gt 0) { Build-ResourceScopes -Ids $IncludedUsers -ResourceType 'user' } else { @() } + $includedGroupScopes = if ($null -ne $IncludedGroups -and $IncludedGroups.Count -gt 0) { Build-ResourceScopes -Ids $IncludedGroups -ResourceType 'group' } else { @() } + $excludedUserScopes = if ($null -ne $ExcludedUsers -and $ExcludedUsers.Count -gt 0) { Build-ResourceScopes -Ids $ExcludedUsers -ResourceType 'user' } else { @() } + $excludedGroupScopes = if ($null -ne $ExcludedGroups -and $ExcludedGroups.Count -gt 0) { Build-ResourceScopes -Ids $ExcludedGroups -ResourceType 'group' } else { @() } + + $resourceScopes = New-Object Microsoft.Graph.Beta.PowerShell.Models.MicrosoftGraphM365CapabilityResourceScopes + $resourceScopes.Included = @($includedUserScopes + $includedGroupScopes) + $resourceScopes.Excluded = @($excludedUserScopes + $excludedGroupScopes) + + $inboundAccess = New-Object Microsoft.Graph.Beta.PowerShell.Models.MicrosoftGraphM365CapabilityInboundAccess + $inboundAccess.IsAllowed = $IsAllowed + $inboundAccess.ResourceScopes = $resourceScopes + + Write-Verbose "Updating XTAP M365 capability '$CapabilityId' for partner tenant '$PartnerTenantId'." + Write-Verbose "IsAllowed: $IsAllowed | IncludedUsers: $($IncludedUsers -join ', ') | IncludedGroups: $($IncludedGroups -join ', ') | ExcludedUsers: $($ExcludedUsers -join ', ') | ExcludedGroups: $($ExcludedGroups -join ', ')" + + # ------------------------------------------------------------------ + # Strip custom parameters; forward only pipeline/runtime params. + # ------------------------------------------------------------------ + foreach ($key in @('PartnerTenantId','CapabilityId','IsAllowed', + 'IncludedUsers','ExcludedUsers','IncludedGroups','ExcludedGroups')) { + $null = $PSBoundParameters.Remove($key) + } + + if ($PSCmdlet.ShouldProcess("$PartnerTenantId/$CapabilityId", "Set-PartnerM365XTAPCapability")) { + $result = Update-MgBetaPolicyCrossTenantAccessPolicyPartnerM365Capability ` + -CrossTenantAccessPolicyConfigurationPartnerTenantId $PartnerTenantId ` + -M365CapabilityBaseName $CapabilityId ` + -InboundAccess $inboundAccess ` + -Name $CapabilityId ` + -AdditionalProperties @{ '@odata.type' = "microsoft.graph.$CapabilityId" } ` + @PSBoundParameters + if ($null -ne $result) { ConvertTo-EntraXTAPM365CapabilityFlatOutput -Result $result -IsPartner } + } + } + + end { + } +}