From ee9642c6a16ce9ffa3d2454f138bf7c3e99725fe Mon Sep 17 00:00:00 2001 From: Jeff Hodges Date: Mon, 4 Nov 2024 19:31:28 -0800 Subject: [PATCH 01/13] require a database in contentsignaturepki --- signer/contentsignaturepki/contentsignature.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/signer/contentsignaturepki/contentsignature.go b/signer/contentsignaturepki/contentsignature.go index e8bfbd546..67194521e 100644 --- a/signer/contentsignaturepki/contentsignature.go +++ b/signer/contentsignaturepki/contentsignature.go @@ -83,6 +83,9 @@ func New(conf signer.Configuration) (s *ContentSigner, err error) { s.chainUploadLocation = conf.ChainUploadLocation s.caCert = conf.CaCert s.db = conf.DB + if s.db == nil { + return nil, fmt.Errorf("contentsignaturepki %q: a database is required by this signer type but none have been configured", s.ID) + } s.subdomainOverride = conf.SubdomainOverride if conf.Type != Type { From 4cd164d8e4a3987ec1984477b154ca8aec7e1fc6 Mon Sep 17 00:00:00 2001 From: Jeff Hodges Date: Mon, 4 Nov 2024 19:45:17 -0800 Subject: [PATCH 02/13] refactor tests in contentsignaturepki --- .../contentsignature_test.go | 340 ++++++++++-------- 1 file changed, 190 insertions(+), 150 deletions(-) diff --git a/signer/contentsignaturepki/contentsignature_test.go b/signer/contentsignaturepki/contentsignature_test.go index b196b122f..142bcced1 100644 --- a/signer/contentsignaturepki/contentsignature_test.go +++ b/signer/contentsignaturepki/contentsignature_test.go @@ -17,8 +17,116 @@ import ( ) func TestSign(t *testing.T) { + keys := goodKeys() + var testcases = []struct { + cfg signer.Configuration + expectedCommonName string + }{ + {cfg: signer.Configuration{ + Type: Type, + ID: "testsigner0", + Mode: P384ECDSA, + X5U: "file:///tmp/autograph_unit_tests/chains/", + ChainUploadLocation: "file:///tmp/autograph_unit_tests/chains/", + IssuerPrivKey: keys.issuerPrivKey, + IssuerCert: keys.issuerCert, + CaCert: keys.caCert, + }, + expectedCommonName: "testsigner0.content-signature.mozilla.org", + }, + {cfg: signer.Configuration{ + Type: Type, + ID: "testsigner1", + Mode: P256ECDSA, + X5U: "file:///tmp/autograph_unit_tests/chains/", + ChainUploadLocation: "file:///tmp/autograph_unit_tests/chains/", + IssuerPrivKey: ` +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIEABir6WMfkbG2ZyKKDCij1PlSBldaaJqPQ/9ioWvCM5oAoGCCqGSM49 +AwEHoUQDQgAED0x4GeyH3nxaCVQqPFbRkoBg1BJePxTSg1oaRWIgBbrMYaB/TKpL +WoBQZFUwn11IFDP5y1B6Tt9U5DxQ3tgt+w== +-----END EC PRIVATE KEY-----`, + IssuerCert: ` +-----BEGIN CERTIFICATE----- +MIICIDCCAcWgAwIBAgIIFYW+N1jIJvAwCgYIKoZIzj0EAwMwXzELMAkGA1UEBhMC +VVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRAwDgYDVQQK +EwdNb3ppbGxhMRkwFwYDVQQDExBjc3Jvb3QxNTUwODU0NzkxMB4XDTE4MTIyMTE2 +NTk1MVoXDTI5MDIyMjE2NTk1MVowYDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNB +MRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKEwdNb3ppbGxhMRowGAYD +VQQDExFjc2ludGVyMTU1MDg1NDc5MTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA +BA9MeBnsh958WglUKjxW0ZKAYNQSXj8U0oNaGkViIAW6zGGgf0yqS1qAUGRVMJ9d +SBQz+ctQek7fVOQ8UN7YLfujajBoMA4GA1UdDwEB/wQEAwIBhjATBgNVHSUEDDAK +BggrBgEFBQcDAzAPBgNVHRMBAf8EBTADAQH/MDAGA1UdHgEB/wQmMCSgIjAggh4u +Y29udGVudC1zaWduYXR1cmUubW96aWxsYS5vcmcwCgYIKoZIzj0EAwMDSQAwRgIh +AJYQbM1zDA9RkmNwEc4LafBwL98Z+aGy31z80HeC5Y8hAiEA4KEG+ZNinz5yZItW +NYDcA5Hvd1xXeRQi6SWj6Z2qT7w= +-----END CERTIFICATE-----`, + CaCert: ` +-----BEGIN CERTIFICATE----- +MIIB7DCCAZKgAwIBAgIIFYW+N1i+RHgwCgYIKoZIzj0EAwMwXzELMAkGA1UEBhMC +VVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRAwDgYDVQQK +EwdNb3ppbGxhMRkwFwYDVQQDExBjc3Jvb3QxNTUwODU0NzkxMB4XDTE4MTIyMDE2 +NTk1MVoXDTQ5MDIyMjE2NTk1MVowXzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNB +MRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKEwdNb3ppbGxhMRkwFwYD +VQQDExBjc3Jvb3QxNTUwODU0NzkxMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE +SZakSnBD3qkp15bQ+qzcKCn2+OmoOJKVgrSezyrx7IHjtEbCYUz8Zp+HhKg3NXLY +6ZMjO0zYnq3gTdAzH3amOqM4MDYwDgYDVR0PAQH/BAQDAgGGMBMGA1UdJQQMMAoG +CCsGAQUFBwMDMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwMDSAAwRQIgIBgf +KkmH7TerRPn/517v/41o/sF9Hd9iGBilyWtVMggCIQClvRXiMM6DrabvybPGHWTt +mpvOMOT3falDgXh0iOgdIA== +-----END CERTIFICATE-----`, + }, + expectedCommonName: "testsigner1.content-signature.mozilla.org", + }, + {cfg: signer.Configuration{ + Type: Type, + ID: "testsigner1", + SubdomainOverride: "anothersigner1", + Mode: P256ECDSA, + X5U: "file:///tmp/autograph_unit_tests/chains/dedup-path-anothersigner1", + ChainUploadLocation: "file:///tmp/autograph_unit_tests/chains/dedup-path-anothersigner1", + IssuerPrivKey: ` +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIEABir6WMfkbG2ZyKKDCij1PlSBldaaJqPQ/9ioWvCM5oAoGCCqGSM49 +AwEHoUQDQgAED0x4GeyH3nxaCVQqPFbRkoBg1BJePxTSg1oaRWIgBbrMYaB/TKpL +WoBQZFUwn11IFDP5y1B6Tt9U5DxQ3tgt+w== +-----END EC PRIVATE KEY-----`, + IssuerCert: ` +-----BEGIN CERTIFICATE----- +MIICIDCCAcWgAwIBAgIIFYW+N1jIJvAwCgYIKoZIzj0EAwMwXzELMAkGA1UEBhMC +VVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRAwDgYDVQQK +EwdNb3ppbGxhMRkwFwYDVQQDExBjc3Jvb3QxNTUwODU0NzkxMB4XDTE4MTIyMTE2 +NTk1MVoXDTI5MDIyMjE2NTk1MVowYDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNB +MRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKEwdNb3ppbGxhMRowGAYD +VQQDExFjc2ludGVyMTU1MDg1NDc5MTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA +BA9MeBnsh958WglUKjxW0ZKAYNQSXj8U0oNaGkViIAW6zGGgf0yqS1qAUGRVMJ9d +SBQz+ctQek7fVOQ8UN7YLfujajBoMA4GA1UdDwEB/wQEAwIBhjATBgNVHSUEDDAK +BggrBgEFBQcDAzAPBgNVHRMBAf8EBTADAQH/MDAGA1UdHgEB/wQmMCSgIjAggh4u +Y29udGVudC1zaWduYXR1cmUubW96aWxsYS5vcmcwCgYIKoZIzj0EAwMDSQAwRgIh +AJYQbM1zDA9RkmNwEc4LafBwL98Z+aGy31z80HeC5Y8hAiEA4KEG+ZNinz5yZItW +NYDcA5Hvd1xXeRQi6SWj6Z2qT7w= +-----END CERTIFICATE-----`, + CaCert: ` +-----BEGIN CERTIFICATE----- +MIIB7DCCAZKgAwIBAgIIFYW+N1i+RHgwCgYIKoZIzj0EAwMwXzELMAkGA1UEBhMC +VVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRAwDgYDVQQK +EwdNb3ppbGxhMRkwFwYDVQQDExBjc3Jvb3QxNTUwODU0NzkxMB4XDTE4MTIyMDE2 +NTk1MVoXDTQ5MDIyMjE2NTk1MVowXzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNB +MRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKEwdNb3ppbGxhMRkwFwYD +VQQDExBjc3Jvb3QxNTUwODU0NzkxMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE +SZakSnBD3qkp15bQ+qzcKCn2+OmoOJKVgrSezyrx7IHjtEbCYUz8Zp+HhKg3NXLY +6ZMjO0zYnq3gTdAzH3amOqM4MDYwDgYDVR0PAQH/BAQDAgGGMBMGA1UdJQQMMAoG +CCsGAQUFBwMDMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwMDSAAwRQIgIBgf +KkmH7TerRPn/517v/41o/sF9Hd9iGBilyWtVMggCIQClvRXiMM6DrabvybPGHWTt +mpvOMOT3falDgXh0iOgdIA== +-----END CERTIFICATE-----`, + }, + expectedCommonName: "anothersigner1.content-signature.mozilla.org", + }, + } + input := []byte("foobarbaz1234abcd") - for i, testcase := range PASSINGTESTCASES { + for i, testcase := range testcases { // initialize a signer s, err := New(testcase.cfg) if err != nil { @@ -88,151 +196,8 @@ func TestSign(t *testing.T) { } } } - -var PASSINGTESTCASES = []struct { - cfg signer.Configuration - expectedCommonName string -}{ - {cfg: signer.Configuration{ - Type: Type, - ID: "testsigner0", - Mode: P384ECDSA, - X5U: "file:///tmp/autograph_unit_tests/chains/", - ChainUploadLocation: "file:///tmp/autograph_unit_tests/chains/", - IssuerPrivKey: ` ------BEGIN EC PRIVATE KEY----- -MIGkAgEBBDBcwxsHPTSHIVY1qLobCqBtnjRe0UZWOro1xtg2oV4rkypbkkgHHnSA -s8p0PlGIknKgBwYFK4EEACKhZANiAAQMBfcDj4r/9aAXcUsjjun3vCpBSQoskcdi -iF4bE+AcFmPABh6AnwTZv0sHYPjkovk3R3RfuXlKyoqhuD73VqBhkuK7R6mN2snh -fRkWmi6SzHWZIXPzFScoCaHnJrFzNjs= ------END EC PRIVATE KEY-----`, - IssuerCert: ` ------BEGIN CERTIFICATE----- -MIICXDCCAeKgAwIBAgIIFYW6xg9HrnAwCgYIKoZIzj0EAwMwXzELMAkGA1UEBhMC -VVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRAwDgYDVQQK -EwdNb3ppbGxhMRkwFwYDVQQDExBjc3Jvb3QxNTUwODUxMDA2MB4XDTE4MTIyMTE1 -NTY0NloXDTI5MDIyMjE1NTY0NlowYDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNB -MRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKEwdNb3ppbGxhMRowGAYD -VQQDExFjc2ludGVyMTU1MDg1MTAwNjB2MBAGByqGSM49AgEGBSuBBAAiA2IABAwF -9wOPiv/1oBdxSyOO6fe8KkFJCiyRx2KIXhsT4BwWY8AGHoCfBNm/Swdg+OSi+TdH -dF+5eUrKiqG4PvdWoGGS4rtHqY3ayeF9GRaaLpLMdZkhc/MVJygJoecmsXM2O6Nq -MGgwDgYDVR0PAQH/BAQDAgGGMBMGA1UdJQQMMAoGCCsGAQUFBwMDMA8GA1UdEwEB -/wQFMAMBAf8wMAYDVR0eAQH/BCYwJKAiMCCCHi5jb250ZW50LXNpZ25hdHVyZS5t -b3ppbGxhLm9yZzAKBggqhkjOPQQDAwNoADBlAjBss+GLdMdLT2Y/g73OE9x0WyUG -vqzO7klt20yytmhaYMIPT/zRnWsHZbqEijHMzGsCMQDEoKetuWkyBkzAytS6l+ss -mYigBlwySY+gTqsjuIrydWlKaOv1GU+PXbwX0cQuaN8= ------END CERTIFICATE-----`, - CaCert: ` ------BEGIN CERTIFICATE----- -MIICKTCCAa+gAwIBAgIIFYW6xg2sw4QwCgYIKoZIzj0EAwMwXzELMAkGA1UEBhMC -VVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRAwDgYDVQQK -EwdNb3ppbGxhMRkwFwYDVQQDExBjc3Jvb3QxNTUwODUxMDA2MB4XDTE4MTIyMDE1 -NTY0NloXDTQ5MDIyMjE1NTY0NlowXzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNB -MRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKEwdNb3ppbGxhMRkwFwYD -VQQDExBjc3Jvb3QxNTUwODUxMDA2MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAENrUI -9GJFild/ZVNwh7885643BhJlqTqZSas8mAUkYRDKv9lXk/r+CpLPclrwz/Po21xn -5SlibnOTXaOZdMlDcWCCKqNNGRyi1xPHJIfvtF6+CswJnrkthpy6dimqd0Tyozgw -NjAOBgNVHQ8BAf8EBAMCAYYwEwYDVR0lBAwwCgYIKwYBBQUHAwMwDwYDVR0TAQH/ -BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjB3fOCz2SQvxNZ65juSotQNRvXhB4TZ -nsbYLErV5grBhN+UxzmY9YwlOl6j6CoBiNkCMQCVBh9UBkWNkUfMUGImrCNDLvlw -//Vb8kLBsJmLQjZNbXt+ikjYkWGqppp2pVwwgf4= ------END CERTIFICATE-----`, - }, - expectedCommonName: "testsigner0.content-signature.mozilla.org", - }, - {cfg: signer.Configuration{ - Type: Type, - ID: "testsigner1", - Mode: P256ECDSA, - X5U: "file:///tmp/autograph_unit_tests/chains/", - ChainUploadLocation: "file:///tmp/autograph_unit_tests/chains/", - IssuerPrivKey: ` ------BEGIN EC PRIVATE KEY----- -MHcCAQEEIEABir6WMfkbG2ZyKKDCij1PlSBldaaJqPQ/9ioWvCM5oAoGCCqGSM49 -AwEHoUQDQgAED0x4GeyH3nxaCVQqPFbRkoBg1BJePxTSg1oaRWIgBbrMYaB/TKpL -WoBQZFUwn11IFDP5y1B6Tt9U5DxQ3tgt+w== ------END EC PRIVATE KEY-----`, - IssuerCert: ` ------BEGIN CERTIFICATE----- -MIICIDCCAcWgAwIBAgIIFYW+N1jIJvAwCgYIKoZIzj0EAwMwXzELMAkGA1UEBhMC -VVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRAwDgYDVQQK -EwdNb3ppbGxhMRkwFwYDVQQDExBjc3Jvb3QxNTUwODU0NzkxMB4XDTE4MTIyMTE2 -NTk1MVoXDTI5MDIyMjE2NTk1MVowYDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNB -MRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKEwdNb3ppbGxhMRowGAYD -VQQDExFjc2ludGVyMTU1MDg1NDc5MTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA -BA9MeBnsh958WglUKjxW0ZKAYNQSXj8U0oNaGkViIAW6zGGgf0yqS1qAUGRVMJ9d -SBQz+ctQek7fVOQ8UN7YLfujajBoMA4GA1UdDwEB/wQEAwIBhjATBgNVHSUEDDAK -BggrBgEFBQcDAzAPBgNVHRMBAf8EBTADAQH/MDAGA1UdHgEB/wQmMCSgIjAggh4u -Y29udGVudC1zaWduYXR1cmUubW96aWxsYS5vcmcwCgYIKoZIzj0EAwMDSQAwRgIh -AJYQbM1zDA9RkmNwEc4LafBwL98Z+aGy31z80HeC5Y8hAiEA4KEG+ZNinz5yZItW -NYDcA5Hvd1xXeRQi6SWj6Z2qT7w= ------END CERTIFICATE-----`, - CaCert: ` ------BEGIN CERTIFICATE----- -MIIB7DCCAZKgAwIBAgIIFYW+N1i+RHgwCgYIKoZIzj0EAwMwXzELMAkGA1UEBhMC -VVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRAwDgYDVQQK -EwdNb3ppbGxhMRkwFwYDVQQDExBjc3Jvb3QxNTUwODU0NzkxMB4XDTE4MTIyMDE2 -NTk1MVoXDTQ5MDIyMjE2NTk1MVowXzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNB -MRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKEwdNb3ppbGxhMRkwFwYD -VQQDExBjc3Jvb3QxNTUwODU0NzkxMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE -SZakSnBD3qkp15bQ+qzcKCn2+OmoOJKVgrSezyrx7IHjtEbCYUz8Zp+HhKg3NXLY -6ZMjO0zYnq3gTdAzH3amOqM4MDYwDgYDVR0PAQH/BAQDAgGGMBMGA1UdJQQMMAoG -CCsGAQUFBwMDMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwMDSAAwRQIgIBgf -KkmH7TerRPn/517v/41o/sF9Hd9iGBilyWtVMggCIQClvRXiMM6DrabvybPGHWTt -mpvOMOT3falDgXh0iOgdIA== ------END CERTIFICATE-----`, - }, - expectedCommonName: "testsigner1.content-signature.mozilla.org", - }, - {cfg: signer.Configuration{ - Type: Type, - ID: "testsigner1", - SubdomainOverride: "anothersigner1", - Mode: P256ECDSA, - X5U: "file:///tmp/autograph_unit_tests/chains/dedup-path-anothersigner1", - ChainUploadLocation: "file:///tmp/autograph_unit_tests/chains/dedup-path-anothersigner1", - IssuerPrivKey: ` ------BEGIN EC PRIVATE KEY----- -MHcCAQEEIEABir6WMfkbG2ZyKKDCij1PlSBldaaJqPQ/9ioWvCM5oAoGCCqGSM49 -AwEHoUQDQgAED0x4GeyH3nxaCVQqPFbRkoBg1BJePxTSg1oaRWIgBbrMYaB/TKpL -WoBQZFUwn11IFDP5y1B6Tt9U5DxQ3tgt+w== ------END EC PRIVATE KEY-----`, - IssuerCert: ` ------BEGIN CERTIFICATE----- -MIICIDCCAcWgAwIBAgIIFYW+N1jIJvAwCgYIKoZIzj0EAwMwXzELMAkGA1UEBhMC -VVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRAwDgYDVQQK -EwdNb3ppbGxhMRkwFwYDVQQDExBjc3Jvb3QxNTUwODU0NzkxMB4XDTE4MTIyMTE2 -NTk1MVoXDTI5MDIyMjE2NTk1MVowYDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNB -MRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKEwdNb3ppbGxhMRowGAYD -VQQDExFjc2ludGVyMTU1MDg1NDc5MTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA -BA9MeBnsh958WglUKjxW0ZKAYNQSXj8U0oNaGkViIAW6zGGgf0yqS1qAUGRVMJ9d -SBQz+ctQek7fVOQ8UN7YLfujajBoMA4GA1UdDwEB/wQEAwIBhjATBgNVHSUEDDAK -BggrBgEFBQcDAzAPBgNVHRMBAf8EBTADAQH/MDAGA1UdHgEB/wQmMCSgIjAggh4u -Y29udGVudC1zaWduYXR1cmUubW96aWxsYS5vcmcwCgYIKoZIzj0EAwMDSQAwRgIh -AJYQbM1zDA9RkmNwEc4LafBwL98Z+aGy31z80HeC5Y8hAiEA4KEG+ZNinz5yZItW -NYDcA5Hvd1xXeRQi6SWj6Z2qT7w= ------END CERTIFICATE-----`, - CaCert: ` ------BEGIN CERTIFICATE----- -MIIB7DCCAZKgAwIBAgIIFYW+N1i+RHgwCgYIKoZIzj0EAwMwXzELMAkGA1UEBhMC -VVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRAwDgYDVQQK -EwdNb3ppbGxhMRkwFwYDVQQDExBjc3Jvb3QxNTUwODU0NzkxMB4XDTE4MTIyMDE2 -NTk1MVoXDTQ5MDIyMjE2NTk1MVowXzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNB -MRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKEwdNb3ppbGxhMRkwFwYD -VQQDExBjc3Jvb3QxNTUwODU0NzkxMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE -SZakSnBD3qkp15bQ+qzcKCn2+OmoOJKVgrSezyrx7IHjtEbCYUz8Zp+HhKg3NXLY -6ZMjO0zYnq3gTdAzH3amOqM4MDYwDgYDVR0PAQH/BAQDAgGGMBMGA1UdJQQMMAoG -CCsGAQUFBwMDMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwMDSAAwRQIgIBgf -KkmH7TerRPn/517v/41o/sF9Hd9iGBilyWtVMggCIQClvRXiMM6DrabvybPGHWTt -mpvOMOT3falDgXh0iOgdIA== ------END CERTIFICATE-----`, - }, - expectedCommonName: "anothersigner1.content-signature.mozilla.org", - }, -} - func TestNewFailure(t *testing.T) { - TESTCASES := []struct { + testcases := []struct { err string cfg signer.Configuration }{ @@ -255,7 +220,7 @@ w2hKSJpdD11n9tJEQ7MieRzrqr58rqm9tymUH0rKIg== -----END RSA PRIVATE KEY-----`, }}, } - for _, testcase := range TESTCASES { + for _, testcase := range testcases { _, err := New(testcase.cfg) if !strings.Contains(err.Error(), testcase.err) { t.Fatalf("expected to fail with '%s' but failed with '%s' instead", testcase.err, err) @@ -267,7 +232,18 @@ w2hKSJpdD11n9tJEQ7MieRzrqr58rqm9tymUH0rKIg== } func TestNoShortData(t *testing.T) { - s, err := New(PASSINGTESTCASES[0].cfg) + keys := goodKeys() + cfg := signer.Configuration{ + Type: Type, + ID: "testsigner0", + Mode: P384ECDSA, + X5U: "file:///tmp/autograph_unit_tests/chains/", + ChainUploadLocation: "file:///tmp/autograph_unit_tests/chains/", + IssuerPrivKey: keys.issuerPrivKey, + IssuerCert: keys.issuerCert, + CaCert: keys.caCert, + } + s, err := New(cfg) if err != nil { t.Fatalf("signer initialization failed with: %v", err) } @@ -288,12 +264,76 @@ func (e *ErrorReader) Read(p []byte) (n int, err error) { func TestReadRandFailureOnSignHash(t *testing.T) { input := []byte("foobarbaz1234abcd") - testcase := PASSINGTESTCASES[0] - s, _ := New(testcase.cfg) + keys := goodKeys() + cfg := signer.Configuration{ + Type: Type, + ID: "testsigner0", + Mode: P384ECDSA, + X5U: "file:///tmp/autograph_unit_tests/chains/", + ChainUploadLocation: "file:///tmp/autograph_unit_tests/chains/", + IssuerPrivKey: keys.issuerPrivKey, + IssuerCert: keys.issuerCert, + CaCert: keys.caCert, + } + s, err := New(cfg) + if err != nil { + t.Fatalf("signer initialization failed with: %v", err) + } // TODO: Add a configurable rand.Reader s.rand = &ErrorReader{} - _, err := s.SignData(input, nil) + _, err = s.SignData(input, nil) if err == nil { t.Fatal("Should have failed to sign data with error in the SignHash") } } + +type signerKeys struct { + issuerPrivKey string + issuerCert string + caCert string +} + +// goodKeys is a lil helper for providing a set of ecdsa keys that will work for +// testing. +func goodKeys() signerKeys { + return signerKeys{ + issuerPrivKey: ` +-----BEGIN EC PRIVATE KEY----- +MIGkAgEBBDBcwxsHPTSHIVY1qLobCqBtnjRe0UZWOro1xtg2oV4rkypbkkgHHnSA +s8p0PlGIknKgBwYFK4EEACKhZANiAAQMBfcDj4r/9aAXcUsjjun3vCpBSQoskcdi +iF4bE+AcFmPABh6AnwTZv0sHYPjkovk3R3RfuXlKyoqhuD73VqBhkuK7R6mN2snh +fRkWmi6SzHWZIXPzFScoCaHnJrFzNjs= +-----END EC PRIVATE KEY-----`, + issuerCert: ` +-----BEGIN CERTIFICATE----- +MIICXDCCAeKgAwIBAgIIFYW6xg9HrnAwCgYIKoZIzj0EAwMwXzELMAkGA1UEBhMC +VVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRAwDgYDVQQK +EwdNb3ppbGxhMRkwFwYDVQQDExBjc3Jvb3QxNTUwODUxMDA2MB4XDTE4MTIyMTE1 +NTY0NloXDTI5MDIyMjE1NTY0NlowYDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNB +MRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKEwdNb3ppbGxhMRowGAYD +VQQDExFjc2ludGVyMTU1MDg1MTAwNjB2MBAGByqGSM49AgEGBSuBBAAiA2IABAwF +9wOPiv/1oBdxSyOO6fe8KkFJCiyRx2KIXhsT4BwWY8AGHoCfBNm/Swdg+OSi+TdH +dF+5eUrKiqG4PvdWoGGS4rtHqY3ayeF9GRaaLpLMdZkhc/MVJygJoecmsXM2O6Nq +MGgwDgYDVR0PAQH/BAQDAgGGMBMGA1UdJQQMMAoGCCsGAQUFBwMDMA8GA1UdEwEB +/wQFMAMBAf8wMAYDVR0eAQH/BCYwJKAiMCCCHi5jb250ZW50LXNpZ25hdHVyZS5t +b3ppbGxhLm9yZzAKBggqhkjOPQQDAwNoADBlAjBss+GLdMdLT2Y/g73OE9x0WyUG +vqzO7klt20yytmhaYMIPT/zRnWsHZbqEijHMzGsCMQDEoKetuWkyBkzAytS6l+ss +mYigBlwySY+gTqsjuIrydWlKaOv1GU+PXbwX0cQuaN8= +-----END CERTIFICATE-----`, + caCert: ` +-----BEGIN CERTIFICATE----- +MIICKTCCAa+gAwIBAgIIFYW6xg2sw4QwCgYIKoZIzj0EAwMwXzELMAkGA1UEBhMC +VVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRAwDgYDVQQK +EwdNb3ppbGxhMRkwFwYDVQQDExBjc3Jvb3QxNTUwODUxMDA2MB4XDTE4MTIyMDE1 +NTY0NloXDTQ5MDIyMjE1NTY0NlowXzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNB +MRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKEwdNb3ppbGxhMRkwFwYD +VQQDExBjc3Jvb3QxNTUwODUxMDA2MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAENrUI +9GJFild/ZVNwh7885643BhJlqTqZSas8mAUkYRDKv9lXk/r+CpLPclrwz/Po21xn +5SlibnOTXaOZdMlDcWCCKqNNGRyi1xPHJIfvtF6+CswJnrkthpy6dimqd0Tyozgw +NjAOBgNVHQ8BAf8EBAMCAYYwEwYDVR0lBAwwCgYIKwYBBQUHAwMwDwYDVR0TAQH/ +BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjB3fOCz2SQvxNZ65juSotQNRvXhB4TZ +nsbYLErV5grBhN+UxzmY9YwlOl6j6CoBiNkCMQCVBh9UBkWNkUfMUGImrCNDLvlw +//Vb8kLBsJmLQjZNbXt+ikjYkWGqppp2pVwwgf4= +-----END CERTIFICATE-----`, + } +} From 3b0fdc48e56b141533c40379756f56733efe054a Mon Sep 17 00:00:00 2001 From: Jeff Hodges Date: Mon, 4 Nov 2024 19:53:37 -0800 Subject: [PATCH 03/13] pass in test handler but now hsm errors happen --- .../contentsignature_test.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/signer/contentsignaturepki/contentsignature_test.go b/signer/contentsignaturepki/contentsignature_test.go index 142bcced1..c3a3dc4f0 100644 --- a/signer/contentsignaturepki/contentsignature_test.go +++ b/signer/contentsignaturepki/contentsignature_test.go @@ -12,6 +12,7 @@ import ( "strings" "testing" + "github.com/mozilla-services/autograph/database" "github.com/mozilla-services/autograph/signer" verifier "github.com/mozilla-services/autograph/verifier/contentsignature" ) @@ -125,9 +126,11 @@ mpvOMOT3falDgXh0iOgdIA== }, } + dbHandler := testDBHandler(t) input := []byte("foobarbaz1234abcd") for i, testcase := range testcases { // initialize a signer + testcase.cfg.DB = dbHandler s, err := New(testcase.cfg) if err != nil { t.Fatalf("testcase %d signer initialization failed with: %v", i, err) @@ -242,6 +245,7 @@ func TestNoShortData(t *testing.T) { IssuerPrivKey: keys.issuerPrivKey, IssuerCert: keys.issuerCert, CaCert: keys.caCert, + DB: testDBHandler(t), } s, err := New(cfg) if err != nil { @@ -274,6 +278,7 @@ func TestReadRandFailureOnSignHash(t *testing.T) { IssuerPrivKey: keys.issuerPrivKey, IssuerCert: keys.issuerCert, CaCert: keys.caCert, + DB: testDBHandler(t), } s, err := New(cfg) if err != nil { @@ -337,3 +342,17 @@ nsbYLErV5grBhN+UxzmY9YwlOl6j6CoBiNkCMQCVBh9UBkWNkUfMUGImrCNDLvlw -----END CERTIFICATE-----`, } } + +func testDBHandler(t *testing.T) *database.Handler { + host := database.GetTestDBHost() + dbHandler, err := database.Connect(database.Config{ + Name: "autograph", + User: "myautographdbuser", + Password: "myautographdbpassword", + Host: host + ":5432", + }) + if err != nil { + t.Fatalf("failed to connect to test database: %v", err) + } + return dbHandler +} From 0f247da3c639ec237632d7058b74f377196c93a6 Mon Sep 17 00:00:00 2001 From: Jeff Hodges Date: Mon, 4 Nov 2024 19:55:38 -0800 Subject: [PATCH 04/13] more testhandler refactor --- signer/contentsignaturepki/contentsignature_test.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/signer/contentsignaturepki/contentsignature_test.go b/signer/contentsignaturepki/contentsignature_test.go index c3a3dc4f0..49b1c0d9a 100644 --- a/signer/contentsignaturepki/contentsignature_test.go +++ b/signer/contentsignaturepki/contentsignature_test.go @@ -19,6 +19,8 @@ import ( func TestSign(t *testing.T) { keys := goodKeys() + dbHandler := testDBHandler(t) + var testcases = []struct { cfg signer.Configuration expectedCommonName string @@ -32,6 +34,7 @@ func TestSign(t *testing.T) { IssuerPrivKey: keys.issuerPrivKey, IssuerCert: keys.issuerCert, CaCert: keys.caCert, + DB: dbHandler, }, expectedCommonName: "testsigner0.content-signature.mozilla.org", }, @@ -76,6 +79,7 @@ CCsGAQUFBwMDMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwMDSAAwRQIgIBgf KkmH7TerRPn/517v/41o/sF9Hd9iGBilyWtVMggCIQClvRXiMM6DrabvybPGHWTt mpvOMOT3falDgXh0iOgdIA== -----END CERTIFICATE-----`, + DB: dbHandler, }, expectedCommonName: "testsigner1.content-signature.mozilla.org", }, @@ -121,16 +125,15 @@ CCsGAQUFBwMDMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwMDSAAwRQIgIBgf KkmH7TerRPn/517v/41o/sF9Hd9iGBilyWtVMggCIQClvRXiMM6DrabvybPGHWTt mpvOMOT3falDgXh0iOgdIA== -----END CERTIFICATE-----`, + DB: dbHandler, }, expectedCommonName: "anothersigner1.content-signature.mozilla.org", }, } - dbHandler := testDBHandler(t) input := []byte("foobarbaz1234abcd") for i, testcase := range testcases { // initialize a signer - testcase.cfg.DB = dbHandler s, err := New(testcase.cfg) if err != nil { t.Fatalf("testcase %d signer initialization failed with: %v", i, err) From 9f0d17e1a87494c091e736db666a695d9f09a285 Mon Sep 17 00:00:00 2001 From: Jeff Hodges Date: Mon, 4 Nov 2024 20:14:08 -0800 Subject: [PATCH 05/13] add truncates to contentsignaturepki --- signer/contentsignaturepki/contentsignature_test.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/signer/contentsignaturepki/contentsignature_test.go b/signer/contentsignaturepki/contentsignature_test.go index 49b1c0d9a..d9a30e97c 100644 --- a/signer/contentsignaturepki/contentsignature_test.go +++ b/signer/contentsignaturepki/contentsignature_test.go @@ -357,5 +357,15 @@ func testDBHandler(t *testing.T) *database.Handler { if err != nil { t.Fatalf("failed to connect to test database: %v", err) } + _, err = dbHandler.DB.Exec("truncate table endentities;") + if err != nil { + t.Fatalf("failed to truncate endentities table before running test: %v", err) + } + t.Cleanup(func() { + _, err = dbHandler.DB.Exec("truncate table endentities;") + if err != nil { + t.Fatalf("failed to truncate endentities table after running test: %v", err) + } + }) return dbHandler } From 658d6091f2cac1a20c3515b88713b235e183c363 Mon Sep 17 00:00:00 2001 From: Jeff Hodges Date: Mon, 4 Nov 2024 20:30:19 -0800 Subject: [PATCH 06/13] always rebuild docker image for unit tests Got confused. Need better testing scipt. --- docker-compose.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index b57b2319c..511e8f856 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -97,7 +97,6 @@ services: unit-test: container_name: autograph-unit-test - image: autograph-app build: context: . environment: @@ -116,7 +115,4 @@ services: - db user: "0" working_dir: "/app/src/autograph/" - command: - [ - "./bin/run_unit_tests.sh" - ] + command: ["./bin/run_unit_tests.sh"] From c240741ef89ba29b67f54a43d199ac48b98259d2 Mon Sep 17 00:00:00 2001 From: Jeff Hodges Date: Mon, 4 Nov 2024 22:01:35 -0800 Subject: [PATCH 07/13] k --- .../contentsignature_test.go | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/signer/contentsignaturepki/contentsignature_test.go b/signer/contentsignaturepki/contentsignature_test.go index d9a30e97c..7911f6979 100644 --- a/signer/contentsignaturepki/contentsignature_test.go +++ b/signer/contentsignaturepki/contentsignature_test.go @@ -7,8 +7,10 @@ package contentsignaturepki import ( + "context" "crypto/ecdsa" "errors" + "fmt" "strings" "testing" @@ -357,15 +359,35 @@ func testDBHandler(t *testing.T) *database.Handler { if err != nil { t.Fatalf("failed to connect to test database: %v", err) } - _, err = dbHandler.DB.Exec("truncate table endentities;") + err = dbHandler.CheckConnectionContext(context.Background()) + if err != nil { + t.Fatalf("db.CheckConnection failed when it should not have with error: %s", err) + } + + superDBHandler, err := database.Connect(database.Config{ + Name: "postgres", + User: "myautographdbuser", + Password: "", + Host: host + ":5432", + }) + if err != nil { + t.Fatalf("failed to connect to database as superuser to truncate: %v", err) + } + _, err = superDBHandler.DB.Exec("truncate table endentities;") if err != nil { t.Fatalf("failed to truncate endentities table before running test: %v", err) } + + t.Logf("FIXME HERE 1") + fmt.Println("FIXME HERE 1") t.Cleanup(func() { - _, err = dbHandler.DB.Exec("truncate table endentities;") + _, err = superDBHandler.DB.Exec("truncate table endentities;") if err != nil { + t.Logf("FIXME HERE 2") + fmt.Println("FIXME HERE 2") t.Fatalf("failed to truncate endentities table after running test: %v", err) } + dbHandler.Close() }) return dbHandler } From 9cd7f7cc434345584efb4771536a712a60d64b30 Mon Sep 17 00:00:00 2001 From: Jeff Hodges Date: Fri, 8 Nov 2024 17:30:47 -0800 Subject: [PATCH 08/13] almost done --- .../contentsignaturepki/contentsignature.go | 2 +- .../contentsignature_test.go | 40 +++++++++---------- 2 files changed, 19 insertions(+), 23 deletions(-) diff --git a/signer/contentsignaturepki/contentsignature.go b/signer/contentsignaturepki/contentsignature.go index 67194521e..a5bbfcc69 100644 --- a/signer/contentsignaturepki/contentsignature.go +++ b/signer/contentsignaturepki/contentsignature.go @@ -84,7 +84,7 @@ func New(conf signer.Configuration) (s *ContentSigner, err error) { s.caCert = conf.CaCert s.db = conf.DB if s.db == nil { - return nil, fmt.Errorf("contentsignaturepki %q: a database is required by this signer type but none have been configured", s.ID) + return nil, fmt.Errorf("contentsignaturepki %q: a database is required by the contentsignaturepki signer type but none have been configured", s.ID) } s.subdomainOverride = conf.SubdomainOverride diff --git a/signer/contentsignaturepki/contentsignature_test.go b/signer/contentsignaturepki/contentsignature_test.go index 7911f6979..f5d3b8755 100644 --- a/signer/contentsignaturepki/contentsignature_test.go +++ b/signer/contentsignaturepki/contentsignature_test.go @@ -21,7 +21,7 @@ import ( func TestSign(t *testing.T) { keys := goodKeys() - dbHandler := testDBHandler(t) + dbHandler := newTestDBHandler(t) var testcases = []struct { cfg signer.Configuration @@ -205,14 +205,16 @@ mpvOMOT3falDgXh0iOgdIA== } } func TestNewFailure(t *testing.T) { + dbHandler := newTestDBHandler(t) + testcases := []struct { err string cfg signer.Configuration }{ - {err: `contentsignaturepki "": invalid type`, cfg: signer.Configuration{Type: ""}}, - {err: `contentsignaturepki "": missing signer ID in signer configuration`, cfg: signer.Configuration{Type: Type, ID: ""}}, - {err: `contentsignaturepki "bob": missing issuer private key in signer configuration`, cfg: signer.Configuration{Type: Type, ID: "bob"}}, - {err: `contentsignaturepki "bob": failed to get keys`, cfg: signer.Configuration{Type: Type, ID: "bob", IssuerPrivKey: "Ym9iCg=="}}, + {err: `contentsignaturepki "": invalid type`, cfg: signer.Configuration{Type: "", DB: dbHandler}}, + {err: `contentsignaturepki "": missing signer ID in signer configuration`, cfg: signer.Configuration{Type: Type, ID: "", DB: dbHandler}}, + {err: `contentsignaturepki "bob": missing issuer private key in signer configuration`, cfg: signer.Configuration{Type: Type, ID: "bob", DB: dbHandler}}, + {err: `contentsignaturepki "bob": failed to get keys`, cfg: signer.Configuration{Type: Type, ID: "bob", IssuerPrivKey: "Ym9iCg==", DB: dbHandler}}, {err: `contentsignaturepki "abcd": invalid public key type for issuer, must be ecdsa`, cfg: signer.Configuration{ Type: Type, ID: "abcd", @@ -226,7 +228,12 @@ ogU63yRBtCOZDYKtMbaDvXvLfKjeIBzNAiEA4otLPzrJH6K1HQaf5rgI6dEcBWGP M1ZxulpMFD86/QECIAY+AuNXfbhE6gX7xoedPYB3AML5oTmvdzTsL2IePSZpAiBl w2hKSJpdD11n9tJEQ7MieRzrqr58rqm9tymUH0rKIg== -----END RSA PRIVATE KEY-----`, + DB: dbHandler, }}, + { + err: `contentsignaturepki "foo": a database is required by the contentsignaturepki signer type but none have been configured`, + cfg: signer.Configuration{Type: "contentsignaturepki", ID: "foo", DB: nil}, + }, } for _, testcase := range testcases { _, err := New(testcase.cfg) @@ -250,7 +257,7 @@ func TestNoShortData(t *testing.T) { IssuerPrivKey: keys.issuerPrivKey, IssuerCert: keys.issuerCert, CaCert: keys.caCert, - DB: testDBHandler(t), + DB: newTestDBHandler(t), } s, err := New(cfg) if err != nil { @@ -283,7 +290,7 @@ func TestReadRandFailureOnSignHash(t *testing.T) { IssuerPrivKey: keys.issuerPrivKey, IssuerCert: keys.issuerCert, CaCert: keys.caCert, - DB: testDBHandler(t), + DB: newTestDBHandler(t), } s, err := New(cfg) if err != nil { @@ -348,7 +355,7 @@ nsbYLErV5grBhN+UxzmY9YwlOl6j6CoBiNkCMQCVBh9UBkWNkUfMUGImrCNDLvlw } } -func testDBHandler(t *testing.T) *database.Handler { +func newTestDBHandler(t *testing.T) *database.Handler { host := database.GetTestDBHost() dbHandler, err := database.Connect(database.Config{ Name: "autograph", @@ -364,24 +371,13 @@ func testDBHandler(t *testing.T) *database.Handler { t.Fatalf("db.CheckConnection failed when it should not have with error: %s", err) } - superDBHandler, err := database.Connect(database.Config{ - Name: "postgres", - User: "myautographdbuser", - Password: "", - Host: host + ":5432", - }) - if err != nil { - t.Fatalf("failed to connect to database as superuser to truncate: %v", err) - } - _, err = superDBHandler.DB.Exec("truncate table endentities;") + _, err = dbHandler.DB.Exec("truncate table endentities;") if err != nil { t.Fatalf("failed to truncate endentities table before running test: %v", err) } - - t.Logf("FIXME HERE 1") - fmt.Println("FIXME HERE 1") + t.Cleanup(func() { - _, err = superDBHandler.DB.Exec("truncate table endentities;") + _, err = dbHandler.DB.Exec("truncate table endentities;") if err != nil { t.Logf("FIXME HERE 2") fmt.Println("FIXME HERE 2") From b567fda8bdee471c9dfb63accafd1d02dc428685 Mon Sep 17 00:00:00 2001 From: Jeff Hodges Date: Sat, 9 Nov 2024 00:43:03 -0800 Subject: [PATCH 09/13] add ClearDatabase and a new test to make sure i didnt break the hsm integration --- database/connect.go | 7 ++ main_test.go | 2 +- .../contentsignature_test.go | 103 ++++++++++++++++-- 3 files changed, 101 insertions(+), 11 deletions(-) diff --git a/database/connect.go b/database/connect.go index 735809639..4c36393dd 100644 --- a/database/connect.go +++ b/database/connect.go @@ -119,3 +119,10 @@ func GetTestDBHost() string { } return host } + +// ClearDatabase removes all the data from the given database. It's meant only +// for use in the tests. +func ClearDatabase(db *Handler) error { + _, err := db.DB.Exec("truncate table endentities;") + return err +} diff --git a/main_test.go b/main_test.go index 50acb1bcd..cf5cacd3c 100644 --- a/main_test.go +++ b/main_test.go @@ -60,7 +60,7 @@ func newTestAutographer(t *testing.T) (*autographer, configuration) { MonitorPollInterval: 10 * time.Second, }) if err == nil { - db.Exec("truncate table endentities;") + database.ClearDatabase(db) } close(ag.exit) }) diff --git a/signer/contentsignaturepki/contentsignature_test.go b/signer/contentsignaturepki/contentsignature_test.go index f5d3b8755..37ca3d73b 100644 --- a/signer/contentsignaturepki/contentsignature_test.go +++ b/signer/contentsignaturepki/contentsignature_test.go @@ -8,9 +8,13 @@ package contentsignaturepki import ( "context" + "crypto" "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" "errors" "fmt" + "io" "strings" "testing" @@ -135,6 +139,8 @@ mpvOMOT3falDgXh0iOgdIA== input := []byte("foobarbaz1234abcd") for i, testcase := range testcases { + database.ClearDatabase(dbHandler) + // initialize a signer s, err := New(testcase.cfg) if err != nil { @@ -304,6 +310,91 @@ func TestReadRandFailureOnSignHash(t *testing.T) { } } +type fakeHSM struct { + slotToKeys map[string]crypto.PrivateKey +} + +// GetPrivateKey implements signer.HSM. +func (f *fakeHSM) GetPrivateKey(label []byte) (crypto.PrivateKey, error) { + key, ok := f.slotToKeys[string(label)] + if !ok { + return nil, fmt.Errorf("key not found") + } + return key, nil +} + +// GetRand implements signer.HSM. +func (f *fakeHSM) GetRand() io.Reader { + return rand.Reader +} + +// MakeKey creats a key but currently only makes P256 ecdsa kyes. +func (f *fakeHSM) MakeKey(keyTpl interface{}, keyName string) (crypto.PrivateKey, crypto.PublicKey, error) { + switch keyTpl.(type) { + case *ecdsa.PublicKey: + _, ok := f.slotToKeys[keyName] + if ok { + return nil, nil, fmt.Errorf("fakeHSM: key with name %q already exists", keyName) + } + priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + return nil, nil, fmt.Errorf("fakeHSM: failed to generate key: %v", err) + } + f.slotToKeys[keyName] = priv + return priv, priv.Public(), nil + default: + return nil, nil, fmt.Errorf("fakeHSM: making key of type %T is not supported", keyTpl) + } +} + +// TestExistingEEKeyShouldWork is an attempt to mimic autograph booting up after +// a restart with an existing EE key. That is, the first signer creates the EE +// key in the HSM, and the second one should pick it up successfully. +func TestExistingEEKeyShouldWork(t *testing.T) { + dbHandler := newTestDBHandler(t) + hsm := &fakeHSM{slotToKeys: make(map[string]crypto.PrivateKey)} + newCfg := func() signer.Configuration { + keys := goodKeys() + cfg := &signer.Configuration{ + Type: Type, + ID: "testsigner0", + Mode: P384ECDSA, + X5U: "file:///tmp/autograph_unit_tests/chains/", + ChainUploadLocation: "file:///tmp/autograph_unit_tests/chains/", + IssuerPrivKey: keys.issuerPrivKey, + IssuerCert: keys.issuerCert, + CaCert: keys.caCert, + DB: dbHandler, + } + cfg.InitHSM(hsm) + return *cfg + } + + s1, err := New(newCfg()) + if err != nil { + t.Fatalf("first signer: initialization failed with: %v", err) + } + _, err = s1.SignData([]byte("foobarbaz1234abcd"), nil) + if err != nil { + t.Fatalf("first signer: failed to sign data: %v", err) + } + + s2, err := New(newCfg()) + if err != nil { + t.Fatalf("second signer: initialization failed with: %v", err) + } + _, err = s2.SignData([]byte("foobarbaz1234abcd"), nil) + if err != nil { + t.Fatalf("second signer: failed to sign data: %v", err) + } + if s1.PrivateKey != s2.PrivateKey { + t.Errorf("second signer: private key should be the same as the first signer") + } + if len(hsm.slotToKeys) != 1 { + t.Errorf("expected 1 key in the HSM, got %d", len(hsm.slotToKeys)) + } +} + type signerKeys struct { issuerPrivKey string issuerCert string @@ -371,18 +462,10 @@ func newTestDBHandler(t *testing.T) *database.Handler { t.Fatalf("db.CheckConnection failed when it should not have with error: %s", err) } - _, err = dbHandler.DB.Exec("truncate table endentities;") - if err != nil { - t.Fatalf("failed to truncate endentities table before running test: %v", err) - } + database.ClearDatabase(dbHandler) t.Cleanup(func() { - _, err = dbHandler.DB.Exec("truncate table endentities;") - if err != nil { - t.Logf("FIXME HERE 2") - fmt.Println("FIXME HERE 2") - t.Fatalf("failed to truncate endentities table after running test: %v", err) - } + database.ClearDatabase(dbHandler) dbHandler.Close() }) return dbHandler From 5ffd87233b148edcdacc192fe06b7257e0b7061d Mon Sep 17 00:00:00 2001 From: Jeff Hodges Date: Sat, 9 Nov 2024 00:43:49 -0800 Subject: [PATCH 10/13] rename --- database/connect.go | 4 ++-- main_test.go | 2 +- signer/contentsignaturepki/contentsignature_test.go | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/database/connect.go b/database/connect.go index 4c36393dd..71844921a 100644 --- a/database/connect.go +++ b/database/connect.go @@ -120,9 +120,9 @@ func GetTestDBHost() string { return host } -// ClearDatabase removes all the data from the given database. It's meant only +// DeleteAllIn removes all the data from the given database. It's meant only // for use in the tests. -func ClearDatabase(db *Handler) error { +func DeleteAllIn(db *Handler) error { _, err := db.DB.Exec("truncate table endentities;") return err } diff --git a/main_test.go b/main_test.go index cf5cacd3c..9330264cd 100644 --- a/main_test.go +++ b/main_test.go @@ -60,7 +60,7 @@ func newTestAutographer(t *testing.T) (*autographer, configuration) { MonitorPollInterval: 10 * time.Second, }) if err == nil { - database.ClearDatabase(db) + database.DeleteAllIn(db) } close(ag.exit) }) diff --git a/signer/contentsignaturepki/contentsignature_test.go b/signer/contentsignaturepki/contentsignature_test.go index 37ca3d73b..7380327a5 100644 --- a/signer/contentsignaturepki/contentsignature_test.go +++ b/signer/contentsignaturepki/contentsignature_test.go @@ -139,7 +139,7 @@ mpvOMOT3falDgXh0iOgdIA== input := []byte("foobarbaz1234abcd") for i, testcase := range testcases { - database.ClearDatabase(dbHandler) + database.DeleteAllIn(dbHandler) // initialize a signer s, err := New(testcase.cfg) @@ -462,10 +462,10 @@ func newTestDBHandler(t *testing.T) *database.Handler { t.Fatalf("db.CheckConnection failed when it should not have with error: %s", err) } - database.ClearDatabase(dbHandler) + database.DeleteAllIn(dbHandler) t.Cleanup(func() { - database.ClearDatabase(dbHandler) + database.DeleteAllIn(dbHandler) dbHandler.Close() }) return dbHandler From f2b58be29b99ea970b5ad9981344f6794848ff35 Mon Sep 17 00:00:00 2001 From: Jeff Hodges Date: Tue, 12 Nov 2024 09:34:43 -0800 Subject: [PATCH 11/13] revert accidental compose change --- docker-compose.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 511e8f856..b57b2319c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -97,6 +97,7 @@ services: unit-test: container_name: autograph-unit-test + image: autograph-app build: context: . environment: @@ -115,4 +116,7 @@ services: - db user: "0" working_dir: "/app/src/autograph/" - command: ["./bin/run_unit_tests.sh"] + command: + [ + "./bin/run_unit_tests.sh" + ] From f50efb529fcd5a84f9b7c8ce8e652d90e45adffa Mon Sep 17 00:00:00 2001 From: Jeff Hodges Date: Tue, 12 Nov 2024 09:35:38 -0800 Subject: [PATCH 12/13] put fakehsm lower --- .../contentsignature_test.go | 74 +++++++++---------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/signer/contentsignaturepki/contentsignature_test.go b/signer/contentsignaturepki/contentsignature_test.go index 7380327a5..c50c5586c 100644 --- a/signer/contentsignaturepki/contentsignature_test.go +++ b/signer/contentsignaturepki/contentsignature_test.go @@ -310,43 +310,6 @@ func TestReadRandFailureOnSignHash(t *testing.T) { } } -type fakeHSM struct { - slotToKeys map[string]crypto.PrivateKey -} - -// GetPrivateKey implements signer.HSM. -func (f *fakeHSM) GetPrivateKey(label []byte) (crypto.PrivateKey, error) { - key, ok := f.slotToKeys[string(label)] - if !ok { - return nil, fmt.Errorf("key not found") - } - return key, nil -} - -// GetRand implements signer.HSM. -func (f *fakeHSM) GetRand() io.Reader { - return rand.Reader -} - -// MakeKey creats a key but currently only makes P256 ecdsa kyes. -func (f *fakeHSM) MakeKey(keyTpl interface{}, keyName string) (crypto.PrivateKey, crypto.PublicKey, error) { - switch keyTpl.(type) { - case *ecdsa.PublicKey: - _, ok := f.slotToKeys[keyName] - if ok { - return nil, nil, fmt.Errorf("fakeHSM: key with name %q already exists", keyName) - } - priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) - if err != nil { - return nil, nil, fmt.Errorf("fakeHSM: failed to generate key: %v", err) - } - f.slotToKeys[keyName] = priv - return priv, priv.Public(), nil - default: - return nil, nil, fmt.Errorf("fakeHSM: making key of type %T is not supported", keyTpl) - } -} - // TestExistingEEKeyShouldWork is an attempt to mimic autograph booting up after // a restart with an existing EE key. That is, the first signer creates the EE // key in the HSM, and the second one should pick it up successfully. @@ -470,3 +433,40 @@ func newTestDBHandler(t *testing.T) *database.Handler { }) return dbHandler } + +type fakeHSM struct { + slotToKeys map[string]crypto.PrivateKey +} + +// GetPrivateKey implements signer.HSM. +func (f *fakeHSM) GetPrivateKey(label []byte) (crypto.PrivateKey, error) { + key, ok := f.slotToKeys[string(label)] + if !ok { + return nil, fmt.Errorf("key not found") + } + return key, nil +} + +// GetRand implements signer.HSM. +func (f *fakeHSM) GetRand() io.Reader { + return rand.Reader +} + +// MakeKey creats a key but currently only makes P256 ecdsa kyes. +func (f *fakeHSM) MakeKey(keyTpl interface{}, keyName string) (crypto.PrivateKey, crypto.PublicKey, error) { + switch keyTpl.(type) { + case *ecdsa.PublicKey: + _, ok := f.slotToKeys[keyName] + if ok { + return nil, nil, fmt.Errorf("fakeHSM: key with name %q already exists", keyName) + } + priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + return nil, nil, fmt.Errorf("fakeHSM: failed to generate key: %v", err) + } + f.slotToKeys[keyName] = priv + return priv, priv.Public(), nil + default: + return nil, nil, fmt.Errorf("fakeHSM: making key of type %T is not supported", keyTpl) + } +} From 2bef48480c2e022d6dbac2027702c8b64fed5f36 Mon Sep 17 00:00:00 2001 From: Jeff Hodges Date: Tue, 12 Nov 2024 10:48:05 -0800 Subject: [PATCH 13/13] add addDB to main_test.go set up Plus error handling --- main.go | 16 ++++++++-------- main_test.go | 16 ++++++++++++++++ 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/main.go b/main.go index 62870b34a..f044a2485 100644 --- a/main.go +++ b/main.go @@ -156,10 +156,13 @@ func run(conf configuration, listen string, debug bool) { ag = newAutographer(conf.Server.NonceCacheSize) ag.heartbeatConf = &conf.Heartbeat - if conf.Database.Name != "" { + if conf.Database.Name != "" || os.Getenv("AUTOGRAPH_DB_DSN") != "" { // ignore the monitor close chan since it will stop // when the app is stopped - _ = ag.addDB(conf.Database) + err = ag.addDB(conf.Database) + if err != nil { + log.Fatalf("main.run failed to add database: %s", err) + } } // initialize the hsm if a configuration is defined @@ -361,21 +364,18 @@ func (a *autographer) startCleanupHandler() { // addDB connects to the DB and starts a gorountine to monitor DB // connectivity -func (a *autographer) addDB(dbConf database.Config) chan bool { +func (a *autographer) addDB(dbConf database.Config) error { var err error a.db, err = database.Connect(dbConf) if err != nil { - log.Fatal(err) - } - if a.db == nil { - log.Fatal("failed to initialize database connection, unknown error") + return fmt.Errorf("failed to connect to database: %w", err) } // start a monitoring function that errors if the db // becomes inaccessible closeDBMonitor := make(chan bool, 1) go a.db.Monitor(dbConf.MonitorPollInterval, closeDBMonitor) log.Print("database connection established") - return closeDBMonitor + return nil } // initHSM sets up the HSM and notifies signers it is available diff --git a/main_test.go b/main_test.go index 9330264cd..af4c65d1c 100644 --- a/main_test.go +++ b/main_test.go @@ -25,6 +25,22 @@ func newTestAutographer(t *testing.T) (*autographer, configuration) { log.Fatal(err) } ag := newAutographer(1) + // FIXME refactor helper + host := database.GetTestDBHost() + err = ag.addDB(database.Config{ + Name: "autograph", + User: "myautographdbuser", + Password: "myautographdbpassword", + Host: host + ":5432", + MonitorPollInterval: 10 * time.Second, + }) + if err != nil { + log.Fatalf("newTestAutographer: failed to connect to db: %s", err) + } + err = database.DeleteAllIn(ag.db) + if err != nil { + log.Fatalf("newTestAutographer: failed to delete all in db %s", err) + } err = ag.addSigners(conf.Signers) if err != nil { log.Fatal(err)