@stream44.studio/dco 0.3.0-rc.3 → 0.3.0-rc.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -3
- package/test.sh +25 -2
- package/validate.sh +41 -16
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stream44.studio/dco",
|
|
3
|
-
"version": "0.3.0-rc.
|
|
3
|
+
"version": "0.3.0-rc.4",
|
|
4
4
|
"description": "Developer Certificate of Origin (DCO) tools for signing & verifying.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"keywords": [
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
"validate": "./validate.sh"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@stream44.studio/encapsulate": "^0.4.0-rc.
|
|
32
|
-
"t44": "^0.4.0-rc.
|
|
31
|
+
"@stream44.studio/encapsulate": "^0.4.0-rc.4",
|
|
32
|
+
"t44": "^0.4.0-rc.4"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@types/bun": "^1.3.4",
|
package/test.sh
CHANGED
|
@@ -389,8 +389,31 @@ fi
|
|
|
389
389
|
echo -e "${GREEN}✓ --enforce-signature-fingerprints correctly fails on unsigned commits${NC}"
|
|
390
390
|
echo
|
|
391
391
|
|
|
392
|
-
# Test validate.sh --enforce-signature-fingerprints on the signed repo
|
|
393
|
-
|
|
392
|
+
# Test validate.sh --enforce-signature-fingerprints on the signed repo WITHOUT allowedSignersFile
|
|
393
|
+
# This simulates the GitHub Actions environment where gpg.ssh.allowedSignersFile is not configured.
|
|
394
|
+
# The fix extracts SSH fingerprints directly from raw commit objects instead of relying on %G?/%GK.
|
|
395
|
+
echo -e "${BOLD}${YELLOW}Testing --enforce-signature-fingerprints WITHOUT allowedSignersFile (GitHub Actions scenario)...${NC}"
|
|
396
|
+
cd "$SIGNED_REPO"
|
|
397
|
+
|
|
398
|
+
# Ensure allowedSignersFile is NOT set (simulates GitHub Actions)
|
|
399
|
+
git config --unset gpg.ssh.allowedSignersFile 2>/dev/null || true
|
|
400
|
+
|
|
401
|
+
VALIDATE_OUTPUT=$(./validate.sh "" HEAD --enforce-signature-fingerprints 2>&1) || {
|
|
402
|
+
echo -e "${RED}✗ FAIL: --enforce-signature-fingerprints should pass without allowedSignersFile${NC}"
|
|
403
|
+
echo "$VALIDATE_OUTPUT"
|
|
404
|
+
exit 1
|
|
405
|
+
}
|
|
406
|
+
echo "$VALIDATE_OUTPUT"
|
|
407
|
+
|
|
408
|
+
if ! echo "$VALIDATE_OUTPUT" | grep -q "Signature fingerprints: enforced"; then
|
|
409
|
+
echo -e "${RED}✗ FAIL: Output should contain 'Signature fingerprints: enforced'${NC}"
|
|
410
|
+
exit 1
|
|
411
|
+
fi
|
|
412
|
+
echo -e "${GREEN}✓ --enforce-signature-fingerprints passes WITHOUT allowedSignersFile (raw commit extraction)${NC}"
|
|
413
|
+
echo
|
|
414
|
+
|
|
415
|
+
# Test validate.sh --enforce-signature-fingerprints on the signed repo WITH allowedSignersFile
|
|
416
|
+
echo -e "${BOLD}${YELLOW}Testing --enforce-signature-fingerprints on signed repo (with allowedSignersFile)...${NC}"
|
|
394
417
|
cd "$SIGNED_REPO"
|
|
395
418
|
|
|
396
419
|
# Set up allowed signers for git to verify SSH signatures
|
package/validate.sh
CHANGED
|
@@ -241,6 +241,38 @@ if [[ "$ENFORCE_SIGNATURE_FINGERPRINTS" == "1" ]]; then
|
|
|
241
241
|
SIG_VALIDATION_FAILED=true
|
|
242
242
|
fi
|
|
243
243
|
|
|
244
|
+
# Extract the SSH signing fingerprint directly from the raw commit object.
|
|
245
|
+
# This avoids depending on gpg.ssh.allowedSignersFile which is typically
|
|
246
|
+
# not configured on GitHub Actions runners, causing %G? to report 'N'
|
|
247
|
+
# even when the commit contains a valid SSH signature.
|
|
248
|
+
extract_ssh_fingerprint() {
|
|
249
|
+
local commit_hash="$1"
|
|
250
|
+
local raw_commit
|
|
251
|
+
raw_commit=$(git cat-file commit "$commit_hash" 2>/dev/null)
|
|
252
|
+
|
|
253
|
+
# Check if the commit contains an SSH signature
|
|
254
|
+
if ! echo "$raw_commit" | grep -q "BEGIN SSH SIGNATURE"; then
|
|
255
|
+
echo ""
|
|
256
|
+
return
|
|
257
|
+
fi
|
|
258
|
+
|
|
259
|
+
# Extract the signature block, decode it, and compute the public key fingerprint
|
|
260
|
+
local sig_pem
|
|
261
|
+
sig_pem=$(echo "$raw_commit" | sed -n '/-----BEGIN SSH SIGNATURE-----/,/-----END SSH SIGNATURE-----/p' | sed 's/^gpgsig //' | sed 's/^ //')
|
|
262
|
+
|
|
263
|
+
python3 -c "
|
|
264
|
+
import base64, hashlib, struct, sys
|
|
265
|
+
lines = [l for l in sys.stdin.read().strip().split('\n') if not l.startswith('-----')]
|
|
266
|
+
raw = base64.b64decode(''.join(lines))
|
|
267
|
+
# SSHSIG format: magic 'SSHSIG' (6) + version uint32 (4) + public key string
|
|
268
|
+
idx = 10
|
|
269
|
+
pk_len = struct.unpack('>I', raw[idx:idx+4])[0]
|
|
270
|
+
pk_blob = raw[idx+4:idx+4+pk_len]
|
|
271
|
+
fp = base64.b64encode(hashlib.sha256(pk_blob).digest()).decode().rstrip('=')
|
|
272
|
+
print(f'SHA256:{fp}')
|
|
273
|
+
" <<< "$sig_pem"
|
|
274
|
+
}
|
|
275
|
+
|
|
244
276
|
# Verify each commit has a valid SSH signature matching the expected fingerprint
|
|
245
277
|
if [[ "$SIG_VALIDATION_FAILED" == "false" ]]; then
|
|
246
278
|
while IFS= read -r commit; do
|
|
@@ -248,13 +280,12 @@ if [[ "$ENFORCE_SIGNATURE_FINGERPRINTS" == "1" ]]; then
|
|
|
248
280
|
commit_email=$(git log -1 --format='%ae' "$commit")
|
|
249
281
|
commit_subject=$(git log -1 --format='%s' "$commit")
|
|
250
282
|
|
|
251
|
-
#
|
|
252
|
-
|
|
253
|
-
sig_status=$(git log -1 --format='%G?' "$commit" 2>/dev/null || true)
|
|
283
|
+
# Extract the SSH signature fingerprint directly from the raw commit
|
|
284
|
+
sig_fingerprint=$(extract_ssh_fingerprint "$commit")
|
|
254
285
|
|
|
255
|
-
verbose_log "Commit $commit_short:
|
|
286
|
+
verbose_log "Commit $commit_short: sig_fingerprint=$sig_fingerprint email=$commit_email"
|
|
256
287
|
|
|
257
|
-
if [[ -z "$
|
|
288
|
+
if [[ -z "$sig_fingerprint" ]]; then
|
|
258
289
|
echo -e "${RED}✗ FAIL${NC} $commit_short - ${YELLOW}$commit_subject${NC}"
|
|
259
290
|
echo -e " ${RED}Missing SSH signature on commit${NC}"
|
|
260
291
|
SIG_VALIDATION_FAILED=true
|
|
@@ -265,26 +296,20 @@ if [[ "$ENFORCE_SIGNATURE_FINGERPRINTS" == "1" ]]; then
|
|
|
265
296
|
expected_fp="${EXPECTED_FINGERPRINTS[$commit_email]:-}"
|
|
266
297
|
if [[ -n "$expected_fp" ]]; then
|
|
267
298
|
# Compare the fingerprint from the commit signature with the expected one
|
|
268
|
-
if [[ "$
|
|
299
|
+
if [[ "$sig_fingerprint" == "$expected_fp" ]]; then
|
|
269
300
|
echo -e "${GREEN}✓ PASS${NC} $commit_short - $commit_subject"
|
|
270
|
-
echo -e " SSH signature: ${CYAN}$
|
|
301
|
+
echo -e " SSH signature: ${CYAN}$sig_fingerprint${NC}"
|
|
271
302
|
else
|
|
272
303
|
echo -e "${RED}✗ FAIL${NC} $commit_short - ${YELLOW}$commit_subject${NC}"
|
|
273
304
|
echo -e " Expected fingerprint: ${CYAN}$expected_fp${NC}"
|
|
274
|
-
echo -e " Actual fingerprint: ${CYAN}$
|
|
305
|
+
echo -e " Actual fingerprint: ${CYAN}$sig_fingerprint${NC}"
|
|
275
306
|
echo -e " ${RED}SSH signature fingerprint mismatch${NC}"
|
|
276
307
|
SIG_VALIDATION_FAILED=true
|
|
277
308
|
fi
|
|
278
309
|
else
|
|
279
310
|
# No expected fingerprint for this email — just verify it has a signature
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
echo -e " SSH signature: ${CYAN}$sig_output${NC} (no fingerprint in .dco-signatures to cross-check)"
|
|
283
|
-
else
|
|
284
|
-
echo -e "${RED}✗ FAIL${NC} $commit_short - ${YELLOW}$commit_subject${NC}"
|
|
285
|
-
echo -e " ${RED}Invalid SSH signature (status: $sig_status)${NC}"
|
|
286
|
-
SIG_VALIDATION_FAILED=true
|
|
287
|
-
fi
|
|
311
|
+
echo -e "${GREEN}✓ PASS${NC} $commit_short - $commit_subject"
|
|
312
|
+
echo -e " SSH signature: ${CYAN}$sig_fingerprint${NC} (no fingerprint in .dco-signatures to cross-check)"
|
|
288
313
|
fi
|
|
289
314
|
done <<< "$COMMITS"
|
|
290
315
|
fi
|