Skip to content

Commit

Permalink
Enable trusted Signing (#1280)
Browse files Browse the repository at this point in the history
## 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.

New setting example:

  "trustedSigning": {
    "Endpoint": "https://neu.codesigning.azure.net",
    "Account": "BCCodeSigningTest",
    "CertificateProfile": "BCCodeSigningPublic"
  }

These values are defined from your trusted signing account in Azure.

Note that your Azure_Credentials secret (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.

---------

Co-authored-by: freddydk <freddydk@users.noreply.github.com>
  • Loading branch information
freddydk and freddydk authored Oct 28, 2024
1 parent 754f321 commit cf04f7b
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 51 deletions.
5 changes: 5 additions & 0 deletions Actions/AL-Go-Helper.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
43 changes: 27 additions & 16 deletions Actions/Sign/Sign.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand All @@ -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 `
Expand Down
72 changes: 47 additions & 25 deletions Actions/Sign/Sign.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand All @@ -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 `
Expand All @@ -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
}
}
}

Expand Down
20 changes: 14 additions & 6 deletions RELEASENOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,27 @@

- 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:

- `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
Expand Down
1 change: 1 addition & 0 deletions Scenarios/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ The repository settings are only read from the repository settings file (.github
| <a id="excludeEnvironments"></a>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. | \[ \] |
| <a id="trustMicrosoftNuGetFeeds"></a>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 |
| <a id="trustedNuGetFeeds"></a>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:<br />**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").<br />**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.<br />**patterns** = AL-Go for GitHub will only trust packages, where the ID matches this pattern. Default is all packages (\*).<br />**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. | \[ \] |
| <a id="trustedSigning"></a>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:<br />**Account** must be the name of your trusted signing account.<br />**Endpoint** must point to the endpoint of your trusted signing account (ex. https://weu.codesigning.azure.net).<br />**CertificateProfile** must be the CertificateProfile in your trusted signing account you want to use for signing.<br />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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down

6 comments on commit cf04f7b

@mcebailly
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey sir, how can we include this new signing process in our actions for our App Source projects?

@freddydk
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't created a workshop scenario yet - but it is described in the PR description above

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 for AL-Go
to sign your apps using Azure Trusted Signing.

New setting example:

"trustedSigning": {
"Endpoint": "https://neu.codesigning.azure.net/",
"Account": "BCCodeSigningTest",
"CertificateProfile": "BCCodeSigningPublic"
}

These values are defined from your trusted signing account in Azure.

Note that your Azure_Credentials secret (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.

@mcebailly
Copy link

@mcebailly mcebailly commented on cf04f7b Oct 30, 2024 via email

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@freddydk
Copy link
Contributor Author

@freddydk freddydk commented on cf04f7b Oct 30, 2024 via email

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mcebailly
Copy link

@mcebailly mcebailly commented on cf04f7b Oct 30, 2024 via email

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@freddydk
Copy link
Contributor Author

@freddydk freddydk commented on cf04f7b Oct 30, 2024 via email

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.