From f9a27e3fa6e540c97a024bceaa559029cf15a8a9 Mon Sep 17 00:00:00 2001 From: Ken Gordon Date: Thu, 11 Apr 2024 17:35:14 +0100 Subject: [PATCH 1/5] Clean up and match actual fragments. Don't base64 encode the rego policy. Signed-off-by: Ken Gordon --- cmd/sign1util/main.go | 3 ++- pkg/cosesign1/Makefile | 60 ++++++++++++++++++++++++++++++------------ 2 files changed, 45 insertions(+), 18 deletions(-) diff --git a/cmd/sign1util/main.go b/cmd/sign1util/main.go index d63792b..efbf5a4 100644 --- a/cmd/sign1util/main.go +++ b/cmd/sign1util/main.go @@ -49,7 +49,8 @@ func checkCoseSign1(inputFilename string, chainFilename string, didString string if err == nil { fmt.Fprintf(os.Stdout, "DID resolvers passed:\n%s\n", didDoc) } else { - fmt.Fprintf(os.Stdout, "DID resolvers failed: err: %s doc:\n%s\n", err.Error(), didDoc) + // all the error paths return an empty string, so we can just print the error + fmt.Fprintf(os.Stdout, "DID resolvers failed: err: %s\n", err.Error()) } } return unpacked, err diff --git a/pkg/cosesign1/Makefile b/pkg/cosesign1/Makefile index de2f703..0a63da7 100755 --- a/pkg/cosesign1/Makefile +++ b/pkg/cosesign1/Makefile @@ -23,11 +23,16 @@ # will print the new fingerprint of the intermediate cert as part of the did:x509 generated # + +# note test-fail is expected to fail + +all: chain.pem cose test-fail test-pass + cose: infra.rego.cose # from these media types have to match containerd. The also need to change and the security policy one ought to be x-ms-ccepolicy-frag # fragment atrifact type = application/x-ms-ccepolicy-frag -# fragment media type = application/cose_x509+rego +# fragment media type = application/cose-x509+rego # Use a local linux build of the tool for the purposes of this Makefile - ie assume using in wsl. # Usually sign1util.exe is a windows exe in /mnt/c/ContainerPlat aka c:\ContainerPlat but that is not certain. @@ -35,9 +40,14 @@ cose: infra.rego.cose sign1util: ../../cmd/sign1util/main.go *.go go build ../../cmd/sign1util -infra.rego.cose: infra.rego.base64 chain.pem leaf.private.pem sign1util - ./sign1util create -algo ES384 -chain chain.pem -claims infra.rego.base64 -key leaf.private.pem -out $@ -issuer TestIssuer -feed TestFeed -salt zero - ./sign1util check -in $@ +#infra.rego.cose: infra.rego chain.pem leaf.private.pem sign1util +# ./sign1util create -algo ES384 -chain chain.pem -claims infra.rego -key leaf.private.pem -out $@ -issuer TestIssuer -feed TestFeed -salt zero +# ./sign1util check -in $@ + +%.rego.cose: %.rego chain.pem leaf.private.pem sign1util + ./sign1util create -algo ES384 -chain chain.pem -claims $< -key leaf.private.pem -out $@ -salt zero \ + -feed acceuroperegistry.azurecr.io/infra:latest -content-type application/unknown+rego \ + -issuer TestIssuer -feed TestFeed print: infra.rego.cose sign1util ./sign1util chain -in $< > tmp.chain.pem @@ -51,9 +61,16 @@ show: sign1util didx509: chain.pem sign1util ./sign1util did-x509 -chain chain.pem -i 1 -policy "subject:CN:Test Leaf (DO NOT TRUST)" -verbose +ISSUER_DID = $(shell ./sign1util did-x509 -chain chain.pem -policy cn) +DID_FINGERPRINT = $(shell ./sign1util did-x509 -chain chain.pem -policy cn | cut -d: -f5) + +info: chain.pem sign1util + @echo "ISSUER_DID: $(ISSUER_DID)" + @echo "DID_FINGERPRINT: $(DID_FINGERPRINT)" + # for this to pass the did:x509 fingerprint (RgpNsHOK5hPlCAfTtiGY_BcDhFRxQbJnhlxNDhxps6U here) needs to be the one output from make print -did-check: chain.pem infra.rego.cose sign1util - ./sign1util check -in infra.rego.cose -did did:x509:0:sha256:RgpNsHOK5hPlCAfTtiGY_BcDhFRxQbJnhlxNDhxps6U::subject:CN:Test%20Leaf%20%28DO%20NOT%20TRUST%29 +did-check: chain.pem infra.rego.cose sign1util info + ./sign1util check -in infra.rego.cose -did $(ISSUER_DID) # For normal workflow start from the chain.pem, here we'd take the chain from inside the cose sign1 doc, eg to manually confirm it is # as otherwise expected (ie that the issuer DID matches the chain) or to shortcut getting a DID from a cose document. @@ -61,13 +78,27 @@ did-check: chain.pem infra.rego.cose sign1util did-from-cose: sign1util infra.rego.cose ./sign1util did-x509 -in infra.rego.cose -policy cn -did-fail-fingerprint: chain.pem sign1util - ./sign1util check -chain chain.pem -in infra.rego.cose -did did:x509:0:sha256:XXXi_nuWegx4NiLaeGabiz36bDUhDDiHEFl8HXMA_4o::subject:CN:Test+Leaf+%28DO+NOT+TRUST%29 +# these test changing the fingerprint/sublect to prove failure when the DID is checked against the chain +# note that since the infra.rego.cose is actually good the first part of the check will report a pass "checkCoseSign1 passed" -did-fail-subject: chain.pem sign1util - ./sign1util check -chain chain.pem -in infra.rego.cose -did did:x509:0:sha256:RgpNsHOK5hPlCAfTtiGY_BcDhFRxQbJnhlxNDhxps6U::subject:CN:Test+XXXX+%28DO+NOT+TRUST%29 +# expect "DID resolvers failed: err: DID verification failed: unexpected certificate fingerprint" +did-fail-fingerprint: chain.pem sign1util infra.rego.cose + ./sign1util check -in infra.rego.cose -did did:x509:0:sha256:XXXi_nuWegx4NiLaeGabiz36bDUhDDiHEFl8HXMA_4o::subject:CN:Test+Leaf+%28DO+NOT+TRUST%29 -did-fail: did-fail-subject did-fail-fingerprint +# expect "DID resolvers failed: err: DID verification failed: invalid subject value: CN=Test XXXX (DO NOT TRUST)" +did-fail-subject: chain.pem sign1util infra.rego.cose + ./sign1util check -in infra.rego.cose -did did:x509:0:sha256:$(DID_FINGERPRINT)::subject:CN:Test+XXXX+%28DO+NOT+TRUST%29 + +did-fail: did-fail-subject did-fail-fingerprint + +# can be confusing +test: test-pass test-fail + +# positive tests +test-pass: print show didx509 did-check did-from-cose + +# negative tests +test-fail: did-fail # beyond the scope of this repo @@ -80,17 +111,12 @@ did-fail: did-fail-subject did-fail-fingerprint # --artifact-type application/x-ms-ccepolicy-frag \ # --manifest-config /dev/null:application/vnd.unknown.config.v1+json \ # --subject ${INFRA_IMAGE} \ -# ./infra.rego.cose:application/cose_x509+rego +# ./infra.rego.cose:application/cose-x509+rego %.pem: $(MAKE) -f Makefile.certs chain.pem -infra.rego.base64: infra.rego - base64 infra.rego > infra.rego.base64 - -test-all: print show didx509 did-check did-from-cose did-fail - clean: $(MAKE) -f Makefile.certs $@ rm -f infra.rego.base64 infra.rego.cose sign1util From 2ed357c3758bc2a741b94a4a83626b853e2c0c29 Mon Sep 17 00:00:00 2001 From: Ken Gordon Date: Fri, 12 Apr 2024 16:39:27 +0100 Subject: [PATCH 2/5] If there exists a file xyzzy.rego, make xyzzy.rego.cose will work. FEED= and ISSUER_DID overrides will work. Note though that the signing is by the (generated) private key and so setting the ISSUER_DID override will result in a badly formed fragment, as in the fragment case the issuer DID MUST match the cert chain. Signed-off-by: Ken Gordon --- pkg/cosesign1/Makefile | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/pkg/cosesign1/Makefile b/pkg/cosesign1/Makefile index 0a63da7..d429cf7 100755 --- a/pkg/cosesign1/Makefile +++ b/pkg/cosesign1/Makefile @@ -30,6 +30,14 @@ all: chain.pem cose test-fail test-pass cose: infra.rego.cose +%.pem: + $(MAKE) -f Makefile.certs chain.pem + +ISSUER_DID = $(shell ./sign1util did-x509 -chain chain.pem -policy cn) +DID_FINGERPRINT = $(shell ./sign1util did-x509 -chain chain.pem -policy cn | cut -d: -f5) +FEED = acceuroperegistry.azurecr.io/infra + + # from these media types have to match containerd. The also need to change and the security policy one ought to be x-ms-ccepolicy-frag # fragment atrifact type = application/x-ms-ccepolicy-frag # fragment media type = application/cose-x509+rego @@ -46,8 +54,8 @@ sign1util: ../../cmd/sign1util/main.go *.go %.rego.cose: %.rego chain.pem leaf.private.pem sign1util ./sign1util create -algo ES384 -chain chain.pem -claims $< -key leaf.private.pem -out $@ -salt zero \ - -feed acceuroperegistry.azurecr.io/infra:latest -content-type application/unknown+rego \ - -issuer TestIssuer -feed TestFeed + -feed $(FEED) -content-type application/unknown+rego \ + -issuer $(ISSUER_DID) print: infra.rego.cose sign1util ./sign1util chain -in $< > tmp.chain.pem @@ -61,9 +69,6 @@ show: sign1util didx509: chain.pem sign1util ./sign1util did-x509 -chain chain.pem -i 1 -policy "subject:CN:Test Leaf (DO NOT TRUST)" -verbose -ISSUER_DID = $(shell ./sign1util did-x509 -chain chain.pem -policy cn) -DID_FINGERPRINT = $(shell ./sign1util did-x509 -chain chain.pem -policy cn | cut -d: -f5) - info: chain.pem sign1util @echo "ISSUER_DID: $(ISSUER_DID)" @echo "DID_FINGERPRINT: $(DID_FINGERPRINT)" @@ -113,8 +118,6 @@ test-fail: did-fail # --subject ${INFRA_IMAGE} \ # ./infra.rego.cose:application/cose-x509+rego -%.pem: - $(MAKE) -f Makefile.certs chain.pem clean: From e0703d6bd505475d30ee54e318183e0da7ee1197 Mon Sep 17 00:00:00 2001 From: Ken Gordon Date: Mon, 15 Apr 2024 11:34:58 +0100 Subject: [PATCH 3/5] Need a test-all target for the CI Signed-off-by: Ken Gordon --- pkg/cosesign1/Makefile | 2 ++ pkg/cosesign1/bob.rego | 17 +++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 pkg/cosesign1/bob.rego diff --git a/pkg/cosesign1/Makefile b/pkg/cosesign1/Makefile index d429cf7..a13c0e6 100755 --- a/pkg/cosesign1/Makefile +++ b/pkg/cosesign1/Makefile @@ -99,6 +99,8 @@ did-fail: did-fail-subject did-fail-fingerprint # can be confusing test: test-pass test-fail +test-all: test + # positive tests test-pass: print show didx509 did-check did-from-cose diff --git a/pkg/cosesign1/bob.rego b/pkg/cosesign1/bob.rego new file mode 100644 index 0000000..fbc8073 --- /dev/null +++ b/pkg/cosesign1/bob.rego @@ -0,0 +1,17 @@ +package infra + +svn := "1" +framework_version := "0.1.0" + +containers := [ + { + "command": ["python3","infra.py"], + "env_rules": [{"pattern": "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "strategy": "string", "required": false},{"pattern": "PYTHONUNBUFFERED=1", "strategy": "string", "required": false},{"pattern": "TERM=xterm", "strategy": "string", "required": false}], + "layers": ["37e9dcf799048b7d35ce53584e0984198e1bc3366c3bb5582fd97553d31beb4e","97112ba1d4a2c86c1c15a3e13f606e8fcc0fb1b49154743cadd1f065c42fee5a","1e66649e162d99c4d675d8d8c3af90ece3799b33d24671bc83fe9ea5143daf2f","3413e98a178646d4703ea70b9bff2d4410e606a22062046992cda8c8aedaa387","b99a9ced77c45fc4dc96bac8ea1e4d9bc1d2a66696cc057d3f3cca79dc999702","e7fbe653352d546497c534c629269c4c04f1997f6892bd66c273f0c9753a4de3","04c110e9406d2b57079f1eac4c9c5247747caa3bcaab6d83651de6e7da97cb40","92e50344671ca5a960887b64c545dbc6d5ca3be82d105c486aabbd381db67578","0a91a3c8a3e80e31a0692609a39e74469119ba071cb0c450a04c86a480345484"], + "mounts": [], + "exec_processes": [], + "signals": [], + "allow_elevated": true, + "working_dir": "/infra" + }, +] From 144c5e61b64eb0a46a3fc05e010a03f5d23c95ac Mon Sep 17 00:00:00 2001 From: KenGordon Date: Mon, 15 Apr 2024 13:15:43 +0100 Subject: [PATCH 4/5] Update ci.yml Change order so that the infra.rego.cose exists. --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 78d0c57..0526a79 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,10 +24,10 @@ jobs: - name: Build run: go build -v ./... - - name: Test - run: go test -v ./... - - name: Test Makafile commands run: | cd pkg/cosesign1 make test-all + + - name: Test + run: go test -v ./... From 422c552ff73da3ba5976e69f27be4e50d5592975 Mon Sep 17 00:00:00 2001 From: Maksim An Date: Fri, 5 Jul 2024 11:44:26 -0700 Subject: [PATCH 5/5] fix: Makefile and cosesign1 tests Remove references of `infra.rego.cose.base64` from Makefile and code. Add `AUTOPARSE_CHAIN` param to makefile, which will parse the pem certs automatically, otherwise test values will be set. Update tests expectations and parameters Signed-off-by: Maksim An --- pkg/cosesign1/Makefile | 11 ++++++++--- pkg/cosesign1/cosesign1util_test.go | 26 +++++++++++++++++--------- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/pkg/cosesign1/Makefile b/pkg/cosesign1/Makefile index a13c0e6..8c98213 100755 --- a/pkg/cosesign1/Makefile +++ b/pkg/cosesign1/Makefile @@ -26,6 +26,11 @@ # note test-fail is expected to fail +AUTOPARSE_CHAIN:=0 +ISSUER_DID:="TestIssuer" +FEED:="TestFeed" +DID_FINGERPRINT:="" + all: chain.pem cose test-fail test-pass cose: infra.rego.cose @@ -33,10 +38,10 @@ cose: infra.rego.cose %.pem: $(MAKE) -f Makefile.certs chain.pem +ifeq "$(AUTOPARSE_CHAIN)" "1" ISSUER_DID = $(shell ./sign1util did-x509 -chain chain.pem -policy cn) DID_FINGERPRINT = $(shell ./sign1util did-x509 -chain chain.pem -policy cn | cut -d: -f5) -FEED = acceuroperegistry.azurecr.io/infra - +endif # from these media types have to match containerd. The also need to change and the security policy one ought to be x-ms-ccepolicy-frag # fragment atrifact type = application/x-ms-ccepolicy-frag @@ -124,4 +129,4 @@ test-fail: did-fail clean: $(MAKE) -f Makefile.certs $@ - rm -f infra.rego.base64 infra.rego.cose sign1util + rm -f infra.rego.cose sign1util diff --git a/pkg/cosesign1/cosesign1util_test.go b/pkg/cosesign1/cosesign1util_test.go index 3342b8a..1d217d4 100644 --- a/pkg/cosesign1/cosesign1util_test.go +++ b/pkg/cosesign1/cosesign1util_test.go @@ -48,14 +48,22 @@ var certChainPEM string func TestMain(m *testing.M) { fmt.Println("Generating files...") + makeCleanOut, err := exec.Command("make", "clean").CombinedOutput() + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to clean up: %s\n", err) + fmt.Fprintf(os.Stderr, string(makeCleanOut)) + os.Exit(1) + } - err := exec.Command("make", "chain.pem", "infra.rego.cose").Run() + outputBytes, err := exec.Command("make", "chain.pem", "infra.rego.cose", "leaf.private.pem").CombinedOutput() if err != nil { fmt.Fprintf(os.Stderr, "Failed to build the required test files: %s", err) + fmt.Fprintf(os.Stderr, string(outputBytes)) os.Exit(1) } + fmt.Println(string(outputBytes)) - fragmentRego = readFileStringOrExit("infra.rego.base64") + fragmentRego = readFileStringOrExit("infra.rego") fragmentCose = readFileBytesOrExit("infra.rego.cose") leafPrivatePem = readFileStringOrExit("leaf.private.pem") leafCertPEM = readFileStringOrExit("leaf.cert.pem") @@ -85,7 +93,7 @@ func Test_UnpackAndValidateCannedFragment(t *testing.T) { unpacked, err := UnpackAndValidateCOSE1CertChain(fragmentCose) if err != nil { - t.Errorf("UnpackAndValidateCOSE1CertChain failed: %s", err.Error()) + t.Fatalf("UnpackAndValidateCOSE1CertChain failed: %s", err) } iss := unpacked.Issuer @@ -101,17 +109,17 @@ func Test_UnpackAndValidateCannedFragment(t *testing.T) { if !comparePEMs(pubcert, leafCertPEM) { t.Fatal("pubcert did not match") } - if cty != "application/unknown+json" { - t.Fatal("cty did not match") + if cty != "application/unknown+rego" { + t.Fatalf("cty did not match: %s", cty) } if payload != fragmentRego { t.Fatal("payload did not match") } if iss != "TestIssuer" { - t.Fatal("iss did not match") + t.Fatalf("iss did not match: %s", iss) } if feed != "TestFeed" { - t.Fatal("feed did not match") + t.Fatalf("feed did not match: %s", feed) } } @@ -132,13 +140,13 @@ func Test_UnpackAndValidateCannedFragmentCorrupted(t *testing.T) { // Use CreateCoseSign1 to make a document that should match the one made by the makefile func Test_CreateCoseSign1Fragment(t *testing.T) { - var raw, err = CreateCoseSign1([]byte(fragmentRego), "TestIssuer", "TestFeed", "application/unknown+json", []byte(certChainPEM), []byte(leafPrivatePem), "zero", cose.AlgorithmES384) + var raw, err = CreateCoseSign1([]byte(fragmentRego), "TestIssuer", "TestFeed", "application/unknown+rego", []byte(certChainPEM), []byte(leafPrivatePem), "zero", cose.AlgorithmES384) if err != nil { t.Fatalf("CreateCoseSign1 failed: %s", err) } if len(raw) != len(fragmentCose) { - t.Fatal("created fragment length does not match expected") + t.Fatalf("created fragment length (%d) does not match expected (%d)", len(raw), len(fragmentCose)) } for i := range raw {