diff --git a/Actions/AL-Go-Helper.ps1 b/Actions/AL-Go-Helper.ps1
index fee6f3258..81bbd41c2 100644
--- a/Actions/AL-Go-Helper.ps1
+++ b/Actions/AL-Go-Helper.ps1
@@ -661,6 +661,11 @@ function ReadSettings {
"defaultReleaseMD" = "## Release reference documentation\n\nThis is the generated reference documentation for [{REPOSITORY}](https://github.com/{REPOSITORY}).\n\nYou can use the navigation bar at the top and the table of contents to the left to navigate your documentation.\n\nYou can change this content by creating/editing the **{INDEXTEMPLATERELATIVEPATH}** file in your repository or use the alDoc:defaultReleaseMD setting in your repository settings file (.github/AL-Go-Settings.json)\n\n{RELEASENOTES}"
}
"trustMicrosoftNuGetFeeds" = $true
+ "trustedSigning" = [ordered]@{
+ "Endpoint" = ""
+ "Account" = ""
+ "CertificateProfile" = ""
+ }
}
# Read settings from files and merge them into the settings object
diff --git a/Actions/Sign/Sign.ps1 b/Actions/Sign/Sign.ps1
index 4e3a0f3b7..6e123f6a8 100644
--- a/Actions/Sign/Sign.ps1
+++ b/Actions/Sign/Sign.ps1
@@ -28,23 +28,35 @@ Write-Host "::endgroup::"
# Get parameters for signing
$AzureCredentials = ConvertFrom-Json ([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($AzureCredentialsJson)))
$settings = $env:Settings | ConvertFrom-Json
-if ($settings.keyVaultName) {
- $AzureKeyVaultName = $settings.keyVaultName
-}
-elseif ($AzureCredentials.PSobject.Properties.name -eq "keyVaultName") {
- $AzureKeyVaultName = $AzureCredentials.keyVaultName
+
+if ($settings.TrustedSigning.Endpoint -and $settings.TrustedSigning.Account -and $settings.TrustedSigning.CertificateProfile) {
+ $SigningParams = @{
+ "SigningEndpoint" = $settings.TrustedSigning.Endpoint
+ "SigningAccount" = $settings.TrustedSigning.Account
+ "SigningCertificateProfile" = $settings.TrustedSigning.CertificateProfile
+ }
}
else {
- throw "KeyVaultName is not specified in AzureCredentials nor in settings. Please specify it in one of them."
-}
+ if ($settings.keyVaultName) {
+ $AzureKeyVaultName = $settings.keyVaultName
+ }
+ elseif ($AzureCredentials.PSobject.Properties.name -eq "keyVaultName") {
+ $AzureKeyVaultName = $AzureCredentials.keyVaultName
+ }
+ else {
+ throw "KeyVaultName is not specified in AzureCredentials nor in settings. Please specify it in one of them."
+ }
-$AzureCredentialParams = @{
- "ClientId" = $AzureCredentials.clientId
- "TenantId" = $AzureCredentials.tenantId
-}
-if ($AzureCredentials.PSobject.Properties.name -eq "clientSecret") {
- $AzureCredentialParams += @{
- "ClientSecret" = $AzureCredentials.clientSecret
+ $SigningParams = @{
+ "ClientId" = $AzureCredentials.clientId
+ "TenantId" = $AzureCredentials.tenantId
+ "KeyVaultName" = $AzureKeyVaultName
+ "CertificateName" = $settings.keyVaultCodesignCertificateName
+ }
+ if ($AzureCredentials.PSobject.Properties.name -eq "clientSecret") {
+ $SigningParams += @{
+ "ClientSecret" = $AzureCredentials.clientSecret
+ }
}
}
InstallAzModuleIfNeeded -name 'Az.Accounts'
@@ -54,8 +66,7 @@ $description = "Signed with AL-Go for GitHub"
$descriptionUrl = "$ENV:GITHUB_SERVER_URL/$ENV:GITHUB_REPOSITORY"
Write-Host "::group::Signing files"
-Invoke-SigningTool @AzureCredentialParams -KeyVaultName $AzureKeyVaultName `
- -CertificateName $settings.keyVaultCodesignCertificateName `
+Invoke-SigningTool @SigningParams `
-FilesToSign $PathToFiles `
-Description $description `
-DescriptionUrl $descriptionUrl `
diff --git a/Actions/Sign/Sign.psm1 b/Actions/Sign/Sign.psm1
index 3d8d9fce9..439b2c711 100644
--- a/Actions/Sign/Sign.psm1
+++ b/Actions/Sign/Sign.psm1
@@ -78,16 +78,22 @@ function Install-SigningTool() {
#>
function Invoke-SigningTool() {
param(
- [Parameter(Mandatory = $true)]
+ [Parameter(Mandatory = $true, ParameterSetName="KeyVaultSigning")]
[string] $KeyVaultName,
- [Parameter(Mandatory = $true)]
+ [Parameter(Mandatory = $true, ParameterSetName="KeyVaultSigning")]
[string] $CertificateName,
- [Parameter(Mandatory = $false)]
+ [Parameter(Mandatory = $false, ParameterSetName="KeyVaultSigning")]
[string] $ClientId,
- [Parameter(Mandatory = $false)]
+ [Parameter(Mandatory = $false, ParameterSetName="KeyVaultSigning")]
[string] $ClientSecret,
- [Parameter(Mandatory = $false)]
+ [Parameter(Mandatory = $false, ParameterSetName="KeyVaultSigning")]
[string] $TenantId,
+ [Parameter(Mandatory = $true, ParameterSetName="TrustedSigning")]
+ [string] $SigningEndpoint,
+ [Parameter(Mandatory = $true, ParameterSetName="TrustedSigning")]
+ [string] $SigningAccount,
+ [Parameter(Mandatory = $true, ParameterSetName="TrustedSigning")]
+ [string] $SigningCertificateProfile,
[Parameter(Mandatory = $true)]
[string] $FilesToSign,
[Parameter(Mandatory = $true)]
@@ -105,14 +111,12 @@ function Invoke-SigningTool() {
$signingToolExe = Install-SigningTool
# Sign files
- if ($ClientId -and $ClientSecret -and $TenantId) {
- Write-Host "Invoking signing tool using clientId/clientSecret"
- . $signingToolExe code azure-key-vault `
- --azure-key-vault-url "https://$KeyVaultName.vault.azure.net/" `
- --azure-key-vault-certificate $CertificateName `
- --azure-key-vault-client-id $ClientId `
- --azure-key-vault-client-secret $ClientSecret `
- --azure-key-vault-tenant-id $TenantId `
+ if ($PsCmdlet.ParameterSetName -eq "TrustedSigning") {
+ Write-Host "Invoking signing tool using trusted signing"
+ . $signingToolExe code trusted-signing `
+ --trusted-signing-endpoint $SigningEndpoint `
+ --trusted-signing-account $SigningAccount `
+ --trusted-signing-certificate-profile $SigningCertificateProfile `
--description $Description `
--description-url $DescriptionUrl `
--file-digest $DigestAlgorithm `
@@ -122,18 +126,36 @@ function Invoke-SigningTool() {
$FilesToSign
}
else {
- Write-Host "Invoking signing tool using managed identity"
- . $signingToolExe code azure-key-vault `
- --azure-key-vault-url "https://$KeyVaultName.vault.azure.net/" `
- --azure-key-vault-certificate $CertificateName `
- --azure-key-vault-managed-identity $true `
- --description $Description `
- --description-url $DescriptionUrl `
- --file-digest $DigestAlgorithm `
- --timestamp-digest $DigestAlgorithm `
- --timestamp-url $TimestampService `
- --verbosity $Verbosity `
- $FilesToSign
+ if ($ClientId -and $ClientSecret -and $TenantId) {
+ Write-Host "Invoking signing tool using clientId/clientSecret"
+ . $signingToolExe code azure-key-vault `
+ --azure-key-vault-url "https://$KeyVaultName.vault.azure.net/" `
+ --azure-key-vault-certificate $CertificateName `
+ --azure-key-vault-client-id $ClientId `
+ --azure-key-vault-client-secret $ClientSecret `
+ --azure-key-vault-tenant-id $TenantId `
+ --description $Description `
+ --description-url $DescriptionUrl `
+ --file-digest $DigestAlgorithm `
+ --timestamp-digest $DigestAlgorithm `
+ --timestamp-url $TimestampService `
+ --verbosity $Verbosity `
+ $FilesToSign
+ }
+ else {
+ Write-Host "Invoking signing tool using managed identity"
+ . $signingToolExe code azure-key-vault `
+ --azure-key-vault-url "https://$KeyVaultName.vault.azure.net/" `
+ --azure-key-vault-certificate $CertificateName `
+ --azure-key-vault-managed-identity $true `
+ --description $Description `
+ --description-url $DescriptionUrl `
+ --file-digest $DigestAlgorithm `
+ --timestamp-digest $DigestAlgorithm `
+ --timestamp-url $TimestampService `
+ --verbosity $Verbosity `
+ $FilesToSign
+ }
}
}
diff --git a/RELEASENOTES.md b/RELEASENOTES.md
index aee778dbc..f54abcdff 100644
--- a/RELEASENOTES.md
+++ b/RELEASENOTES.md
@@ -2,6 +2,20 @@
- Issue 1241 Increment Version Number might produce wrong app.json
+### New Project Settings
+
+- `pageScriptingTests` should be an array of page scripting test file specifications, relative to the AL-Go project. Examples of file specifications: `recordings/my*.yml` (for all yaml files in the recordings subfolder matching my\*.yml), `recordings` (for all \*.yml files in the recordings subfolder) or `recordings/test.yml` (for a single yml file)
+- `doNotRunPageScriptingTests` can force the pipeline to NOT run the page scripting tests specified in pageScriptingTests. Note this setting can be set in a [workflow specific settings file](#where-are-the-settings-located) to only apply to that workflow
+- `restoreDatabases` should be an array of events, indicating when you want to start with clean databases in the container. Possible events are: `BeforeBcpTests`, `BeforePageScriptingTests`, `BeforeEachTestApp`, `BeforeEachBcptTestApp`, `BeforeEachPageScriptingTest`
+
+### New Repository Settings
+
+- `trustedSigning` is a structure defining `Account`, `EndPoint` and `CertificateProfile` if you want to use trusted signing. Note that your Azure_Credentials secret (Microsoft Entra ID App or Managed identity) still needs to provide access to your azure subscription and be assigned the `Trusted Signing Certificate Profile Signer` role in the Trusted Signing Account.
+
+### Support for Azure Trusted Signing
+
+Read https://learn.microsoft.com/en-us/azure/trusted-signing/ for more information about Trusted Signing and how to set it up. After setting up your trusted signing account and certificate profile, you need to create a setting called [trustedSigning](https://aka.ms/algosettings#trustedSigning) for AL-Go to sign your apps using Azure Trusted Signing.
+
### Support for Page Scripting Tests
Page Scripting tests are now supported as part of CI/CD. By specifying pageScriptingTests in your project settings file, AL-Go for GitHub will automatically run these page scripting tests as part of your CI/CD workflow, generating the following build artifacts:
@@ -9,12 +23,6 @@ Page Scripting tests are now supported as part of CI/CD. By specifying pageScrip
- `PageScriptingTestResults` is a JUnit test results file with all results combined.
- `PageScriptingTestResultDetails` are the detailed test results (including videos) when any of the page scripting tests have failures. If the page scripting tests succeed - the details are not published.
-### New Project Settings
-
-- `pageScriptingTests` should be an array of page scripting test file specifications, relative to the AL-Go project. Examples of file specifications: `recordings/my*.yml` (for all yaml files in the recordings subfolder matching my\*.yml), `recordings` (for all \*.yml files in the recordings subfolder) or `recordings/test.yml` (for a single yml file)
-- `doNotRunPageScriptingTests` can force the pipeline to NOT run the page scripting tests specified in pageScriptingTests. Note this setting can be set in a [workflow specific settings file](#where-are-the-settings-located) to only apply to that workflow
-- `restoreDatabases` should be an array of events, indicating when you want to start with clean databases in the container. Possible events are: `BeforeBcpTests`, `BeforePageScriptingTests`, `BeforeEachTestApp`, `BeforeEachBcptTestApp`, `BeforeEachPageScriptingTest`
-
## v6.0
### Issues
diff --git a/Scenarios/settings.md b/Scenarios/settings.md
index 677f2b9f2..7b7fae0bf 100644
--- a/Scenarios/settings.md
+++ b/Scenarios/settings.md
@@ -121,6 +121,7 @@ The repository settings are only read from the repository settings file (.github
| excludeEnvironments | excludeEnvironments can be an array of GitHub Environments, which should be excluded from the list of environments considered for deployment. github-pages is automatically added to this array and cannot be used as environment for deployment of AL-Go for GitHub projects. | \[ \] |
| trustMicrosoftNuGetFeeds | Unless this setting is set to false, AL-Go for GitHub will trust the NuGet feeds provided by Microsoft. The feeds provided by Microsoft contains all Microsoft apps, all Microsoft symbols and symbols for all AppSource apps. | true |
| trustedNuGetFeeds | trustedNuGetFeeds can be an array of NuGet feed specifications, which AL-Go for GitHub will use for dependency resolution. Every feed specification must include a URL property and can optionally include a few other properties:
**url** = The URL of the feed (examples: https://pkgs.dev.azure.com/myorg/apps/\_packaging/myrepo/nuget/v3/index.json or https://nuget.pkg.github.com/mygithuborg/index.json").
**authTokenSecret** = If the NuGet feed specified by URL is private, the authTokenSecret must be the name of a secret containing the authentication token with permissions to search and read packages from the NuGet feed.
**patterns** = AL-Go for GitHub will only trust packages, where the ID matches this pattern. Default is all packages (\*).
**fingerprints** = If specified, AL-Go for GitHub will only trust packages signed with a certificate with a fingerprint matching one of the fingerprints in this array. | \[ \] |
+| trustedSigning | Structure defining the properties needed for enabling trusted Signing. Please read [this](https://learn.microsoft.com/en-us/azure/trusted-signing/) to setup your Azure Trusted Signing Account and Certificate Profile and then provide these properties in this setting:
**Account** must be the name of your trusted signing account.
**Endpoint** must point to the endpoint of your trusted signing account (ex. https://weu.codesigning.azure.net).
**CertificateProfile** must be the CertificateProfile in your trusted signing account you want to use for signing.
Please note that your Azure_Credentials secret (Microsoft Entra ID App or Managed identity) needs to provide access to your azure subscription and be assigned the `Trusted Signing Certificate Profile Signer` role in the Trusted Signing Account. |
## AppSource specific advanced settings
diff --git a/Templates/AppSource App/.github/workflows/_BuildALGoProject.yaml b/Templates/AppSource App/.github/workflows/_BuildALGoProject.yaml
index fb7cc20ec..c66027d23 100644
--- a/Templates/AppSource App/.github/workflows/_BuildALGoProject.yaml
+++ b/Templates/AppSource App/.github/workflows/_BuildALGoProject.yaml
@@ -97,7 +97,7 @@ jobs:
with:
shell: ${{ inputs.shell }}
project: ${{ inputs.project }}
- get: useCompilerFolder,keyVaultCodesignCertificateName,doNotSignApps,doNotRunTests,artifact,generateDependencyArtifact
+ get: useCompilerFolder,keyVaultCodesignCertificateName,doNotSignApps,doNotRunTests,artifact,generateDependencyArtifact,trustedSigning
- name: Read secrets
id: ReadSecrets
@@ -148,7 +148,7 @@ jobs:
installTestAppsJson: ${{ steps.DownloadProjectDependencies.outputs.DownloadedTestApps }}
- name: Sign
- if: inputs.signArtifacts && env.doNotSignApps == 'False' && env.keyVaultCodesignCertificateName != ''
+ if: inputs.signArtifacts && env.doNotSignApps == 'False' && (env.keyVaultCodesignCertificateName != '' || (fromJson(env.trustedSigning).Endpoint != '' && fromJson(env.trustedSigning).Account != '' && fromJson(env.trustedSigning).CertificateProfile != ''))
id: sign
uses: microsoft/AL-Go-Actions/Sign@main
with:
diff --git a/Templates/Per Tenant Extension/.github/workflows/_BuildALGoProject.yaml b/Templates/Per Tenant Extension/.github/workflows/_BuildALGoProject.yaml
index fb7cc20ec..c66027d23 100644
--- a/Templates/Per Tenant Extension/.github/workflows/_BuildALGoProject.yaml
+++ b/Templates/Per Tenant Extension/.github/workflows/_BuildALGoProject.yaml
@@ -97,7 +97,7 @@ jobs:
with:
shell: ${{ inputs.shell }}
project: ${{ inputs.project }}
- get: useCompilerFolder,keyVaultCodesignCertificateName,doNotSignApps,doNotRunTests,artifact,generateDependencyArtifact
+ get: useCompilerFolder,keyVaultCodesignCertificateName,doNotSignApps,doNotRunTests,artifact,generateDependencyArtifact,trustedSigning
- name: Read secrets
id: ReadSecrets
@@ -148,7 +148,7 @@ jobs:
installTestAppsJson: ${{ steps.DownloadProjectDependencies.outputs.DownloadedTestApps }}
- name: Sign
- if: inputs.signArtifacts && env.doNotSignApps == 'False' && env.keyVaultCodesignCertificateName != ''
+ if: inputs.signArtifacts && env.doNotSignApps == 'False' && (env.keyVaultCodesignCertificateName != '' || (fromJson(env.trustedSigning).Endpoint != '' && fromJson(env.trustedSigning).Account != '' && fromJson(env.trustedSigning).CertificateProfile != ''))
id: sign
uses: microsoft/AL-Go-Actions/Sign@main
with: