Skip to content

Commit

Permalink
Merge pull request #5059 from NikCharlebois/ADOOrganizationOwner
Browse files Browse the repository at this point in the history
ADOOrganizationOwner - Initial Release
  • Loading branch information
NikCharlebois committed Sep 18, 2024
2 parents 5c4d855 + 97f4430 commit 05b1751
Show file tree
Hide file tree
Showing 7 changed files with 654 additions and 0 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

* AADPasswordRuleSettings
* Initial release
* ADOOrganizationOwner
* Initial release.
* ADOOrganizationOwner
* Initial release.
* ADOSecurityPolicy
* Initial release.
* AzureSubscription
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,343 @@
function Get-TargetResource
{
[CmdletBinding()]
[OutputType([System.Collections.Hashtable])]
param
(
[Parameter(Mandatory = $true)]
[System.String]
$OrganizationName,

[Parameter()]
[System.String]
$Owner,

[Parameter()]
[System.Management.Automation.PSCredential]
$Credential,

[Parameter()]
[System.String]
$ApplicationId,

[Parameter()]
[System.String]
$TenantId,

[Parameter()]
[System.String]
$CertificateThumbprint,

[Parameter()]
[Switch]
$ManagedIdentity,

[Parameter()]
[System.String[]]
$AccessTokens
)

$ConnectionMode = New-M365DSCConnection -Workload 'AzureDevOPS' `
-InboundParameters $PSBoundParameters

#Ensure the proper dependencies are installed in the current environment.
Confirm-M365DSCDependencies

#region Telemetry
$ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '')
$CommandName = $MyInvocation.MyCommand
$data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName `
-CommandName $CommandName `
-Parameters $PSBoundParameters
Add-M365DSCTelemetryEvent -Data $data
#endregion

$nullResult = $PSBoundParameters
try
{
$uri = "https://vssps.dev.azure.com/$OrganizationName/_apis/Organization/Collections/Me"
$organizationInfo = Invoke-M365DSCAzureDevOPSWebRequest -Uri $uri

$uri = "https://vsaex.dev.azure.com/$OrganizationName/_apis/userentitlements?api-version=7.2-preview.4"
$allUsers = Invoke-M365DSCAzureDevOPSWebRequest -Uri $uri

$ownerInfo = $allUsers.Items | Where-Object -FilterScript {$_.id -eq $organizationInfo.owner}

$results = @{
OrganizationName = $OrganizationName
Owner = $ownerInfo.user.principalName
Credential = $Credential
ApplicationId = $ApplicationId
TenantId = $TenantId
CertificateThumbprint = $CertificateThumbprint
ManagedIdentity = $ManagedIdentity.IsPresent
AccessTokens = $AccessTokens
}
return [System.Collections.Hashtable] $results
}
catch
{
Write-Verbose -Message $_
New-M365DSCLogEntry -Message 'Error retrieving data:' `
-Exception $_ `
-Source $($MyInvocation.MyCommand.Source) `
-TenantId $TenantId `
-Credential $Credential

return $nullResult
}
}

function Set-TargetResource
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[System.String]
$OrganizationName,

[Parameter()]
[System.String]
$Owner,

[Parameter()]
[System.Management.Automation.PSCredential]
$Credential,

[Parameter()]
[System.String]
$ApplicationId,

[Parameter()]
[System.String]
$TenantId,

[Parameter()]
[System.String]
$CertificateThumbprint,

[Parameter()]
[Switch]
$ManagedIdentity,

[Parameter()]
[System.String[]]
$AccessTokens
)
$ConnectionMode = New-M365DSCConnection -Workload 'AzureDevOPS' `
-InboundParameters $PSBoundParameters

#Ensure the proper dependencies are installed in the current environment.
Confirm-M365DSCDependencies

#region Telemetry
$ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '')
$CommandName = $MyInvocation.MyCommand
$data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName `
-CommandName $CommandName `
-Parameters $PSBoundParameters
Add-M365DSCTelemetryEvent -Data $data
#endregion

Write-Verbose -Message "Retrieving all users."
$uri = "https://vsaex.dev.azure.com/$OrganizationName/_apis/userentitlements?api-version=7.2-preview.4"
$allUsers = Invoke-M365DSCAzureDevOPSWebRequest -Uri $uri

$ownerInfo = $allUsers.items | Where-Object -FilterScript {$_.user.principalName -eq $Owner}

if ($null -ne $ownerInfo)
{
Write-Verbose -Message "Updating owner for organization {$OrganizationName} to {$($ownerInfo.id)}"
$body = "[{`"from`":`"`",`"op`":2,`"path`":`"/Owner`",`"value`":`"$($ownerInfo.id)`"}]"
$uri ='https://vssps.dev.azure.com/O365DSC-Dev/_apis/Organization/Collections/Me?api-version=7.1-preview.1'
Invoke-M365DSCAzureDevOPSWebRequest -Uri $uri -Method PATCH -Body $body
}
else
{
throw "Could not retrieve an Azure DevOPS user entitlement for {$Owner}"
}
}

function Test-TargetResource
{
[CmdletBinding()]
[OutputType([System.Boolean])]
param
(
[Parameter(Mandatory = $true)]
[System.String]
$OrganizationName,

[Parameter()]
[System.String]
$Owner,

[Parameter()]
[System.Management.Automation.PSCredential]
$Credential,

[Parameter()]
[System.String]
$ApplicationId,

[Parameter()]
[System.String]
$TenantId,

[Parameter()]
[System.String]
$CertificateThumbprint,

[Parameter()]
[Switch]
$ManagedIdentity,

[Parameter()]
[System.String[]]
$AccessTokens
)

#Ensure the proper dependencies are installed in the current environment.
Confirm-M365DSCDependencies

#region Telemetry
$ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '')
$CommandName = $MyInvocation.MyCommand
$data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName `
-CommandName $CommandName `
-Parameters $PSBoundParameters
Add-M365DSCTelemetryEvent -Data $data
#endregion

$CurrentValues = Get-TargetResource @PSBoundParameters
$ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone()

Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)"
Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)"

$testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues `
-Source $($MyInvocation.MyCommand.Source) `
-DesiredValues $PSBoundParameters `
-ValuesToCheck $ValuesToCheck.Keys

Write-Verbose -Message "Test-TargetResource returned $testResult"

return $testResult
}
function Export-TargetResource
{
[CmdletBinding()]
[OutputType([System.String])]
param
(
[Parameter()]
[System.Management.Automation.PSCredential]
$Credential,

[Parameter()]
[System.String]
$ApplicationId,

[Parameter()]
[System.String]
$TenantId,

[Parameter()]
[System.Management.Automation.PSCredential]
$ApplicationSecret,

[Parameter()]
[System.String]
$CertificateThumbprint,

[Parameter()]
[Switch]
$ManagedIdentity,

[Parameter()]
[System.String[]]
$AccessTokens
)

try
{
$ConnectionMode = New-M365DSCConnection -Workload 'AzureDevOPS' `
-InboundParameters $PSBoundParameters

#region Telemetry
$ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '')
$CommandName = $MyInvocation.MyCommand
$data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName `
-CommandName $CommandName `
-Parameters $PSBoundParameters
Add-M365DSCTelemetryEvent -Data $data
#endregion

$Script:ExportMode = $true

$profile = Invoke-M365DSCAzureDevOPSWebRequest -Uri 'https://app.vssps.visualstudio.com/_apis/profile/profiles/me?api-version=5.1'
$accounts = Invoke-M365DSCAzureDevOPSWebRequest -Uri "https://app.vssps.visualstudio.com/_apis/accounts?api-version=7.1-preview.1&memberId=$($profile.id)"

$i = 1
$dscContent = ''
if ($accounts.Length -eq 0)
{
Write-Host $Global:M365DSCEmojiGreenCheckMark
}
else
{
Write-Host "`r`n" -NoNewline
}
foreach ($account in $accounts)
{
$organization = $account.Value.accountName
if ($null -ne $Global:M365DSCExportResourceInstancesCount)
{
$Global:M365DSCExportResourceInstancesCount++
}

$displayedKey = $organization
Write-Host " |---[$i/$($accounts.Count)] $displayedKey" -NoNewline
$params = @{
OrganizationName = $organization
Credential = $Credential
ApplicationId = $ApplicationId
TenantId = $TenantId
CertificateThumbprint = $CertificateThumbprint
ManagedIdentity = $ManagedIdentity.IsPresent
AccessTokens = $AccessTokens
}

$Results = Get-TargetResource @Params
$Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode `
-Results $Results

$currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName `
-ConnectionMode $ConnectionMode `
-ModulePath $PSScriptRoot `
-Results $Results `
-Credential $Credential
$dscContent += $currentDSCBlock
Save-M365DSCPartialExport -Content $currentDSCBlock `
-FileName $Global:PartialExportFileName
$i++
Write-Host $Global:M365DSCEmojiGreenCheckMark
}
return $dscContent
}
catch
{
Write-Host $Global:M365DSCEmojiRedX

New-M365DSCLogEntry -Message 'Error during Export:' `
-Exception $_ `
-Source $($MyInvocation.MyCommand.Source) `
-TenantId $TenantId `
-Credential $Credential

return ''
}
}

Export-ModuleMember -Function *-TargetResource
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[ClassVersion("1.0.0.0"), FriendlyName("ADOOrganizationOwner")]
class MSFT_ADOOrganizationOwner : OMI_BaseResource
{
[Key, Description("NAme of the Azure DevOPS Organization")] String OrganizationName;
[Write, Description("User principal of the organization's owner")] String Owner;
[Write, Description("Credentials of the workload's Admin"), EmbeddedInstance("MSFT_Credential")] string Credential;
[Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId;
[Write, Description("Id of the Azure Active Directory tenant used for authentication.")] String TenantId;
[Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint;
[Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity;
[Write, Description("Access token used for authentication.")] String AccessTokens[];
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

# ADOOrganizationOwner

## Description

Configures the owner of an Azure DevOPS organization.
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"resourceName": "ADOOrganizationOwner",
"description": "Configures the owner of an Azure DevOPS organization.",
"roles": {
"read": [],
"update": []
},
"permissions": {
"graph": {
"delegated": {
"read": [],
"update": []
},
"application": {
"read": [],
"update": []
}
}
}
}
Loading

0 comments on commit 05b1751

Please sign in to comment.