Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Praval #20604

Draft
wants to merge 13 commits into
base: master
Choose a base branch
from
106 changes: 102 additions & 4 deletions Tasks/Common/VstsAzureRestHelpers_/VstsAzureRestHelpers_.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ function Get-EnvironmentAuthUrl {
[Parameter(Mandatory = $false)] $useMSAL = $false
)

$envAuthUrl = if ($useMSAL) { $endpoint.Data.activeDirectoryAuthority } else { $endpoint.Data.environmentAuthorityUrl }
$envAuthUrl = if ($useMSAL) { $endpoint.Data.activeDirectoryAuthority } else { $endpoint.Data.environmentAuthorityUrl }

if ([string]::IsNullOrEmpty($envAuthUrl)) {
if (($endpoint.Data.Environment) -and ($endpoint.Data.Environment -eq $azureStack)) {
Expand Down Expand Up @@ -370,7 +370,7 @@ function Build-MSALInstance {

$clientBuilder = [Microsoft.Identity.Client.ConfidentialClientApplicationBuilder]::Create($clientId).WithAuthority($envAuthUrl, $tenantId)

if ($Endpoint.Auth.Parameters.AuthenticationType -eq 'SPNCertificate') {
if ($endpoint.Auth.Parameters.AuthenticationType -eq 'SPNCertificate') {
Write-Verbose "MSAL - ServicePrincipal - certificate is used.";

$pemFileContent = $endpoint.Auth.Parameters.ServicePrincipalCertificate
Expand All @@ -384,6 +384,8 @@ function Build-MSALInstance {
$vstsEndpoint = Get-VstsEndpoint -Name SystemVssConnection -Require
$vstsAccessToken = $vstsEndpoint.auth.parameters.AccessToken

Write-Verbose "ServiceConnectionId ${connectedServiceNameARM} and vstsAccessToken ${vstsAccessToken}"

$oidc_token = Get-VstsFederatedToken -serviceConnectionId $connectedServiceNameARM -vstsAccessToken $vstsAccessToken

$msalClientInstance = $clientBuilder.WithClientAssertion($oidc_token).Build()
Expand Down Expand Up @@ -1358,6 +1360,52 @@ function ConvertTo-Pfx {
return $pfxFilePath, $pfxFilePassword
}

function Get-VstsFederatedTokenModified {
param(
[Parameter(Mandatory=$true)]
[string]$serviceConnectionId,
[Parameter(Mandatory=$true)]
[string]$vstsAccessToken
)

$uri = Get-VstsTaskVariable -Name 'System.CollectionUri' -Require
$planId = Get-VstsTaskVariable -Name 'System.PlanId' -Require
$jobId = Get-VstsTaskVariable -Name 'System.JobId' -Require
$hub = Get-VstsTaskVariable -Name 'System.HostType' -Require
$projectId = Get-VstsTaskVariable -Name 'System.TeamProjectId' -Require

Write-Host "URI $uri"
Write-Verbose "URI $uri"


# Construct the API URL
$url = $uri + "$projectId/_apis/distributedtask/hubs/$hub/plans/$planId/jobs/$jobId/oidctoken?serviceConnectionId=$serviceConnectionId&api-version=7.1-preview.1"
Write-Verbose $url

$headers = @{
"Authorization" = "Basic " + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$($vstsAccessToken)"))
"Content-Type" = "application/json"
}

# Make the POST request to generate the OIDC token
$response = Invoke-WebRequest -Uri $url -Method Post -Headers $headers -Body $body

Write-Verbose "Response : $response"

# Parse the response content to extract the OIDC token
$responseContent = $response.Content | ConvertFrom-Json
Write-Verbose "responseContent : $responseContent"
$oidcToken = $responseContent.oidcToken # The token field contains the OIDC token


if ($null -eq $oidcToken -or $oidcToken -eq [string]::Empty) {
Write-Verbose "Failed to create OIDC token."
throw (New-Object System.Exception(Get-VstsLocString -Key AZ_CouldNotGenerateOidcToken))
}
Write-Verbose "Token generated $oidcToken"
return $oidcToken
}

function Get-VstsFederatedToken {
param(
[Parameter(Mandatory=$true)]
Expand All @@ -1373,13 +1421,17 @@ function Get-VstsFederatedToken {
Write-Verbose "$newtonsoftDll not found."
throw
}
Write-Verbose "newtonsoftDll ${newtonsoftDll}"
$jsAssembly = [System.Reflection.Assembly]::LoadFrom($newtonsoftDll)

$vsServicesDll = [System.IO.Path]::Combine($OMDirectory, "Microsoft.VisualStudio.Services.WebApi.dll")
Write-Verbose "vsServiceDll ${vsServicesDll}"

if (!(Test-Path -LiteralPath $vsServicesDll -PathType Leaf)) {
Write-Verbose "$vsServicesDll not found."
throw
}

try {
Add-Type -LiteralPath $vsServicesDll
} catch {
Expand All @@ -1391,18 +1443,27 @@ function Get-VstsFederatedToken {
param($sender, $e)

if ($e.Name -like 'Newtonsoft.Json, *') {
return $jsAssembly
return $Global:jsAssembly
}

Write-Verbose "Unable to resolve assembly name '$($e.Name)'"
return $null
}

$a = [System.AppDomain]::CurrentDomain
Write-Host "[System.AppDomain]::CurrentDomain $a"

[System.AppDomain]::CurrentDomain.add_AssemblyResolve($onAssemblyResolve)


$taskHttpClient = $null;
try {
Write-Verbose "Trying again to construct the HTTP client."

$federatedCredential = New-Object Microsoft.VisualStudio.Services.OAuth.VssOAuthAccessTokenCredential($vstsAccessToken)

Write-Verbose "Post : federatedCredential $federatedCredential"

$uri = Get-VstsTaskVariable -Name 'System.CollectionUri' -Require
$vssCredentials = New-Object Microsoft.VisualStudio.Services.Common.VssCredentials(
(New-Object Microsoft.VisualStudio.Services.Common.WindowsCredential($false)), # Do not use default credentials.
Expand Down Expand Up @@ -1439,6 +1500,42 @@ function Get-VstsFederatedToken {
return $federatedToken
}

# Get the Bearer Access Token - MSAL
function Get-AccessTokenMSALWithCustomScope {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)] $endpoint,
[string][Parameter(Mandatory=$false)] $connectedServiceNameARM,
[string][Parameter(Mandatory=$false)] $scope
)

try {
Get-MSALInstance $endpoint $connectedServiceNameARM
Write-Verbose "Get-MSALInstance completed"
} catch {
Write-Verobse "Get-MSALInstance failed with $_"
}

# prepare MSAL scopes
[string] $resourceId = $scope + "/.default"
$scopes = [Collections.Generic.List[string]]@($resourceId)

try {
Write-Verbose "Fetching Access Token - MSAL"
$tokenResult = $script:msalClientInstance.AcquireTokenForClient($scopes).ExecuteAsync().GetAwaiter().GetResult()
return $tokenResult
}
catch {
$exceptionMessage = $_.Exception.Message.ToString()
$parsedException = Parse-Exception($_.Exception)
if ($parsedException) {
$exceptionMessage = $parsedException
}
Write-Error "ExceptionMessage: $exceptionMessage (in function: Get-AccessTokenMSAL)"
throw (Get-VstsLocString -Key AZ_SpnAccessTokenFetchFailure -ArgumentList $endpoint.Auth.Parameters.TenantId)
}
}

# Export only the public function.
Export-ModuleMember -Function Add-AzureSqlDatabaseServerFirewallRule
Export-ModuleMember -Function Remove-AzureSqlDatabaseServerFirewallRule
Expand All @@ -1455,4 +1552,5 @@ Export-ModuleMember -Function Get-AzureLoadBalancersDetails
Export-ModuleMember -Function Get-AzureLoadBalancerDetails
Export-ModuleMember -Function Get-AzureRMLoadBalancerFrontendIpConfigDetails
Export-ModuleMember -Function Get-AzureRMLoadBalancerInboundNatRuleConfigDetails
Export-ModuleMember -Function Get-AzureRMAccessToken
Export-ModuleMember -Function Get-AzureRMAccessToken
Export-ModuleMember -Function Get-AccessTokenMSALWithCustomScope
Loading