microsoft/hve-core

Public

mirrored from https://github.com/microsoft/hve-coreAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
10592b26aa7353560efbeca809ec1230c8ad230a

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

scripts/security/Sign-RaiArtifacts.ps1

198lines · modecode

1#!/usr/bin/env pwsh
2# Copyright (c) Microsoft Corporation.
3# SPDX-License-Identifier: MIT
4
5#Requires -Version 7.0
6
7<#
8.SYNOPSIS
9 Generates a SHA-256 manifest for RAI planning artifacts and optionally signs it with cosign.
10
11.DESCRIPTION
12 Enumerates all files under the RAI planning artifact directory for a given project slug,
13 computes SHA-256 hashes for each artifact, and writes a JSON manifest file. When cosign
14 is available and requested, the manifest is signed using Sigstore keyless signing to
15 provide cryptographic provenance.
16
17.PARAMETER ProjectSlug
18 The project slug identifying the RAI planning session. Corresponds to the subdirectory
19 under .copilot-tracking/rai-plans/.
20
21.PARAMETER OutputPath
22 Path for the generated manifest file. Defaults to
23 .copilot-tracking/rai-plans/{ProjectSlug}/artifact-manifest.json.
24
25.PARAMETER IncludeCosign
26 When specified, attempts to sign the manifest with cosign keyless signing after
27 generation. Requires cosign to be available in PATH. Gracefully skips signing with
28 a warning when cosign is not found.
29
30.EXAMPLE
31 ./scripts/security/Sign-RaiArtifacts.ps1 -ProjectSlug "contoso-ai"
32
33 Generates a SHA-256 manifest for all artifacts under
34 .copilot-tracking/rai-plans/contoso-ai/.
35
36.EXAMPLE
37 ./scripts/security/Sign-RaiArtifacts.ps1 -ProjectSlug "contoso-ai" -IncludeCosign
38
39 Generates the manifest and signs it with cosign keyless signing.
40
41.EXAMPLE
42 npm run rai:sign -- -ProjectSlug "contoso-ai" -IncludeCosign
43
44 Invokes the script through the npm wrapper with cosign signing enabled.
45
46.NOTES
47 The manifest excludes its own file (artifact-manifest.json) and any cosign signature
48 files (.sig, .bundle) from the hash inventory to avoid circular references.
49#>
50
51[CmdletBinding()]
52param(
53 [Parameter(Mandatory)]
54 [ValidateNotNullOrEmpty()]
55 [string]$ProjectSlug,
56
57 [Parameter(Mandatory = $false)]
58 [string]$OutputPath,
59
60 [Parameter(Mandatory = $false)] [string]$OutputPath,
61
62 [Parameter(Mandatory = $false)]
63 [switch]$IncludeCosign
64)
65
66$ErrorActionPreference = 'Stop'
67
68#region Helper Functions
69
70function Get-ArtifactHash {
71 <#
72 .OUTPUTS
73 [string] Lowercase hex SHA-256 digest.
74 #>
75 [CmdletBinding()]
76 [OutputType([string]e SHA-256 hash of a file and returns a lowercase hex string.
77 .OUTPUTS
78 [string] Lowercase hex SHA-256 digest.
79 #>
80 [CmdletBinding()]
81 [OutputType([string])]
82 param(
83 [Parameter(Mandatory)]
84 [string]$FilePath
85 )
86
87 (Get-FileHash -Path $FilePath -Algorithm SHA256).Hash.ToLower()
88}
89
90 #region Artifact Generation
91
92 #endregion
93
94#region Main Execution
95if ($MyInvocation.InvocationName -ne '.') {
96
97 #region Artifact Generation
98
99 $artifactDir = Join-Path -Path $PWD -ChildPath ".copilot-tracking/rai-plans/$ProjectSlug"
100
101if (-not (Test-Path -Path $artifactDir -PathType Container)) {
102 Write-Host "❌ Artifact directory not found: $artifactDir" -ForegroundColor Red
103 exit 1
104}
105
106if (-not $OutputPath) {
107 $OutputPath = Join-Path -Path $artifactDir -ChildPath 'artifact-manifest.json'
108}
109
110# File patterns to exclude from the manifest to avoid circular references
111$excludePatterns = @(
112 'artifact-manifest.json',
113 '*.sig',
114 '*.bundle'
115)
116
117Write-Host "🔐 Generating artifact manifest for project: $ProjectSlug" -ForegroundColor Cyan
118
119$artifacts = Get-ChildItem -Path $artifactDir -File -Recurse |
120 Where-Object {
121 $fileName = $_.Name
122 -not ($excludePatterns | Where-Object { $fileName -like $_ })
123 } |
124 Sort-Object FullName
125
126if ($artifacts.Count -eq 0) {
127 Write-Host "⚠️ No artifacts found in: $artifactDir" -ForegroundColor Yellow
128 exit 0
129}
130
131Write-Host "📁 Found $($artifacts.Count) artifact(s) to hash" -ForegroundColor Cyan
132
133$fileEntries = [System.Collections.Generic.List[object]]::new()
134
135foreach ($file in $artifacts) {
136 $relativePath = $file.FullName.Substring($artifactDir.Length + 1) -replace '\\', '/'
137 $hash = Get-ArtifactHash -FilePath $file.FullName
138 $fileEntries.Add(@{
139 path = $relativePath
140 sha256 = $hash
141 sizeBytes = $file.Length
142 })
143 Write-Host " ✅ $relativePath" -ForegroundColor Green
144}
145
146$manifest = [ordered]@{
147 version = '1.0'
148 projectSlug = $ProjectSlug
149 generatedAt = (Get-Date -Format 'o')
150 algorithm = 'SHA256'
151 Write-Host "📋 Manifest written to: $OutputPath" -ForegroundColor Green
152 Write-Host " Files hashed: $($fileEntries.Count)" -ForegroundColor Cyan
153
154 #endregion Artifact Generation
155
156 Set-Content -Path $OutputPath -Value $manifestJson -Encoding utf8NoBOM
157
158 Write-Host "📋 Manifest written to: $OutputPath" -ForegroundColor Green
159 Write-Host " Files hashed: $($fileEntries.Count)" -ForegroundColor Cyan
160
161 #endregion Artifact Generation
162
163 #region Cosign Signing
164
165if ($IncludeCosign) {
166 $cosignCmd = Get-Command -Name 'cosign' -ErrorAction SilentlyContinue
167
168 if (-not $cosignCmd) {
169 Write-Host "⚠️ cosign not found in PATH. Skipping signature." -ForegroundColor Yellow
170 Write-Host " Install cosign from https://docs.sigstore.dev/cosign/system_config/installation/" -ForegroundColor Yellow
171 exit 0
172 }
173
174 Write-Host "🔏 Signing manifest with cosign keyless signing..." -ForegroundColor Cyan
175
176 try {
177 & cosign sign-blob `
178 --yes `
179 --output-signature "$OutputPath.sig" `
180 --bundle "$OutputPath.bundle" `
181 $OutputPath
182
183 Write-Host "✅ Manifest signed successfully" -ForegroundColor Green
184 Write-Host " Signature: $OutputPath.sig" -ForegroundColor Cyan
185 Write-Host " Bundle: $OutputPath.bundle" -ForegroundColor Cyan
186 #endregion Cosign Signing
187
188 Write-Host "❌ Cosign signing failed: $_" -ForegroundColor Red
189 exit 2
190 }
191}
192
193 #endregion Cosign Signing
194
195 Write-Host "🎉 Artifact signing complete" -ForegroundColor Green
196
197}
198#endregion Main Execution
199