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

Support for AZURE_CREDENTIALSSecretName setting #1115

Merged
merged 19 commits into from
Jun 26, 2024
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion Actions/AL-Go-Helper.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -2403,11 +2403,17 @@ function InstallAzModuleIfNeeded {
InstallModule -name $name -minimumVersion $minimumVersion
}

$script:AzConnected = $false

function ConnectAz {
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '', Justification = 'GitHub Secrets come in as plain text')]
param(
[PsCustomObject] $azureCredentials
)
if ($script:AzConnected) {
return
}
InstallAzModuleIfNeeded -name 'Az.KeyVault'
try {
Clear-AzContext -Scope Process
Clear-AzContext -Scope CurrentUser -Force -ErrorAction SilentlyContinue
Expand All @@ -2431,7 +2437,7 @@ function ConnectAz {
Write-Host "Selecting subscription $($azureCredentials.SubscriptionId)"
Set-AzContext -SubscriptionId $azureCredentials.SubscriptionId -Tenant $azureCredentials.TenantId -ErrorAction SilentlyContinue -WarningAction SilentlyContinue | Out-Null
}
$script:keyvaultConnectionExists = $true
$script:AzConnected = $true
Write-Host "Successfully connected to Azure"
}
catch {
Expand Down
1 change: 1 addition & 0 deletions Actions/ReadSecrets/ReadSecrets.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ try {
$result = Invoke-RestMethod -Method GET -UseBasicParsing -Headers @{ "Authorization" = "bearer $ENV:ACTIONS_ID_TOKEN_REQUEST_TOKEN"; "Accept" = "application/vnd.github+json" } -Uri "$ENV:ACTIONS_ID_TOKEN_REQUEST_URL&audience=api://AzureADTokenExchange"
$json += @{ "clientAssertion" = $result.value }
$secretValue = $json | ConvertTo-Json -Compress
MaskValue -key "$secretName with federated token" -value $secretValue
}
catch {
throw "$SecretName doesn't contain any ClientSecret and AL-Go is unable to acquire an ID_TOKEN. Error was $($_.Exception.Message)"
Expand Down
42 changes: 25 additions & 17 deletions Actions/ReadSecrets/ReadSecretsHelper.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,29 @@ Param(
)

$script:gitHubSecrets = $_gitHubSecrets | ConvertFrom-Json
$script:keyvaultConnectionExists = $false
$script:isKeyvaultSet = $script:gitHubSecrets.PSObject.Properties.Name -eq "AZURE_CREDENTIALS"
$script:escchars = @(' ','!','\"','#','$','%','\u0026','\u0027','(',')','*','+',',','-','.','/','0','1','2','3','4','5','6','7','8','9',':',';','\u003c','=','\u003e','?','@','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','[','\\',']','^','_',[char]96,'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','{','|','}','~')

. (Join-Path -Path $PSScriptRoot -ChildPath "..\AL-Go-Helper.ps1" -Resolve)

function GetAzureCredentialsSecretName {
$settings = $env:Settings | ConvertFrom-Json
if ($settings.PSObject.Properties.Name -eq "AZURE_CREDENTIALSSecretName") {
return $settings.AZURE_CREDENTIALSSecretName
}
else {
return "AZURE_CREDENTIALS"
}
}

function GetAzureCredentials {
$secretName = GetAzureCredentialsSecretName
if ($script:gitHubSecrets.PSObject.Properties.Name -eq $secretName) {
return $script:gitHubSecrets."$secretName"
}
return $null
}


function MaskValue {
Param(
[string] $key,
Expand Down Expand Up @@ -68,10 +85,10 @@ function GetGithubSecret {

function GetKeyVaultCredentials {
$creds = $null
if ($script:isKeyvaultSet) {
$jsonStr = $script:gitHubSecrets.AZURE_CREDENTIALS
$jsonStr = GetAzureCredentials
if ($jsonStr) {
if ($jsonStr -contains "`n" -or $jsonStr -contains "`r") {
throw "Secret AZURE_CREDENTIALS cannot contain line breaks, needs to be formatted as compressed JSON (no line breaks)"
throw "Secret for Azure KeyVault Connection ($(GetAzureCredentialsSecretName)) cannot contain line breaks, needs to be formatted as compressed JSON (no line breaks)"
}
try {
$creds = $jsonStr | ConvertFrom-Json
Expand All @@ -84,7 +101,7 @@ function GetKeyVaultCredentials {
$creds.TenantId | Out-Null
}
catch {
throw "Secret AZURE_CREDENTIALS is wrongly formatted. Needs to be formatted as compressed JSON (no line breaks) and contain at least the properties: clientId, clientSecret, tenantId and subscriptionId."
throw "Secret for Azure KeyVault Connection ($(GetAzureCredentialsSecretName)) is wrongly formatted. Needs to be formatted as compressed JSON (no line breaks) and contain at least the properties: clientId, clientSecret, tenantId and subscriptionId."
}
$keyVaultNameExists = $creds.PSObject.Properties.Name -eq 'keyVaultName'
$settings = $env:Settings | ConvertFrom-Json
Expand All @@ -111,20 +128,11 @@ function GetKeyVaultSecret {
[PsCustomObject] $keyVaultCredentials,
[switch] $encrypted
)

if (-not $script:isKeyvaultSet) {
if ($null -eq $keyVaultCredentials) {
return $null
}

if (-not $script:keyvaultConnectionExists) {
InstallAzModuleIfNeeded -name 'Az.KeyVault'
try {
ConnectAz -azureCredentials $keyVaultCredentials
}
catch {
throw "Error trying to get secrets from Azure Key Vault. Error was $($_.Exception.Message)"
}
}
ConnectAz -azureCredentials $keyVaultCredentials

$secretSplit = $secretName.Split('=')
$envVar = $secretSplit[0]
Expand Down
2 changes: 1 addition & 1 deletion Actions/Sign/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Sign apps with a certificate stored in Azure Key Vault
| :-- | :-: | :-- | :-- |
| shell | | The shell (powershell or pwsh) in which the PowerShell script in this action should run | powershell |
| parentTelemetryScopeJson | | Specifies the parent telemetry scope for the telemetry signal | {} |
| azureCredentialsJson | Yes | Azure Credentials secret | |
| azureCredentialsJson | Yes | Azure Credentials secret (Base 64 encoded) | |
| timestampService | | The URI of the timestamp server | http://timestamp.digicert.com |
| digestAlgorithm | | The digest algorithm to use for signing and timestamping | SHA256 |
| pathToFiles | Yes | The path to the files to be signed |
Expand Down
4 changes: 2 additions & 2 deletions Actions/Sign/Sign.ps1
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingPlainTextForPassword', '', Justification = 'GitHub Secrets are transferred as plain text')]
param(
[Parameter(HelpMessage = "Azure Credentials secret", Mandatory = $true)]
[Parameter(HelpMessage = "Azure Credentials secret (Base 64 encoded)", Mandatory = $true)]
[string] $AzureCredentialsJson,
[Parameter(HelpMessage = "The path to the files to be signed", Mandatory = $true)]
[String] $PathToFiles,
Expand Down Expand Up @@ -34,7 +34,7 @@ try {
Write-Host "::endgroup::"

# Get parameters for signing
$AzureCredentials = ConvertFrom-Json $AzureCredentialsJson
$AzureCredentials = ConvertFrom-Json ([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($AzureCredentialsJson)))
$settings = $env:Settings | ConvertFrom-Json
if ($settings.keyVaultName) {
$AzureKeyVaultName = $settings.keyVaultName
Expand Down
2 changes: 1 addition & 1 deletion Actions/Sign/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ inputs:
required: false
default: powershell
azureCredentialsJson:
description: Azure Credentials secret
description: Azure Credentials secret (Base 64 encoded)
required: true
pathToFiles:
description: The path to the files to be signed
Expand Down
1 change: 1 addition & 0 deletions RELEASENOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

- Issue 1105 Increment Version Number - repoVersion in .github/AL-Go-Settings.json is not updated
- Issue 1073 Publish to AppSource - Automated validation: failure
- Issue 1098 Support for specifying the name of the AZURE_CREDENTIALS secret by adding a AZURE_CREDENTIALSSecretName setting

### Dependencies to PowerShell modules

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ jobs:
with:
shell: ${{ inputs.shell }}
gitHubSecrets: ${{ toJson(secrets) }}
getSecrets: '${{ inputs.secrets }},appDependencyProbingPathsSecrets'
getSecrets: '${{ inputs.secrets }},appDependencyProbingPathsSecrets,AZURE_CREDENTIALS'

- name: Determine ArtifactUrl
uses: microsoft/AL-Go-Actions/DetermineArtifactUrl@main
Expand Down Expand Up @@ -159,7 +159,7 @@ jobs:
uses: microsoft/AL-Go-Actions/Sign@main
with:
shell: ${{ needs.Initialization.outputs.githubRunnerShell }}
azureCredentialsJson: ${{ secrets.AZURE_CREDENTIALS }}
azureCredentialsJson: '${{ fromJson(steps.ReadSecrets.outputs.Secrets).AZURE_CREDENTIALS }}'
pathToFiles: '${{ inputs.project }}/.buildartifacts/Apps/*.app'
parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ jobs:
with:
shell: ${{ inputs.shell }}
gitHubSecrets: ${{ toJson(secrets) }}
getSecrets: '${{ inputs.secrets }},appDependencyProbingPathsSecrets'
getSecrets: '${{ inputs.secrets }},appDependencyProbingPathsSecrets,AZURE_CREDENTIALS'

- name: Determine ArtifactUrl
uses: microsoft/AL-Go-Actions/DetermineArtifactUrl@main
Expand Down Expand Up @@ -159,7 +159,7 @@ jobs:
uses: microsoft/AL-Go-Actions/Sign@main
with:
shell: ${{ needs.Initialization.outputs.githubRunnerShell }}
azureCredentialsJson: ${{ secrets.AZURE_CREDENTIALS }}
azureCredentialsJson: '${{ fromJson(steps.ReadSecrets.outputs.Secrets).AZURE_CREDENTIALS }}'
pathToFiles: '${{ inputs.project }}/.buildartifacts/Apps/*.app'
parentTelemetryScopeJson: ${{ needs.Initialization.outputs.telemetryScopeJson }}

Expand Down
Loading