Skip to content

Commit

Permalink
changes to full sample including sbom
Browse files Browse the repository at this point in the history
  • Loading branch information
Paul Savoie committed Mar 5, 2024
1 parent d1b3e43 commit e872445
Show file tree
Hide file tree
Showing 21 changed files with 2,922 additions and 13 deletions.
Original file line number Diff line number Diff line change
@@ -1,31 +1,37 @@
# This workflow is a demo of how to use the Gihub Actions workflow steps for SignPath. For a complete documentation,
# view https://github.com/SignPath/github-actions

name: sign-with-signpath
name: build-and-sign
run-name: Demo workflow signing with SignPath
on:
push:
branches: ["main"]
pull_request:
schedule:
- cron: '30 3 * * *' # every day at 3:30am UTC
workflow_dispatch: # Allows you to run this workflow manually from the Actions tab

jobs:
build-and-sign:
build_and_sign:
runs-on: windows-latest
steps:

- name: checkout
uses: actions/checkout@v3
with:
fetch-depth: 0

- name: build
run: "echo \"This is a dummy build step that creates build-output/hello-world.exe\""
run: ./src/Build.ps1

- name: create SBOM
run: ./sbom/Create-SBOM.ps1

- name: upload-unsigned-artifact
- name: upload-unsigned-artifact
uses: actions/upload-artifact@v3
with:
name: "hello-world"
path: "./build-output/hello-world.exe"
name: "demo-application-unsigned"
path: "./_BuildResult-unsigned"
if-no-files-found: error

- name: sign
Expand All @@ -34,15 +40,15 @@ jobs:
github-token: '${{ secrets.GITHUB_TOKEN }}'
api-token: '${{ secrets.SIGNPATH_API_TOKEN }}'
organization-id: '${{ vars.SIGNPATH_ORGANIZATION_ID }}'
project-slug: 'Executable'
signing-policy-slug: 'test-signing'
artifact-configuration-slug: 'initial'
artifact-name: "hello-world"
output-artifact-directory: "build-output/signed"
project-slug: 'Demo Application'
signing-policy-slug: ${{ github.ref == 'refs/heads/main' && 'release-signing' || 'test-signing' }}
artifact-configuration-slug: 'v1'
artifact-name: "demo-application-unsigned"
output-artifact-directory: "_BuildResult-signed"

- name: upload-signed-artifact
uses: actions/upload-artifact@v3
with:
name: "hello-world-signed"
path: "./build-output/signed/hello-world.exe"
name: "demo-application-signed"
path: "_BuildResult-signed"
if-no-files-found: error
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.store
.vs
bin
node_modules
obj
src/wwwroot/js
_temp
bom.xml
verification
Binary file removed build-output/hello-world.exe
Binary file not shown.
Binary file removed build-output/sample.dll
Binary file not shown.
55 changes: 55 additions & 0 deletions sbom/Create-SBOM.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# PowerShell script that will create the SBOM file

# 1 Preparation
# 1.a general settings
$ErrorActionPreference = "Stop"
function Fail-On-Error {
param(
$description
)

if ($LASTEXITCODE -ne 0) {
Write-Host "Executing '$description' failed with exit code $LASTEXITCODE."
exit 1
}
}

# 1.b Create a temporary folder
$tempPath = Join-Path $PSScriptRoot "_temp"
New-Item -ItemType Directory -Force -Path $tempPath

# 2 Create NuGet SBOM
# 2.a install the .Net tool
dotnet tool install cyclonedx --tool-path $tempPath

# 2.b create nuget bom
$cyclonDxToolPath = Join-Path $tempPath "dotnet-CycloneDX.exe"
& "${cyclonDxToolPath}" --output "${tempPath}" -f "nuget.bom.xml" --exclude-dev ..\src\DemoExample.csproj

# 3 Create NPM SBOM
$packageJsonPath = Join-Path $PSScriptRoot ".." "src" "package.json"
$npmBomPath = Join-Path $tempPath "npm.bom.xml"

# 3.a make sure the package is installed
Push-Location (Join-Path $PSScriptRoot ".." "src")
npm install --omit=optional
Fail-On-Error "npm install"
Pop-Location

# 3.b. create actual NPM SBOM
npx --yes "@cyclonedx/cyclonedx-npm" "${packageJsonPath}" --omit dev --output-format XML --output-file "${npmBomPath}"
Fail-On-Error "cyclonedx-npm"

# 4 Merge SBOMs
# 4.a download cyclonedx-cli.exe
$cycloneDxCliToolPath = Join-Path $tempPath "cyclonedx-cli.exe"
if (-Not (Test-Path $cycloneDxCliToolPath)) {
$releases = Invoke-RestMethod -Uri "https://api.github.com/repos/CycloneDX/cyclonedx-cli/releases"
$asset = ($releases | Select-Object -First 1).assets | ? { $_.name -eq "cyclonedx-win-x64.exe" }
Invoke-WebRequest -Uri ($asset.browser_download_url) -OutFile "${cycloneDxCliToolPath}"
}

# 4.b merge both SBOMs into a final one
$nugetBomPath = Join-Path $tempPath "nuget.bom.xml"
$finalBomPath = Join-Path $PSScriptRoot ".." "_BuildResult-unsigned" "bom.xml"
& "${cycloneDxCliToolPath}" merge --input-files "${npmBomPath}" "${nugetBomPath}" --output-format "xml" --output-file "${finalBomPath}" --group "com.SignPath.demos" --name "SignPath Demo Application" --version "1.0.0"
26 changes: 26 additions & 0 deletions sbom/Verify-SBOM.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
New-Item -ItemType Directory -Force -Path verification

# Get signing request details
$signingRequestDetails = Invoke-RestMethod -Headers @{ Authorization = "Bearer ${env:SIGNPATH_CI_USER_TOKEN}" } `
"https://app.signpath.io/Api/v1/${env:SIGNPATH_ORGANIZATION_ID}/SigningRequests/${env:SIGNPATH_SIGNING_REQUEST_ID}"
# Get project details
$projectDetails = Invoke-RestMethod -Headers @{ Authorization = "Bearer ${env:SIGNPATH_CI_USER_TOKEN}" } `
"https://app.signpath.io/Api/v1-pre/${env:SIGNPATH_ORGANIZATION_ID}/Projects/$($signingRequestDetails.projectSlug)"
# Extract signing policy from project details
$signingPolicyDetails = $projectDetails.signingPolicies `
| Where-Object {$_.metadata.slug -eq $signingRequestDetails.signingPolicySlug} `
| Select -First 1

# Download certificate
Invoke-WebRequest -Headers @{ Authorization = "Bearer ${env:SIGNPATH_CI_USER_TOKEN}" } `
"$($signingPolicyDetails.certificateUrl)/X509Certificate" -OutFile verification/certificate.cer
# Extract public key
openssl x509 -pubkey -noout -in verification/certificate.cer -inform DER -out verification/public_key.pem

# Download verify tool
$releases = Invoke-RestMethod -Uri "https://api.github.com/repos/signpath/cyclonedx-cli/releases"
$asset = ($releases | Select-Object -First 1).assets | ? { $_.name -eq "cyclonedx-win-x64.exe" }
Invoke-WebRequest -Uri ($asset.browser_download_url) -OutFile "verification/cyclonedx-cli.exe"

# Actual verification
& ./verification/cyclonedx-cli.exe verify all ./_BuildResult-signed/bom.xml --key-file ./verification/public_key.pem
13 changes: 13 additions & 0 deletions src/Build.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# build .Net application
dotnet build --configuration Release

# build MSI installer
Copy-Item src\installer\description.wxs .\src\bin\Release\net7.0\description.wxs -Force
Push-Location .src\bin\Release\net7.0
& "${env:WIX}bin\candle.exe" description.wxs
& "${env:WIX}bin\light.exe" description.wixobj -out DemoExample.msi
Pop-Location

# copy build to output directory
New-Item -ItemType Directory -Path "_BuildResult-unsigned"
Copy-Item src\bin\Release\net7.0\DemoExample.msi _BuildResult-unsigned\DemoExample.msi
18 changes: 18 additions & 0 deletions src/DemoExample.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Serilog.AspNetCore" Version="7.0.0" />
</ItemGroup>

<Target Name="BuildClientAssets" BeforeTargets="Build">
<Exec Command="npm install" />
<Exec Command="npm run build" />
</Target>

</Project>
25 changes: 25 additions & 0 deletions src/Pages/Index.cshtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
@page

<div>
<svg xmlns="http://www.w3.org/2000/svg" id="logo" viewbox="0,0,620.2,124.6" width="620.20001" height="124.6">
<title>SignPath GmbH</title>
<g id="g3684" transform="translate(-27.1 -22.8)">
<path id="path3682" fill="#fff" d="M133.4 22.8H62.6L27.1 84.2l35.4 61.4h70.9l35.4-61.4zm1.7 68.6c-.7 1.6-2.3 2.6-4.1 2.6H94.2c-2.5 0-4.5-2-4.5-4.5s2-4.5 4.5-4.5H121l-10.5-11.9a4.43 4.43 0 0 1 0-5.9L121 55.3H76.7v71.2c0 2.5-2 4.5-4.5 4.5s-4.5-2-4.5-4.5V41.7c0-2.5 2-4.5 4.5-4.5s4.5 2 4.5 4.5v4.6H131c1.8 0 3.4 1 4.1 2.6.7 1.6.4 3.5-.7 4.8L120 70.1l14.4 16.4c1.1 1.4 1.4 3.3.7 4.9z"/>
</g>
<g id="Inhalt" transform="translate(-27.1 -22.8)">
<g id="g3705">
<g id="g3703">
<path id="path3687" stroke="#fff" stroke-width="3" fill="none" d="M208.4 104c7.3 5.8 16 9.2 25.3 9.2 9.1 0 15.5-3.2 15.5-10.4 0-6.2-4-8.7-11.2-11.4l-11.6-4.2c-10.6-3.9-18.7-9.6-18.7-22.7 0-14 12.2-21.7 26.9-21.7 9 0 17.1 2.3 23.5 6.5v13.9c-6.6-5.1-13.9-8.6-23.2-8.6-8.1 0-14 3.1-14 9.6 0 5.8 3.8 8.2 10.4 10.5l12.9 4.7c12.5 4.5 18.2 11.6 18.2 23.1 0 14.5-12.3 22.6-28.6 22.6-10.6 0-19.7-3.1-25.3-7z"/>
<path id="path3689" stroke="#fff" stroke-width="3" fill="none" d="M280.5 56.7c-4.3 0-8.1-3.5-8.1-7.9s3.8-7.9 8.1-7.9 8.1 3.5 8.1 7.9-3.8 7.9-8.1 7.9zm6.5 67.2h-13V66.2h13z"/>
<path id="path3691" stroke="#fff" stroke-width="3" fill="none" d="M339.1 118.2c-2.6 3.1-8.1 6-14.5 6-17 0-26.6-14.2-26.6-29.6 0-15.4 9.6-29.6 26.6-29.6 6.5 0 11.9 2.9 14.5 6v-4.7h13v52.9c0 21-16 28.2-29.6 28.2-7.7 0-14.5-1.9-19.2-4.9v-13.8c6 5.3 11.9 7.3 19.2 7.3 9.2 0 16.6-5.5 16.6-15.8zm0-35c-2.2-3.9-6.9-6.9-12.3-6.9-10 0-15.7 7.7-15.7 18.2s5.7 18.2 15.7 18.2c5.5 0 10.1-3 12.3-6.9z"/>
<path id="path3693" stroke="#fff" stroke-width="3" fill="none" d="M367 66.2h13v5.5c3.1-3.6 8.8-6.8 15.6-6.8 13.1 0 20.4 8.7 20.4 21.4v37.5h-13V88.6c0-7.1-3.5-11.8-10.9-11.8-5.6 0-10.6 3.5-12.1 9.2v37.9h-13z"/>
<path id="path3695" stroke="#fff" stroke-width="3" fill="none" d="M445 94.1v29.7h-13.5V44.1h30.8c16.5 0 27.3 8.6 27.3 25.1 0 16.2-10.8 24.9-27.3 24.9zm17.1-38.3h-17v26.6h17c9.4 0 14.2-5.6 14.2-13.2-.1-7.9-4.9-13.4-14.2-13.4z"/>
<path id="path3697" stroke="#fff" stroke-width="3" fill="none" d="M530.1 87c0-6.5-5.2-10.3-13.2-10.3-6.2 0-11.3 1.9-16 5.1V69.9c3.8-2.7 11-4.9 18.3-4.9 14.9 0 23.4 8.1 23.4 21.2V124h-12.5v-3.2c-1.9 1.9-7.7 4.3-14.2 4.3-11.8 0-21.6-7-21.6-18.8 0-10.9 9.7-18.6 22.5-18.6 5.2 0 10.9 1.8 13.2 3.5zm0 16.8c-1.4-3.6-6.5-5.8-11.7-5.8-5.8 0-11.9 2.5-11.9 8.2 0 5.8 6.1 8.3 11.9 8.3 5.2 0 10.3-2.2 11.7-5.8z"/>
<path id="path3699" stroke="#fff" stroke-width="3" fill="none" d="M575.8 123.9h-13V77h-11.7V66.2h11.7V50.8h13v15.5h13V77h-13z"/>
<path id="path3701" stroke="#fff" stroke-width="3" fill="none" d="M598.3 39.5h13v32.2c3.1-3.6 8.8-6.8 15.6-6.8 13.1 0 20.4 8.7 20.4 21.4v37.5h-13V88.6c0-7.1-3.5-11.8-10.9-11.8-5.6 0-10.7 3.5-12.1 9.2v37.9h-13z"/>
</g>
</g>
</g>
</svg>
<span id='slogan'></span>
</div>
19 changes: 19 additions & 0 deletions src/Pages/Index.cshtml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace DemoExample.Pages;

public class IndexModel : PageModel
{
private readonly ILogger<IndexModel> _logger;

public IndexModel(ILogger<IndexModel> logger)
{
_logger = logger;
}

public void OnGet()
{
_logger.LogInformation("Home page was called");
}
}
17 changes: 17 additions & 0 deletions src/Pages/Shared/_Layout.cshtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>SignPath Demo Example App</title>
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
<script src="~/js/main.js"></script>
</head>
<body>
<div>
<main role="main">
@RenderBody()
</main>
</div>
</body>
</html>
3 changes: 3 additions & 0 deletions src/Pages/_ViewImports.cshtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@using DemoExample
@namespace DemoExample.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
3 changes: 3 additions & 0 deletions src/Pages/_ViewStart.cshtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@{
Layout = "_Layout";
}
28 changes: 28 additions & 0 deletions src/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using Serilog;

var builder = WebApplication.CreateBuilder(args);

builder.Host.UseSerilog((context, configuration) => configuration.ReadFrom.Configuration(context.Configuration));

// Add services to the container.
builder.Services.AddRazorPages();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}

app.UseSerilogRequestLogging();

app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapRazorPages();

app.Run();
34 changes: 34 additions & 0 deletions src/appsettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"Serilog": {
"Using": [ "Serilog.Sinks.File", "Serilog.Sinks.Console" ],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"System": "Warning"
}
},
"WriteTo": [
{
"Name": "Console"
},
{
"Name": "File",
"Args": {
"path": "/logs/log-.txt",
"rollOnFileSizeLimit": true,
"formatter": "Serilog.Formatting.Compact.CompactJsonFormatter,Serilog.Formatting.Compact",
"rollingInterval": "Day"
}
}
],
"Enrich": [ "FromLogContext", "WithThreadId", "WithMachineName" ]
}
}
13 changes: 13 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import Vivus from 'vivus';
import Typed from 'typed.js';

document.addEventListener('DOMContentLoaded', function() {
new Vivus('logo', {duration: 100} );

new Typed('#slogan', {
strings: ['Built. Signed. Delivered.'],
typeSpeed: 50,
showCursor: false,
autoInsertCss: false
});
});
Loading

0 comments on commit e872445

Please sign in to comment.