|
12 | 12 | description: 'Comma-separated list of dependency types to check' |
13 | 13 | required: false |
14 | 14 | type: string |
15 | | - default: 'actions,containers' |
| 15 | + default: 'github-actions' |
16 | 16 | soft-fail: |
17 | 17 | description: 'Whether to continue on compliance violations' |
18 | 18 | required: false |
@@ -71,45 +71,74 @@ jobs: |
71 | 71 | run: | |
72 | 72 | Write-Host "Validating dependency SHA pinning compliance..." |
73 | 73 | |
74 | | - # Build parameter list |
| 74 | + # Ensure logs directory exists |
| 75 | + New-Item -ItemType Directory -Force -Path logs | Out-Null |
| 76 | + |
| 77 | + # Build parameter list for JSON output (always generate) |
75 | 78 | $params = @{ |
76 | 79 | Path = '.' |
| 80 | + Recursive = $true |
77 | 81 | Format = 'json' |
78 | 82 | OutputPath = 'logs/dependency-pinning-results.json' |
79 | 83 | } |
80 | 84 | |
| 85 | + # Enable failure on threshold violations unless soft-fail is requested |
| 86 | + if ('${{ inputs.soft-fail }}' -ne 'true') { |
| 87 | + $params['FailOnUnpinned'] = $true |
| 88 | + } |
| 89 | + |
| 90 | + # Pass dependency types filter to script |
81 | 91 | if ('${{ inputs.dependency-types }}') { |
82 | | - $params['DependencyTypes'] = '${{ inputs.dependency-types }}' |
| 92 | + $params['IncludeTypes'] = '${{ inputs.dependency-types }}' |
83 | 93 | } |
84 | 94 | |
| 95 | + # Pass compliance threshold to script (script handles enforcement) |
85 | 96 | if ('${{ inputs.threshold }}') { |
86 | 97 | $params['Threshold'] = [int]'${{ inputs.threshold }}' |
87 | 98 | } |
88 | 99 | |
89 | | - # Run validation script |
| 100 | + # Run validation script (JSON format) |
90 | 101 | & scripts/security/Test-DependencyPinning.ps1 @params |
| 102 | + $jsonExitCode = $LASTEXITCODE |
| 103 | + |
| 104 | + # Generate SARIF format if requested |
| 105 | + if ('${{ inputs.upload-sarif }}' -eq 'true') { |
| 106 | + Write-Host "Generating SARIF format for Security tab..." |
| 107 | + $params['Format'] = 'sarif' |
| 108 | + $params['OutputPath'] = 'logs/dependency-pinning-results.sarif' |
| 109 | + |
| 110 | + & scripts/security/Test-DependencyPinning.ps1 @params |
| 111 | + } |
91 | 112 | |
92 | | - # Extract metrics from report |
93 | | - $report = Get-Content logs/dependency-pinning-results.json | ConvertFrom-Json |
94 | | - $complianceScore = $report.ComplianceScore |
95 | | - $unpinnedCount = $report.UnpinnedDependencies |
96 | | - $threshold = [int]'${{ inputs.threshold }}' |
97 | | - $isCompliant = $complianceScore -ge $threshold |
98 | | - |
99 | | - "compliance-score=$complianceScore" >> $env:GITHUB_OUTPUT |
100 | | - "unpinned-count=$unpinnedCount" >> $env:GITHUB_OUTPUT |
101 | | - "is-compliant=$($isCompliant.ToString().ToLower())" >> $env:GITHUB_OUTPUT |
102 | | - |
103 | | - Write-Host "Compliance Score: $complianceScore%" |
104 | | - Write-Host "Unpinned Dependencies: $unpinnedCount" |
105 | | - Write-Host "Is Compliant (>=$threshold%): $isCompliant" |
106 | | - |
107 | | - # Fire GitHub Actions warnings for each violation |
108 | | - if ($unpinnedCount -gt 0) { |
109 | | - foreach ($violation in $report.Violations) { |
110 | | - Write-Output "::warning file=$($violation.File),line=$($violation.Line)::Unpinned $($violation.Type) dependency: $($violation.Name)@$($violation.Version) (Severity: $($violation.Severity))" |
| 113 | + # Extract metrics from JSON report |
| 114 | + if (Test-Path logs/dependency-pinning-results.json) { |
| 115 | + $report = Get-Content logs/dependency-pinning-results.json | ConvertFrom-Json |
| 116 | + $complianceScore = $report.ComplianceScore |
| 117 | + $unpinnedCount = $report.UnpinnedDependencies |
| 118 | + |
| 119 | + # Extract threshold from report metadata (script calculated compliance) |
| 120 | + $threshold = $report.Metadata.ComplianceThreshold |
| 121 | + $isCompliant = $complianceScore -ge $threshold |
| 122 | + |
| 123 | + "compliance-score=$complianceScore" >> $env:GITHUB_OUTPUT |
| 124 | + "unpinned-count=$unpinnedCount" >> $env:GITHUB_OUTPUT |
| 125 | + "is-compliant=$($isCompliant.ToString().ToLower())" >> $env:GITHUB_OUTPUT |
| 126 | + |
| 127 | + Write-Host "Compliance Score: $complianceScore%" |
| 128 | + Write-Host "Unpinned Dependencies: $unpinnedCount" |
| 129 | + Write-Host "Is Compliant (>=$threshold%): $isCompliant" |
| 130 | + |
| 131 | + # Fire GitHub Actions warnings for each violation |
| 132 | + if ($unpinnedCount -gt 0) { |
| 133 | + foreach ($violation in $report.Violations) { |
| 134 | + Write-Output "::warning file=$($violation.File),line=$($violation.Line)::Unpinned $($violation.Type) dependency: $($violation.Name)@$($violation.Version) (Severity: $($violation.Severity))" |
| 135 | + } |
111 | 136 | } |
112 | 137 | } |
| 138 | + else { |
| 139 | + Write-Error "Failed to generate dependency pinning report" |
| 140 | + exit 1 |
| 141 | + } |
113 | 142 |
|
114 | 143 | - name: Upload SARIF to Security tab |
115 | 144 | if: inputs.upload-sarif && always() |
@@ -164,9 +193,3 @@ jobs: |
164 | 193 | "@ |
165 | 194 | }) |
166 | 195 | "@ | Out-File -FilePath $env:GITHUB_STEP_SUMMARY -Encoding UTF8 |
167 | | -
|
168 | | - - name: Fail job if non-compliant |
169 | | - if: steps.pinning.outputs.is-compliant == 'false' && !inputs.soft-fail |
170 | | - run: | |
171 | | - echo "Dependency pinning scan failed - compliance threshold not met" |
172 | | - exit 1 |
|
0 commit comments