diff --git a/.github/acme2certifier.pem b/.github/acme2certifier.pem index 6d15eeaa..1d2438e2 100644 --- a/.github/acme2certifier.pem +++ b/.github/acme2certifier.pem @@ -26,29 +26,31 @@ y9EOGEZMZAIwdzOlHqaFt937o0dqNy2tY1VQ9YtpJ234JbS2whG8PjoqMeTMmgDG jhv3T8V79bS/dQ3eiFdqtgHnDzjfCV/4LSBsDGRHOSHU2qxXiETTfT4= -----END RSA PRIVATE KEY----- -----BEGIN CERTIFICATE----- -MIIESzCCAjOgAwIBAgIIfsWXGpYTi+8wDQYJKoZIhvcNAQELBQAwETEPMA0GA1UE -AxMGc3ViLWNhMB4XDTIzMDcxNjE1MzYwMFoXDTI0MDcxNTE1MzYwMFowEzERMA8G -A1UEAwwIYWNtZV9zcnYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCz -IvzlRkotxA+eHQrwe8Zy/yoFXv3kSPwkDPSYJ0QueyTk5WQq/DcPPuWpszn99OR7 -CGYe+Wy22KvLEwIR6VZmFByCDnWD7t03FFN1iNhH+ECU1FIDBdWD1LfJ4/ZdiKT7 -w7rNghivvm+YtvqkMXtFaWkVaUIu44IYdZDXsnFNR5ACWJGmdGxkhJwH28f6dQUw -JgyBUKbvP28Y8Q6+eCavLFsZad2Oq9xh8HO8Qb+jFGA2OdzhTd+PrEU0fy9pVSzB -XLyrzcKa0PUlt69IL0YzZyPpN0sO3Xvgv7AyvUrwZJlbz+K6vs1u5ZQP5Y/1f2fn -Jt1ozflpIuBKKG2iOEVTAgMBAAGjgaQwgaEwDAYDVR0TAQH/BAIwADAWBgNVHSUB -Af8EDDAKBggrBgEFBQcDATBGBgNVHREEPzA9gghhY21lX3NydoINYWNtZV9zcnYu -YWNtZYIJbG9jYWxob3N0gghhY21lLXNydoINYWNtZS1zcnYuYWNtZTARBglghkgB -hvhCAQEEBAMCBkAwHgYJYIZIAYb4QgENBBEWD3hjYSBjZXJ0aWZpY2F0ZTANBgkq -hkiG9w0BAQsFAAOCAgEAZ9xErDtqOtf4tXcZC5kpV+PzEfj6iI17r94Z4aGb6plv -2LXFcldwrNe+wyvpaMLgyAgei1eIWKUw4aknHJwcymYxWkV+YEkUW0q43NztA6oY -o7zJDX9ltIlmnbWP+Sqpe051Ln5uoTjc6xvD61EEdYAu/eInT+lsQHTjhxbCtSkk -twYoeiXXI34PHSQqahuVRT8DThuMsxNC7v8eRKfbvCRAv1obD+KDE2P4YvIqy1Lc -HwHV7X6ipcYDTCDv9dCoLSer1pTidZGGtTbSA8KVlaPgWV405m3gROkxSDPuuFgN -5y2oTxQIdKsFtT2iIJj0gbzk3SduVQ4OPEnM1x800HmTRdzJbv83IswoSEt30nkZ -v1+fKtVokxJA9IliciUdvmoSs806G/4tRTfwK2eHhZjfvbotG5uCshRSvHEHuDlb -HLcv34h07nKh1QhDjurf6EIpk2Z6b7tQCprNMoVFiACYX6h524ZkB4pvhvF8i5Rt -HESu0iuxUZk49OsheOl5V/SqHMhr2fFKSqSgBdDRrthpE1MvHdYzBLT7xGm1oxK0 -40et7iEqScSxbI5ic6WG6rJ5pZeqp9cjDdTvM194EMPgmhc8UqN8nkpIeJ0yBZC1 -ve1n0pi6S0TuaVlTo71wX49YwFEq/z3nbjIzi0YYmlmRAYjffE7px4b0a3VDLQA= +MIIEkDCCAnigAwIBAgIINem9Fn3yI2cwDQYJKoZIhvcNAQELBQAwKjEXMBUGA1UE +CxMOYWNtZTJjZXJ0aWZpZXIxDzANBgNVBAMTBnN1Yi1jYTAeFw0yNDA3MjMwNjE2 +MDBaFw0yNjA3MjMwNjE2MDBaMBMxETAPBgNVBAMMCGFjbWVfc3J2MIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsyL85UZKLcQPnh0K8HvGcv8qBV795Ej8 +JAz0mCdELnsk5OVkKvw3Dz7lqbM5/fTkewhmHvlsttiryxMCEelWZhQcgg51g+7d +NxRTdYjYR/hAlNRSAwXVg9S3yeP2XYik+8O6zYIYr75vmLb6pDF7RWlpFWlCLuOC +GHWQ17JxTUeQAliRpnRsZIScB9vH+nUFMCYMgVCm7z9vGPEOvngmryxbGWndjqvc +YfBzvEG/oxRgNjnc4U3fj6xFNH8vaVUswVy8q83CmtD1JbevSC9GM2cj6TdLDt17 +4L+wMr1K8GSZW8/iur7NbuWUD+WP9X9n5ybdaM35aSLgSihtojhFUwIDAQABo4HQ +MIHNMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFCBBm1m0llstSbjZx9CypR7hfh0I +MAsGA1UdDwQEAwIEsDAWBgNVHSUBAf8EDDAKBggrBgEFBQcDATBGBgNVHREEPzA9 +gghhY21lX3NydoINYWNtZV9zcnYuYWNtZYIJbG9jYWxob3N0gghhY21lLXNydoIN +YWNtZS1zcnYuYWNtZTARBglghkgBhvhCAQEEBAMCB4AwHgYJYIZIAYb4QgENBBEW +D3hjYSBjZXJ0aWZpY2F0ZTANBgkqhkiG9w0BAQsFAAOCAgEAgKxcS2L507h+c7XD +14oY4xbGcuGd/4RPKHz7VV5xxybZHGHjJ+WAq5Hd89FqjkaZ6gBB4hfpHqXMLPv2 +aFX9mXoW5ilH1BGZAEn3xMefdfkrnqCAvr3iKFasmqdTQovyVBEUsE6Zb2A5rhA9 +yWoHPBkcMhP5XYkGVaCWfOh5XUrt6HAD0+wJPb57nxBXRctJK5aF/Jl/tFoJrUVg +t9penQ3TuVnZqdFI5ofwR/DUZIGqoTRjatAjwHgg5yc07erwMuu0nhqAINVlQm7v +phgc2gkXXwcsAQvlRcY5017cHB9IDYsEczVh0DHdhWNvkcKvIqoO8sx+3Thi6wzb +/pnvbq1T8C59YhCk5MkmQXMKyvI5ik+sY+aDtVsyc9+G6A9qhU7BL7stFI/tuFwA +KVsqeDVPv/QYXleV/Ys3WqbxXrLRJv8qWpxEKIE3TKCJYUg6LOBPNmR2VtWEaBoA +ItkUNm1UHbbidCMo9nZqupzeyVC0RcXrwfBNqONT9B90AvRnyHqlIuVY6LZKIEfi +rSUzyL8eGON5wXv/dPr7fUqrzAFWTn3eLhh+KXY9a1e5uK95T2A7/kOuDoIAlM0v +ueREv5XaK2dp7M1yynzlGxRAtDWtify1W2p1TOMQoI+SpB5bWJ8jP9N0CR5m8Q4I +/oPqgSi1uZzgN2kOOSLkZcy8QUE= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFTzCCAzegAwIBAgIIAzHyhSyrXfMwDQYJKoZIhvcNAQELBQAwKzEXMBUGA1UE diff --git a/.github/acme2certifier_cabundle.pem b/.github/acme2certifier_cabundle.pem index bfafedca..45f865f4 100644 --- a/.github/acme2certifier_cabundle.pem +++ b/.github/acme2certifier_cabundle.pem @@ -1,61 +1,64 @@ -----BEGIN CERTIFICATE----- -MIIFHjCCAwagAwIBAgIIcFUYZLICUHowDQYJKoZIhvcNAQELBQAwEjEQMA4GA1UE -AxMHcm9vdC1jYTAeFw0yMDA2MDkxNzE4MDBaFw0zMDA2MDkxNzE3MDBaMBExDzAN -BgNVBAMTBnN1Yi1jYTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAO2x -CXITgVcFJuqh5ibdBUwaNJgI3lBmG2aLjvIaBXbH3ocH6WsXO1d5i37PepArmTpG -fd+Ew3FvUmyiPzFO3WJSwgk096yoLVQHwAcxyuy1dBXemGFBm3v5ofTK+MyINxJP -PkRWbJLhSETofzCo/vbFkBqIkFoarh8uEwfxzhpDq3cWjROaJhHhT+6GsbDMGouL -za9J1HVs4Fn5fkmFxB9g7st5Z19TVIKCisPP4VQNmbhaWuHJMkaXDkaVAUcw6QQy -quwfdl78jndh14D8tFuoLZcRxT/cfQPmqhcjjkkTelMk/5OfYlk+1wjoAEToXDzG -HTkXS/zkGMdZeZFstXAFhy0THlSMO5RTuKwSXxIObvKKM2WdNVpnYOD5XaZnvFJx -5fQu13HiNrprQKQAssihKqz9iCeJ0xuwuIydkrmjXSU0KtyzSZXBgaaMSeRYx+dG -hVfv1f6U+MQjBq+QEbkuafcFs3TnuRcbbWA4H+T4cJK3krg9m9s1P2tTAFYuNDAR -Df6IgPPyeSglcMpKPqg7uZWR5e/0wQj29XLUgrkFoIPsLEML6aKTMOdiCUcdAdne -mkwcB7JIth+HAeSjNpW1lRb14QNxbf52qxN0X8HsDNYmg++rxxOOwEMzYuo7Ch1C -lzI0RGaRHHbkWymj+doyXvVwnV4ZZwRXXpeJmhmTAgMBAAGjeTB3MBIGA1UdEwEB -/wQIMAYBAf8CAQEwHQYDVR0OBBYEFIMnznmJq0PWTssJTOYznKF7gjN4MB8GA1Ud -IwQYMBaAFL/OiI9h7taWfyqsHzQwwiq3NBvOMA4GA1UdDwEB/wQEAwIBBjARBglg -hkgBhvhCAQEEBAMCAAcwDQYJKoZIhvcNAQELBQADggIBAJMwQ33+tL2yO+tePbDZ -b5ZiASeAI6FmHWLtTpx3YeDBXR1NFtMGR1jYiWO5Mc6BAmLC2KPevXt+VM7RWeQU -PlMKfcbxX5XdrhMWyC0HSvGQtg0/Ftc6do8Mj3wOIrmlskJPDX9s4VT0ersabRdZ -2Djkcyub5PipMcJcPR7IpnfLJLcK1/QxrAHZtdseUuOyvXelAoPWTPLk4uMxEzGk -lTDhqjCzVc3+sRJOwV9QQopOX3tB5vijAzC96jrRj90UNDZBt9IJu0sBIYro/a9O -AqxFbQXcsr6rUZgvktWgghqJOai/iidTCA0TM4SqJUuaok4guJmMTGc8mJZ+EfmV -8JPJ/8OaP2KU2VcMDzqN4/KeZt7+tfG7GB3h6l3D7M/q8qkSYYo2nzQ405EB/KVY -ohhw85RcJw3zqnziFuTmTTSqu4zOLlGFwSri7VgH3JfmgGWmjQ6B8wP3V0jKydFb -JaIM4PLPRZeCHfexJ3Iu2a174saShxBwBsfCVah+9j6PJ8Pvx8LzPW+WeyW56NpF -FamwsJJKqafvBMuZPjCR+burDPJh9Y7IrPZNDsgmBcUzB9BCxB1Qlj4fdkieuHJM -5m6jaOeUlnECprkyutyh5lEY0BVw5RO+v9SqtI/6cbFrclMcb1SpF5W0slEX3xTG -02BvBlCOKrZlqnp/jSdmAZ9s +MIIFTzCCAzegAwIBAgIIAzHyhSyrXfMwDQYJKoZIhvcNAQELBQAwKzEXMBUGA1UE +CxMOYWNtZTJjZXJ0aWZpZXIxEDAOBgNVBAMTB3Jvb3QtY2EwHhcNMjAwNTI3MTM1 +NDAwWhcNMzAwNTI2MjM1OTAwWjAqMRcwFQYDVQQLEw5hY21lMmNlcnRpZmllcjEP +MA0GA1UEAxMGc3ViLWNhMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA +xXHaGZsolXe+PBdUryngHP9VbBC1mehqeTtYI+hqsqGNH7q9a7bSrxMwFuF1kYL8 +jqqxkJdtl0L94xcxJg/ZdMx7Nt0vGI+BaAuTpEpUEHeN4tqS6NhB/m/0LGkAELc/ +qkzmoO4B1FDwEEj/3IXtZcupqG80oDt7jWSGXdtF7NTjzcumznMeRXidCdhxRxT/ +/WrsChaytXo0xWZ56oeNwd6x6Dr8/39PBOWtj4fldyDcg+Q+alci2tx9pxmu2bCV +XcB9ftCLKhDk2WEHE88bgKSp7fV2RCmq9po+Tx8JJ7qecLunUsK/F0XN4kpoQLm9 +hcymqchnMSncSiyin1dQHGHWgXDtBDdq6A2Z6rx26Qk5H9HTYvcNSe1YwFEDoGLB +ZQjbCPWiaqoaH4agBQTclPvrrSCRaVmhUSO+pBtSXDkmN4t3MDZxfgRkp8ixwkB1 +5Y5f0LTpCyAJsdQDw8+Ea0aDqO30eskh4CErnm9+Fejd9Ew2cwpdwfBXzVSbYilM +GueQihZHvJmVRxAwU69aO2Qs8B0tQ60CfWKVlmWPiakrvYYlPp0FBsM61G6LZEN8 +hH2CKnS8hHv5IWEXZvp0Pk8V3P5h6bWN0Tl+x/V1Prt7Wp8NoiPETE8XyDDxe6dm +KxztWBH/mTsJyMGb6ZiUoXdPU9TFUKqHxTRLHaxfsPsCAwEAAaN4MHYwEgYDVR0T +AQH/BAgwBgEB/wIBATAdBgNVHQ4EFgQUv96OjgYiIqutQ8jd1E+oq0hBPtUwDgYD +VR0PAQH/BAQDAgGGMBEGCWCGSAGG+EIBAQQEAwIABzAeBglghkgBhvhCAQ0EERYP +eGNhIGNlcnRpZmljYXRlMA0GCSqGSIb3DQEBCwUAA4ICAQBbHLEVyg4f9uEujroc +31UVyDRLMdPgEPLjOenSBCBmH0N81whDmxNI/7JAAB6J14WMX8OLF0HkZnb7G77W +vDhy1aFvQFbXHBz3/zUO9Mw9J4L2XEW6ond3Nsh1m2oXeBde3R3ANxuIzHqZDlP9 +6YrRcHjnf4+1/5AKDJAvJD+gFb5YnYUKH2iSvHUvG17xcZx98Rf2eo8LealG4JqH +Jh4sKRy0VjDQD7jXSCbweTHEb8wz+6OfNGrIo+BhTFP5vPcwE4nlJwYBoaOJ5cVa +7gdQJ7WkLSxvwHxuxzvSVK73u3jl3I9SqTrbMLG/jeJyV0P8EvdljOaGnCtQVRwC +zM4ptXUvKhKOHy7/nyTF/Bc35ZwwL/2xWvNK1+NibgE/6CFxupwWpdmxQbVVuoQ3 +2tUil9ty0yC6m5GKE8+t1lrZuxyA+b/TBnYNO5xo8UEMbkpxaNYSwmw+f/loxXP/ +M7sIBcLvy2ugHEBxwd9o/kLXeXT2DaRvxPjp4yk8MpJRpNmz3aB5HJwaUnaRLVo5 +Z3XWWXmjMGZ6/m0AAoDbDz/pXtOoJZT8BJdD1DuDdszVsQnLVn4B/LtIXL6FbXsF +zfv6ERP9a5gpKUZ+4NjgrnlGtdccNZpwyWF0IXcvaq3b8hXIRO4hMjzHeHfzJN4t +jX1vlY35Ofonc4+6dRVamBiF9A== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIFHzCCAwegAwIBAgIISRJolCjaE+8wDQYJKoZIhvcNAQELBQAwEjEQMA4GA1UE -AxMHcm9vdC1jYTAeFw0yMDA2MDkxNzE3MDBaFw0zMDA2MDkxNzE3MDBaMBIxEDAO -BgNVBAMTB3Jvb3QtY2EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDk -UX6DpcKks9qIbIstBjYvDAcU0hvypQwILvDpCFSy9uZ8SO9PRSfK0ltxljmu3ESS -62OuGO8s9+HJm7rxkXVX6YttnYU60KrlmiRS9Js0BRj2jfL4E4ydNc6cIE4perh9 -3ydQJmaS16KiNmEC+XE/5mBpI4qQrRm2obYOloyxShFc3CzsJe55iyhtclZf1L/6 -JNgc3t6Q4RGiGnvXv2nJOI0BnnC9QY0DtZITuXK/43RES08MEizgpsTJz0QQ2ugJ -FJa5SzbPC8f1hzTYctB7LLPc6nFpECESZ4zplAu/5ruD/7jtkwNBWeGo+kPCkyHx -AL/XQH42VpM8iQbN61CWboV4ibYhP9/ko1oyM5UV5+UPqYEsao4MSJ3oblQEFHta -SrOsy7Z6ZXW0eYK8Z/iYjXZ2wSskJis3K7sh/9oPrm1jlAXwpEGsJlE6xobrnWHz -5c3/PxNvKj3U5jdiJhVcJxvMFpHL5fLqLQU4aXwsZIvPOyM7wZyLrmWbkzvmcg2t -4TWwJSlVf2QGIZ4C8HsXnZJoM+GhVMGJpNJAJ7XzmI6ExmCwEcBbfkPQXHuB9hGb -fRQRRR+/eXXjU62VyxpbwWNygxHsigV3bc1GGwK613Y9t5l1I4DMTB150dliNT7f -+nWzsA3GdBTj/frBOclVjXRLqt5sE/SvMkHwYd7+7QIDAQABo3kwdzASBgNVHRMB -Af8ECDAGAQH/AgECMB0GA1UdDgQWBBS/zoiPYe7Wln8qrB80MMIqtzQbzjAfBgNV -HSMEGDAWgBS/zoiPYe7Wln8qrB80MMIqtzQbzjAOBgNVHQ8BAf8EBAMCAQYwEQYJ -YIZIAYb4QgEBBAQDAgAHMA0GCSqGSIb3DQEBCwUAA4ICAQCkJd69cYr4CKechyDM -TGivDBmqmEt3WDo5jNSbckJ+4gSUD+TcSfyUqXbKGAM5d9unZrnDLfh256IsYyyz -oAkzDi5LhS2umKK6cc5XyZFZ6c6JwYfwjw3+7GMSKrzLPwCqQYcJjjs/W9OppKkB -mWwsDA6H5124sQLeHFwFYmjm2LFlNZ+tsYsAPJVmxFnodLjOPEbbFbrDHq5fgbd+ -VKfC9UCXd7OuP6J2MQ6D8SEaynWKp/PsXHk4xAzMrRdg3UjvHMLEcuQXzogzy84V -1gYTMrrLDPg/wXCzUM1lZbHhFriQAWXGCDu3tpr1yS08K7YayHo32QbSMzfXnWCp -LhAV2AI5DA9lBJ8O6ImyNyIm0xiWbiofBmEUw0MaKgTRWWMnIFvLgZH70PJOZw9o -dIHPnXy0aLYm/6jePIg/MYmGW4+3LJMG9AmA3QgzFEvJUIT4NFxh0eNOCEh9cmoz -oISMy0toJRm7YbY2AvtuKoEASWkAyHgPaF7NDvHCqySXTsxzE5O+hiFp3X1byiRm -csixfvC0BVYX4CpxLWUX8Et3mrv42Pd/ZtxtCpwv0G5w+X4OAlOg1DBX5gsf1i+3 -YIIt3y0Bsw1UsRSRgUvaMZCWvKOtCfBYc5HjLS74RijIm9OaiDc2LDQOUloiT3xd -pLo0ga8P7AMdeSpyJF1qdsTqxA== +MIIFcDCCA1igAwIBAgIIevLTTxOMoZgwDQYJKoZIhvcNAQELBQAwKzEXMBUGA1UE +CxMOYWNtZTJjZXJ0aWZpZXIxEDAOBgNVBAMTB3Jvb3QtY2EwHhcNMjAwNTI3MDAw +MDAwWhcNMzAwNTI2MjM1OTU5WjArMRcwFQYDVQQLEw5hY21lMmNlcnRpZmllcjEQ +MA4GA1UEAxMHcm9vdC1jYTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB +AJy4UZHdZgYt64k/rFamoC676tYvtabeuiqVw1c6oVZI897cFLG6BYwyr2Eaj7tF +rqTJDeMN4vZSudLsmLDq6m8KwX/riPzUTIlcjM5aIMANZr9rLEs3NWtcivolB5aQ +1slhdVitUPLuxsFnYeQTyxFyP7lng9M/Z403KLG8phdmKjM0vJkaj4OuKOXf3UsW +qWQYyRl/ms07xVj02uq08LkoeO+jtQisvyVXURdaCceZtyK/ZBQ7NFCsbK112cVR +1e2aJol7NJAA6Wm6iBzAdkAA2l3kh40SLoEbaiaVMixLN2vilIZOOAoDXX4+T6ir ++KnDVSJ2yu5c/OJMwuXwHrh7Lgg1vsFR5TNehknhjUuWOUO+0TkKPg2A7KTg72OZ +2mOcLZIbxzr1P5RRvdmLQLPrTF2EJvpQPNmbXqN3ZVWEvfHTjkkTFY/dsOTvFTgS +ri15zYKch8votcU7z+BQhgmMtwO2JhPMmZ6ABd9skI7ijWpwOltAhxtdoBO6T6CB +CrE2yXc6V/PyyAKcFglNmIght5oXsnE+ub/dtx8f9Iea/xNPdo5aGy8fdaitolDK +16kd3Kb7OE4HMHIwOxxF1BEAqerxxhbLMRBr8hRSZI5cvLzWLvpAQ5zuhjD6V3b9 +BYFd4ujAu3zl3mbzdbYjFoGOX6aBZaGDxlc4O2W7HxntAgMBAAGjgZcwgZQwDwYD +VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUDGVvuTFYZtEAkz3af9wRKDDvAswwHwYD +VR0jBBgwFoAUDGVvuTFYZtEAkz3af9wRKDDvAswwDgYDVR0PAQH/BAQDAgGGMBEG +CWCGSAGG+EIBAQQEAwIABzAeBglghkgBhvhCAQ0EERYPeGNhIGNlcnRpZmljYXRl +MA0GCSqGSIb3DQEBCwUAA4ICAQAjko7dX+iCgT+m3Iy1Vg6j7MRevPAzq1lqHRRN +Ndt2ct530pIut7Fv5V2xYk35ka+i/G+XyOvTXa9vAUKiBtiRnUPsXu4UcS7CcrCX +EzHx4eOtHnp5wDhO0Fx5/OUZTaP+L7Pd1GD/j953ibx5bMa/M9Rj+S486nst57tu +DRmEAavFDiMd6L3jH4YSckjmIH2uSeDIaRa9k6ag077XmWhvVYQ9tuR7RGbSuuV3 +Fc6pqcFbbWpoLhNRcFc+hbUKOsKl2cP+QEKP/H2s3WMllqgAKKZeO+1KOsGo1CDs +475bIXyCBpFbH2HOPatmu3yZRQ9fj9ta9EW46n33DFRNLinFWa4WJs4yLVP1juge +2TCOyA1t61iy++RRXSG3e7NFYrEZuCht1EdDAdzIUY89m9NCPwoDYS4CahgnfkkO +7YQe6f6yqK6isyf8ZFcp1uF58eERDiF/FDqS8nLmCdURuI56DDoNvDpig5J/9RNW +G8vEvt2p7QrjeZ3EAatx5JuYty/NKTHZwJWk51CgzEgzDwzE2JIiqeldtL5d0Sl6 +eVuv0G04BEyuXxEWpgVVzBS4qEFIBSnTJzgu1PXmId3yLvg2Nr8NKvwyZmN5xKFp +0A9BWo15zW1PXDaD+l39oTYD7agjXkzTAjYIcfNJ7ATIYFD0xAvNAOf70s7aNupF +fvkG2Q== -----END CERTIFICATE----- diff --git a/.github/acme2certifier_cert.pem b/.github/acme2certifier_cert.pem index 3db631bf..5ee3cdbf 100644 --- a/.github/acme2certifier_cert.pem +++ b/.github/acme2certifier_cert.pem @@ -1,25 +1,27 @@ -----BEGIN CERTIFICATE----- -MIIESzCCAjOgAwIBAgIIfsWXGpYTi+8wDQYJKoZIhvcNAQELBQAwETEPMA0GA1UE -AxMGc3ViLWNhMB4XDTIzMDcxNjE1MzYwMFoXDTI0MDcxNTE1MzYwMFowEzERMA8G -A1UEAwwIYWNtZV9zcnYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCz -IvzlRkotxA+eHQrwe8Zy/yoFXv3kSPwkDPSYJ0QueyTk5WQq/DcPPuWpszn99OR7 -CGYe+Wy22KvLEwIR6VZmFByCDnWD7t03FFN1iNhH+ECU1FIDBdWD1LfJ4/ZdiKT7 -w7rNghivvm+YtvqkMXtFaWkVaUIu44IYdZDXsnFNR5ACWJGmdGxkhJwH28f6dQUw -JgyBUKbvP28Y8Q6+eCavLFsZad2Oq9xh8HO8Qb+jFGA2OdzhTd+PrEU0fy9pVSzB -XLyrzcKa0PUlt69IL0YzZyPpN0sO3Xvgv7AyvUrwZJlbz+K6vs1u5ZQP5Y/1f2fn -Jt1ozflpIuBKKG2iOEVTAgMBAAGjgaQwgaEwDAYDVR0TAQH/BAIwADAWBgNVHSUB -Af8EDDAKBggrBgEFBQcDATBGBgNVHREEPzA9gghhY21lX3NydoINYWNtZV9zcnYu -YWNtZYIJbG9jYWxob3N0gghhY21lLXNydoINYWNtZS1zcnYuYWNtZTARBglghkgB -hvhCAQEEBAMCBkAwHgYJYIZIAYb4QgENBBEWD3hjYSBjZXJ0aWZpY2F0ZTANBgkq -hkiG9w0BAQsFAAOCAgEAZ9xErDtqOtf4tXcZC5kpV+PzEfj6iI17r94Z4aGb6plv -2LXFcldwrNe+wyvpaMLgyAgei1eIWKUw4aknHJwcymYxWkV+YEkUW0q43NztA6oY -o7zJDX9ltIlmnbWP+Sqpe051Ln5uoTjc6xvD61EEdYAu/eInT+lsQHTjhxbCtSkk -twYoeiXXI34PHSQqahuVRT8DThuMsxNC7v8eRKfbvCRAv1obD+KDE2P4YvIqy1Lc -HwHV7X6ipcYDTCDv9dCoLSer1pTidZGGtTbSA8KVlaPgWV405m3gROkxSDPuuFgN -5y2oTxQIdKsFtT2iIJj0gbzk3SduVQ4OPEnM1x800HmTRdzJbv83IswoSEt30nkZ -v1+fKtVokxJA9IliciUdvmoSs806G/4tRTfwK2eHhZjfvbotG5uCshRSvHEHuDlb -HLcv34h07nKh1QhDjurf6EIpk2Z6b7tQCprNMoVFiACYX6h524ZkB4pvhvF8i5Rt -HESu0iuxUZk49OsheOl5V/SqHMhr2fFKSqSgBdDRrthpE1MvHdYzBLT7xGm1oxK0 -40et7iEqScSxbI5ic6WG6rJ5pZeqp9cjDdTvM194EMPgmhc8UqN8nkpIeJ0yBZC1 -ve1n0pi6S0TuaVlTo71wX49YwFEq/z3nbjIzi0YYmlmRAYjffE7px4b0a3VDLQA= +MIIEkDCCAnigAwIBAgIINem9Fn3yI2cwDQYJKoZIhvcNAQELBQAwKjEXMBUGA1UE +CxMOYWNtZTJjZXJ0aWZpZXIxDzANBgNVBAMTBnN1Yi1jYTAeFw0yNDA3MjMwNjE2 +MDBaFw0yNjA3MjMwNjE2MDBaMBMxETAPBgNVBAMMCGFjbWVfc3J2MIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsyL85UZKLcQPnh0K8HvGcv8qBV795Ej8 +JAz0mCdELnsk5OVkKvw3Dz7lqbM5/fTkewhmHvlsttiryxMCEelWZhQcgg51g+7d +NxRTdYjYR/hAlNRSAwXVg9S3yeP2XYik+8O6zYIYr75vmLb6pDF7RWlpFWlCLuOC +GHWQ17JxTUeQAliRpnRsZIScB9vH+nUFMCYMgVCm7z9vGPEOvngmryxbGWndjqvc +YfBzvEG/oxRgNjnc4U3fj6xFNH8vaVUswVy8q83CmtD1JbevSC9GM2cj6TdLDt17 +4L+wMr1K8GSZW8/iur7NbuWUD+WP9X9n5ybdaM35aSLgSihtojhFUwIDAQABo4HQ +MIHNMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFCBBm1m0llstSbjZx9CypR7hfh0I +MAsGA1UdDwQEAwIEsDAWBgNVHSUBAf8EDDAKBggrBgEFBQcDATBGBgNVHREEPzA9 +gghhY21lX3NydoINYWNtZV9zcnYuYWNtZYIJbG9jYWxob3N0gghhY21lLXNydoIN +YWNtZS1zcnYuYWNtZTARBglghkgBhvhCAQEEBAMCB4AwHgYJYIZIAYb4QgENBBEW +D3hjYSBjZXJ0aWZpY2F0ZTANBgkqhkiG9w0BAQsFAAOCAgEAgKxcS2L507h+c7XD +14oY4xbGcuGd/4RPKHz7VV5xxybZHGHjJ+WAq5Hd89FqjkaZ6gBB4hfpHqXMLPv2 +aFX9mXoW5ilH1BGZAEn3xMefdfkrnqCAvr3iKFasmqdTQovyVBEUsE6Zb2A5rhA9 +yWoHPBkcMhP5XYkGVaCWfOh5XUrt6HAD0+wJPb57nxBXRctJK5aF/Jl/tFoJrUVg +t9penQ3TuVnZqdFI5ofwR/DUZIGqoTRjatAjwHgg5yc07erwMuu0nhqAINVlQm7v +phgc2gkXXwcsAQvlRcY5017cHB9IDYsEczVh0DHdhWNvkcKvIqoO8sx+3Thi6wzb +/pnvbq1T8C59YhCk5MkmQXMKyvI5ik+sY+aDtVsyc9+G6A9qhU7BL7stFI/tuFwA +KVsqeDVPv/QYXleV/Ys3WqbxXrLRJv8qWpxEKIE3TKCJYUg6LOBPNmR2VtWEaBoA +ItkUNm1UHbbidCMo9nZqupzeyVC0RcXrwfBNqONT9B90AvRnyHqlIuVY6LZKIEfi +rSUzyL8eGON5wXv/dPr7fUqrzAFWTn3eLhh+KXY9a1e5uK95T2A7/kOuDoIAlM0v +ueREv5XaK2dp7M1yynzlGxRAtDWtify1W2p1TOMQoI+SpB5bWJ8jP9N0CR5m8Q4I +/oPqgSi1uZzgN2kOOSLkZcy8QUE= -----END CERTIFICATE----- \ No newline at end of file diff --git a/.github/actions/acme_clients/action.yml b/.github/actions/acme_clients/action.yml new file mode 100644 index 00000000..230527de --- /dev/null +++ b/.github/actions/acme_clients/action.yml @@ -0,0 +1,464 @@ +name: "acme_clients - enroll, renew and revoke certificates" +description: "Test if acme.sh, certbot and lego can enroll, renew and certificates" +inputs: + ACME_SERVER: + description: "ACME server URL" + required: true + default: "acme-srv" + REVOCATION: + description: "Revocation method" + required: true + default: "true" + RENEWAL: + description: "Renewal method" + required: true + default: "true" + VERIFY_CERT: + description: "Verify certificate" + required: true + default: "true" + USE_CERTBOT: + description: "Use certbot" + required: true + default: "true" + USE_RSA: + description: "Use RSA" + required: true + default: "false" + HTTP_PORT: + description: "HTTP port" + required: true + default: "80" + HTTPS_PORT: + description: "HTTPS port" + required: true + default: "443" + HOSTNAME_SUFFIX: + description: "Hostname suffix" + required: true + NAME_SPACE: + description: "Namespace" + required: true + default: "acme" + +runs: + using: "composite" + steps: + + - name: "Create directories" + run: | + mkdir -p acme-sh/ + sudo mkdir -p certbot/ + sudo mkdir -p lego/ca + sudo cp .github/acme2certifier_cabundle.pem certbot/ + sudo cp .github/acme2certifier_cabundle.pem lego/ + if [ -f cert-2.pem ]; then + echo "delete cert-2.pem" + rm -f cert-2.pem + fi + if [ -f cert-1.pem ]; then + echo "delete cert-1.pem" + rm -f cert-1.pem + fi + ls -la + shell: bash + + - name: "Sleep for 5s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 5s + + - name: "Test if http://acme-srv/directory is accessible" + run: docker run -i --rm --network $NAME_SPACE curlimages/curl -f http://$ACME_SERVER:$HTTP_PORT/directory + shell: bash + env: + ACME_SERVER: ${{ inputs.ACME_SERVER }} + HTTP_PORT: ${{ inputs.HTTP_PORT }} + HTTPS_PORT: ${{ inputs.HTTPS_PORT }} + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "Test if https://acme-srv/directory is accessible" + run: docker run -i --rm --network $NAME_SPACE curlimages/curl --insecure -f https://$ACME_SERVER:$HTTPS_PORT/directory + shell: bash + env: + ACME_SERVER: ${{ inputs.ACME_SERVER }} + HTTP_PORT: ${{ inputs.HTTP_PORT }} + HTTPS_PORT: ${{ inputs.HTTPS_PORT }} + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "HTTP - Enroll lego" + run: | + echo "##### HTTP - Enroll lego #####" + if [ "$USE_RSA" == "false" ]; then + echo "use ECC" + docker run -i --rm -e LEGO_CA_CERTIFICATES=.lego/acme2certifier_cabundle.pem -v $PWD/lego:/.lego/ --name lego$HOSTNAME_SUFFIX --network $NAME_SPACE goacme/lego -s http://$ACME_SERVER:$HTTP_PORT -a --email "lego@example.com" -d lego$HOSTNAME_SUFFIX.$NAME_SPACE --tls run + else + echo "use RSA" + docker run -i --rm -e LEGO_CA_CERTIFICATES=.lego/acme2certifier_cabundle.pem -v $PWD/lego:/.lego/ --name lego$HOSTNAME_SUFFIX --network $NAME_SPACE goacme/lego -s http://$ACME_SERVER:$HTTP_PORT -a --email "lego@example.com" --key-type=rsa2048 -d lego$HOSTNAME_SUFFIX.$NAME_SPACE --tls run + fi + shell: bash + env: + ACME_SERVER: ${{ inputs.ACME_SERVER }} + HTTP_PORT: ${{ inputs.HTTP_PORT }} + HTTPS_PORT: ${{ inputs.HTTPS_PORT }} + USE_RSA: ${{ inputs.USE_RSA }} + HOSTNAME_SUFFIX: ${{ inputs.HOSTNAME_SUFFIX }} + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "HTTP - Revoke lego" + if: ${{ inputs.REVOCATION == 'true' }} + run: | + echo "#### HTTP - Revoke lego" + docker run -i -v $PWD/lego:/.lego/ --rm --name lego$HOSTNAME_SUFFIX --network $NAME_SPACE goacme/lego -s http://$ACME_SERVER:$HTTP_PORT -a --email "lego@example.com" -d lego$HOSTNAME_SUFFIX.$NAME_SPACE revoke + shell: bash + env: + ACME_SERVER: ${{ inputs.ACME_SERVER }} + HTTP_PORT: ${{ inputs.HTTP_PORT }} + HTTPS_PORT: ${{ inputs.HTTPS_PORT }} + HOSTNAME_SUFFIX: ${{ inputs.HOSTNAME_SUFFIX }} + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "HTTPS - Enroll acme.sh" + run: | + echo "##### HTTPS - Enroll acme.sh #####" + if [ "$USE_RSA" == "false" ]; then + echo "use ECC" + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network $NAME_SPACE --name acme-sh$HOSTNAME_SUFFIX neilpang/acme.sh:latest --issue --server https://$ACME_SERVER:$HTTPS_PORT --accountemail 'acme-sh@example.com' -d acme-sh$HOSTNAME_SUFFIX.$NAME_SPACE --alpn --standalone --debug 1 --output-insecure --insecure + ECC="_ecc" + else + echo "use RSA" + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network $NAME_SPACE --name acme-sh$HOSTNAME_SUFFIX neilpang/acme.sh:latest --issue --server https://$ACME_SERVER:$HTTPS_PORT --accountemail 'acme-sh@example.com' -d acme-sh$HOSTNAME_SUFFIX.$NAME_SPACE --alpn --standalone --keylength 2048 --debug 1 --output-insecure --insecure + fi + + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh$HOSTNAME_SUFFIX.$NAME_SPACE${ECC}/ca.cer + if [ "$VERIFY_CERT" == "true" ]; then + if [ -f cert-2.pem ]; then + echo "Multiple CA certs" + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh$HOSTNAME_SUFFIX.$NAME_SPACE${ECC}/acme-sh$HOSTNAME_SUFFIX.$NAME_SPACE.cer + else + echo "Single Root ca" + openssl verify -CAfile cert-1.pem acme-sh/acme-sh$HOSTNAME_SUFFIX.$NAME_SPACE${ECC}/acme-sh$HOSTNAME_SUFFIX.$NAME_SPACE.cer + fi + fi + shell: bash + env: + VERIFY_CERT: ${{ inputs.VERIFY_CERT }} + ACME_SERVER: ${{ inputs.ACME_SERVER }} + HTTP_PORT: ${{ inputs.HTTP_PORT }} + HTTPS_PORT: ${{ inputs.HTTPS_PORT }} + USE_RSA: ${{ inputs.USE_RSA }} + HOSTNAME_SUFFIX: ${{ inputs.HOSTNAME_SUFFIX }} + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "HTTPS - Renew acme.sh" + if: ${{ inputs.RENEWAL == 'true' }} + run: | + echo "##### HTTPS - Renew acme.sh #####" + if [ "$USE_RSA" == "false" ]; then + echo "use ECC" + ECC="_ecc" + else + echo "use RSA" + fi + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network $NAME_SPACE --name acme-sh$HOSTNAME_SUFFIX neilpang/acme.sh:latest --renew --server https://$ACME_SERVER:$HTTPS_PORT --force --accountemail 'acme-sh@example.com' -d acme-sh$HOSTNAME_SUFFIX.$NAME_SPACE --alpn --standalone --debug 1 --output-insecure --insecure + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh$HOSTNAME_SUFFIX.$NAME_SPACE${ECC}/ca.cer + if [ "$VERIFY_CERT" == "true" ]; then + if [ -f cert-2.pem ]; then + echo "Multiple CA certs" + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh$HOSTNAME_SUFFIX.$NAME_SPACE${ECC}/acme-sh$HOSTNAME_SUFFIX.$NAME_SPACE.cer + else + echo "Single Root ca" + openssl verify -CAfile cert-1.pem acme-sh/acme-sh$HOSTNAME_SUFFIX.$NAME_SPACE${ECC}/acme-sh$HOSTNAME_SUFFIX.$NAME_SPACE.cer + fi + fi + shell: bash + env: + VERIFY_CERT: ${{ inputs.VERIFY_CERT }} + ACME_SERVER: ${{ inputs.ACME_SERVER }} + HTTP_PORT: ${{ inputs.HTTP_PORT }} + HTTPS_PORT: ${{ inputs.HTTPS_PORT }} + USE_RSA: ${{ inputs.USE_RSA }} + HOSTNAME_SUFFIX: ${{ inputs.HOSTNAME_SUFFIX }} + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "HTTPS - Revoke HTTP-01 single domain acme.sh" + if: ${{ inputs.REVOCATION == 'true' }} + run: | + echo "##### HTTPS - Revoke HTTP-01 single domain acme.sh #####" + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --name acme-sh$HOSTNAME_SUFFIX --network $NAME_SPACE neilpang/acme.sh:latest --revoke --server https://$ACME_SERVER:$HTTPS_PORT --revoke -d acme-sh$HOSTNAME_SUFFIX.$NAME_SPACE --standalone --debug 2 --output-insecure --insecure + shell: bash + env: + ACME_SERVER: ${{ inputs.ACME_SERVER }} + HTTP_PORT: ${{ inputs.HTTP_PORT }} + HTTPS_PORT: ${{ inputs.HTTPS_PORT }} + HOSTNAME_SUFFIX: ${{ inputs.HOSTNAME_SUFFIX }} + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "HTTPS - Decativate acme.sh #####" + run: | + echo "##### HTTPS - Decativate acme.sh" + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --name acme-sh$HOSTNAME_SUFFIX --network $NAME_SPACE neilpang/acme.sh:latest --deactivate-account --server https://$ACME_SERVER:$HTTPS_PORT --debug 2 --output-insecure --insecure + shell: bash + env: + ACME_SERVER: ${{ inputs.ACME_SERVER }} + HTTP_PORT: ${{ inputs.HTTP_PORT }} + HTTPS_PORT: ${{ inputs.HTTPS_PORT }} + HOSTNAME_SUFFIX: ${{ inputs.HOSTNAME_SUFFIX }} + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "HTTP - Enroll acme.sh" + run: | + echo "##### HTTP - Enroll acme.sh #####" + sudo rm -rf acme-sh/* + if [ "$USE_RSA" == "false" ]; then + echo "use ECC" + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network $NAME_SPACE --name acme-sh$HOSTNAME_SUFFIX neilpang/acme.sh:latest --issue --server http://$ACME_SERVER:$HTTP_PORT --accountemail 'acme-sh@example.com' -d acme-sh$HOSTNAME_SUFFIX.$NAME_SPACE --standalone --debug 1 --output-insecure --insecure + ECC="_ecc" + else + echo "use RSA" + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network $NAME_SPACE --name acme-sh$HOSTNAME_SUFFIX neilpang/acme.sh:latest --issue --server http://$ACME_SERVER:$HTTP_PORT --accountemail 'acme-sh@example.com' -d acme-sh$HOSTNAME_SUFFIX.$NAME_SPACE --standalone --keylength 2048 --debug 1 --output-insecure --insecure + fi + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh$HOSTNAME_SUFFIX.$NAME_SPACE${ECC}/ca.cer + if [ "$VERIFY_CERT" == "true" ]; then + if [ -f cert-2.pem ]; then + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh$HOSTNAME_SUFFIX.$NAME_SPACE${ECC}/acme-sh$HOSTNAME_SUFFIX.$NAME_SPACE.cer + else + echo "single root ca" + openssl verify -CAfile cert-1.pem acme-sh/acme-sh$HOSTNAME_SUFFIX.$NAME_SPACE${ECC}/acme-sh$HOSTNAME_SUFFIX.$NAME_SPACE.cer + fi + fi + shell: bash + env: + VERIFY_CERT: ${{ inputs.VERIFY_CERT }} + ACME_SERVER: ${{ inputs.ACME_SERVER }} + HTTP_PORT: ${{ inputs.HTTP_PORT }} + HTTPS_PORT: ${{ inputs.HTTPS_PORT }} + USE_RSA: ${{ inputs.USE_RSA }} + HOSTNAME_SUFFIX: ${{ inputs.HOSTNAME_SUFFIX }} + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "HTTP - Renew acme.sh" + if: ${{ inputs.RENEWAL == 'true' }} + run: | + echo "##### HTTP - Renew acme.sh #####" + if [ "$USE_RSA" == "false" ]; then + echo "use ECC" + ECC="_ecc" + else + echo "use RSA" + fi + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network $NAME_SPACE --name acme-sh$HOSTNAME_SUFFIX neilpang/acme.sh:latest --renew --server http://$ACME_SERVER:$HTTP_PORT --force --accountemail 'acme-sh@example.com' -d acme-sh$HOSTNAME_SUFFIX.$NAME_SPACE --standalone --debug 1 --output-insecure --insecure + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh$HOSTNAME_SUFFIX.$NAME_SPACE${ECC}/ca.cer + if [ "$VERIFY_CERT" == "true" ]; then + if [ -f cert-2.pem ]; then + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh$HOSTNAME_SUFFIX.$NAME_SPACE${ECC}/acme-sh$HOSTNAME_SUFFIX.$NAME_SPACE.cer + else + echo "single root ca" + openssl verify -CAfile cert-1.pem acme-sh/acme-sh$HOSTNAME_SUFFIX.$NAME_SPACE${ECC}/acme-sh$HOSTNAME_SUFFIX.$NAME_SPACE.cer + fi + fi + shell: bash + env: + VERIFY_CERT: ${{ inputs.VERIFY_CERT }} + ACME_SERVER: ${{ inputs.ACME_SERVER }} + HTTP_PORT: ${{ inputs.HTTP_PORT }} + HTTPS_PORT: ${{ inputs.HTTPS_PORT }} + USE_RSA: ${{ inputs.USE_RSA }} + HOSTNAME_SUFFIX: ${{ inputs.HOSTNAME_SUFFIX }} + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "HTTP - Revoke HTTP-01 single domain acme.sh" + if: ${{ inputs.REVOCATION == 'true' }} + run: | + echo "##### HTTP - Revoke HTTP-01 single domain acme.sh #####" + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --name acme-sh$HOSTNAME_SUFFIX --network $NAME_SPACE neilpang/acme.sh:latest --revoke --server http://$ACME_SERVER:$HTTP_PORT --revoke -d acme-sh$HOSTNAME_SUFFIX.$NAME_SPACE --standalone --debug 2 --output-insecure --insecure + shell: bash + env: + ACME_SERVER: ${{ inputs.ACME_SERVER }} + HTTP_PORT: ${{ inputs.HTTP_PORT }} + HTTPS_PORT: ${{ inputs.HTTPS_PORT }} + HOSTNAME_SUFFIX: ${{ inputs.HOSTNAME_SUFFIX }} + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "HTTP - Decativate acme.sh" + run: | + echo "##### HTTP - Decativate acme.sh #####" + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --name acme-sh$HOSTNAME_SUFFIX --network $NAME_SPACE neilpang/acme.sh:latest --deactivate-account --server http://$ACME_SERVER:$HTTP_PORT --debug 2 --output-insecure --insecure + shell: bash + env: + ACME_SERVER: ${{ inputs.ACME_SERVER }} + HTTP_PORT: ${{ inputs.HTTP_PORT }} + HTTPS_PORT: ${{ inputs.HTTPS_PORT }} + HOSTNAME_SUFFIX: ${{ inputs.HOSTNAME_SUFFIX }} + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "HTTPS - Enroll certbot" + if: ${{ inputs.USE_CERTBOT == 'true' }} + run: | + echo "##### HTTPS - Enroll certbot #####" + if [ "$USE_RSA" == "false" ]; then + docker run -i --rm --name certbot$HOSTNAME_SUFFIX --network $NAME_SPACE -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server https://$ACME_SERVER:$HTTPS_PORT --standalone --preferred-challenges http --no-verify-ssl --agree-tos -m 'certbot@example.com' -d certbot$HOSTNAME_SUFFIX.$NAME_SPACE --cert-name certbot --issuance-timeout 120 + else + docker run -i --rm --name certbot$HOSTNAME_SUFFIX --network $NAME_SPACE -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server https://$ACME_SERVER:$HTTPS_PORT --standalone --preferred-challenges http --no-verify-ssl --agree-tos -m 'certbot@example.com' --key-type rsa -d certbot$HOSTNAME_SUFFIX.$NAME_SPACE --cert-name certbot --issuance-timeout 120 + fi + + if [ "$VERIFY_CERT" == "true" ]; then + if [ -f cert-2.pem ]; then + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem + else + echo "single root ca" + sudo openssl verify -CAfile cert-1.pem certbot/live/certbot/cert.pem + fi + fi + shell: bash + env: + VERIFY_CERT: ${{ inputs.VERIFY_CERT }} + ACME_SERVER: ${{ inputs.ACME_SERVER }} + HTTPS_PORT: ${{ inputs.HTTPS_PORT }} + USE_RSA: ${{ inputs.USE_RSA }} + HOSTNAME_SUFFIX: ${{ inputs.HOSTNAME_SUFFIX }} + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "HTTPS - Revoke certbot" + if: ${{ (inputs.USE_CERTBOT == 'true') && (inputs.REVOCATION == 'true') }} + run: | + echo "##### HTTPS - Revoke certbot #####" + docker run -i --rm --name certbot$HOSTNAME_SUFFIX --network $NAME_SPACE -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot revoke --server https://$ACME_SERVER:$HTTPS_PORT --no-verify-ssl --delete-after-revoke --cert-name certbot + shell: bash + env: + ACME_SERVER: ${{ inputs.ACME_SERVER }} + HTTP_PORT: ${{ inputs.HTTP_PORT }} + HTTPS_PORT: ${{ inputs.HTTPS_PORT }} + HOSTNAME_SUFFIX: ${{ inputs.HOSTNAME_SUFFIX }} + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "HTTP - Enroll certbot #####" + if: ${{ inputs.USE_CERTBOT == 'true' }} + run: | + echo "##### HTTP - Enroll certbot #####" + if [ "$USE_RSA" == "false" ]; then + docker run -i --rm --name certbot$HOSTNAME_SUFFIX --network $NAME_SPACE -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server http://$ACME_SERVER:$HTTP_PORT --standalone --preferred-challenges http --agree-tos -m 'certbot@example.com' -d certbot$HOSTNAME_SUFFIX.$NAME_SPACE --cert-name certbot --issuance-timeout 120 + else + docker run -i --rm --name certbot$HOSTNAME_SUFFIX --network $NAME_SPACE -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server http://$ACME_SERVER:$HTTP_PORT --standalone --preferred-challenges http --agree-tos -m 'certbot@example.com' --key-type rsa -d certbot$HOSTNAME_SUFFIX.$NAME_SPACE --cert-name certbot --issuance-timeout 120 + fi + + if [ "$VERIFY_CERT" == "true" ]; then + if [ -f cert-2.pem ]; then + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem + else + echo "single root ca" + sudo openssl verify -CAfile cert-1.pem certbot/live/certbot/cert.pem + fi + fi + shell: bash + env: + VERIFY_CERT: ${{ inputs.VERIFY_CERT }} + ACME_SERVER: ${{ inputs.ACME_SERVER }} + HTTP_PORT: ${{ inputs.HTTP_PORT }} + HTTPS_PORT: ${{ inputs.HTTPS_PORT }} + HOSTNAME_SUFFIX: ${{ inputs.HOSTNAME_SUFFIX }} + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "HTTP - Revoke certbot" + if: ${{ (inputs.USE_CERTBOT == 'true') && (inputs.REVOCATION == 'true') }} + run: | + echo "##### HTTP - Revoke certbot #####" + docker run -i --rm --name certbot$HOSTNAME_SUFFIX --network $NAME_SPACE -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot revoke --server http://$ACME_SERVER:$HTTP_PORT --delete-after-revoke --cert-name certbot + shell: bash + env: + ACME_SERVER: ${{ inputs.ACME_SERVER }} + HTTP_PORT: ${{ inputs.HTTP_PORT }} + HTTPS_PORT: ${{ inputs.HTTPS_PORT }} + HOSTNAME_SUFFIX: ${{ inputs.HOSTNAME_SUFFIX }} + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "HTTPS - Enroll lego" + run: | + echo "##### HTTPS - Enroll lego #####" + if [ "$USE_RSA" == "false" ]; then + echo "use ECC" + docker run -i --rm -e LEGO_CA_CERTIFICATES=.lego/acme2certifier_cabundle.pem -v $PWD/lego:/.lego/ --name lego$HOSTNAME_SUFFIX --network $NAME_SPACE goacme/lego -s https://$ACME_SERVER:$HTTPS_PORT -a --email "lego@example.com" -d lego$HOSTNAME_SUFFIX.$NAME_SPACE --tls run + else + echo "use RSA" + docker run -i --rm -e LEGO_CA_CERTIFICATES=.lego/acme2certifier_cabundle.pem -v $PWD/lego:/.lego/ --name lego$HOSTNAME_SUFFIX --network $NAME_SPACE goacme/lego -s https://$ACME_SERVER:$HTTPS_PORT -a --email "lego@example.com" --key-type=rsa2048 -d lego$HOSTNAME_SUFFIX.$NAME_SPACE --tls run + fi + + if [ "$VERIFY_CERT" == "true" ]; then + if [ -f cert-2.pem ]; then + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego$HOSTNAME_SUFFIX.$NAME_SPACE.crt + else + echo "single root ca" + sudo openssl verify -CAfile cert-1.pem lego/certificates/lego$HOSTNAME_SUFFIX.$NAME_SPACE.crt + fi + fi + shell: bash + env: + VERIFY_CERT: ${{ inputs.VERIFY_CERT }} + ACME_SERVER: ${{ inputs.ACME_SERVER }} + HTTP_PORT: ${{ inputs.HTTP_PORT }} + HTTPS_PORT: ${{ inputs.HTTPS_PORT }} + USE_RSA: ${{ inputs.USE_RSA }} + HOSTNAME_SUFFIX: ${{ inputs.HOSTNAME_SUFFIX }} + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "HTTPS - Revoke lego" + if: ${{ inputs.REVOCATION == 'true' }} + run: | + echo "##### HTTPS - Revoke lego #####" + docker run -i --rm -e LEGO_CA_CERTIFICATES=.lego/acme2certifier_cabundle.pem -v $PWD/lego:/.lego/ --name lego$HOSTNAME_SUFFIX --network $NAME_SPACE goacme/lego -s https://$ACME_SERVER:$HTTPS_PORT -a --email "lego@example.com" -d lego$HOSTNAME_SUFFIX.$NAME_SPACE revoke + shell: bash + env: + ACME_SERVER: ${{ inputs.ACME_SERVER }} + HTTP_PORT: ${{ inputs.HTTP_PORT }} + HTTPS_PORT: ${{ inputs.HTTPS_PORT }} + HOSTNAME_SUFFIX: ${{ inputs.HOSTNAME_SUFFIX }} + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "HTTP - Enroll lego" + run: | + echo "##### HTTP - Enroll lego #####" + sudo rm -rf lego/* + if [ "$USE_RSA" == "false" ]; then + echo "use ECC" + docker run -i -v $PWD/lego:/.lego/ --rm --name lego$HOSTNAME_SUFFIX --network $NAME_SPACE goacme/lego -s http://$ACME_SERVER:$HTTP_PORT -a --email "lego@example.com" -d lego$HOSTNAME_SUFFIX.$NAME_SPACE --http run + else + echo "use RSA" + docker run -i -v $PWD/lego:/.lego/ --rm --name lego$HOSTNAME_SUFFIX --network $NAME_SPACE goacme/lego -s http://$ACME_SERVER:$HTTP_PORT -a --email "lego@example.com" --key-type=rsa2048 -d lego$HOSTNAME_SUFFIX.$NAME_SPACE --http run + fi + if [ "$VERIFY_CERT" == "true" ]; then + if [ -f cert-2.pem ]; then + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego$HOSTNAME_SUFFIX.$NAME_SPACE.crt + else + echo "single root ca" + sudo openssl verify -CAfile cert-1.pem lego/certificates/lego$HOSTNAME_SUFFIX.$NAME_SPACE.crt + fi + fi + shell: bash + env: + VERIFY_CERT: ${{ inputs.VERIFY_CERT }} + ACME_SERVER: ${{ inputs.ACME_SERVER }} + HTTP_PORT: ${{ inputs.HTTP_PORT }} + HTTPS_PORT: ${{ inputs.HTTPS_PORT }} + USE_RSA: ${{ inputs.USE_RSA }} + HOSTNAME_SUFFIX: ${{ inputs.HOSTNAME_SUFFIX }} + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "HTTP - Revoke lego" + if: ${{ inputs.REVOCATION == 'true' }} + run: | + echo "#### HTTP - Revoke lego" + docker run -i -v $PWD/lego:/.lego/ --rm --name lego$HOSTNAME_SUFFIX --network $NAME_SPACE goacme/lego -s http://$ACME_SERVER:$HTTP_PORT -a --email "lego@example.com" -d lego$HOSTNAME_SUFFIX.$NAME_SPACE revoke + shell: bash + env: + ACME_SERVER: ${{ inputs.ACME_SERVER }} + HTTP_PORT: ${{ inputs.HTTP_PORT }} + HTTPS_PORT: ${{ inputs.HTTPS_PORT }} + HOSTNAME_SUFFIX: ${{ inputs.HOSTNAME_SUFFIX }} + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "Delete acme-sh, letsencypt and lego folders" + run: | + sudo rm -rf lego/* + sudo rm -rf acme-sh/* + sudo rm -rf certbot/* + shell: bash \ No newline at end of file diff --git a/.github/actions/container_build/action.yml b/.github/actions/container_build/action.yml new file mode 100644 index 00000000..921ed6e2 --- /dev/null +++ b/.github/actions/container_build/action.yml @@ -0,0 +1,31 @@ +name: "container_build" +description: "Build Container" +inputs: + DB_HANDLER: + description: "Database handler" + required: true + default: "wsgi" + WEB_SRV: + description: "Web server" + required: true + default: "apache2" + DOCKER_COMPOSE_FILE_PATH: + description: "Path to the docker-compose file" + required: false + default: "examples/Docker/" + +runs: + using: "composite" + steps: + - name: "Build docker-compose (${{ inputs.WEB_SRV }}_${{ inputs.DB_HANDLER }})" + working-directory: ${{ inputs.DOCKER_COMPOSE_FILE_PATH }} + run: | + sudo apt-get install -y docker-compose + sed -i "s/wsgi/$DB_HANDLER/g" .env + sed -i "s/apache2/$WEB_SRV/g" .env + # cat .env + docker-compose build + shell: bash + env: + WEB_SRV: ${{ inputs.WEB_SRV }} + DB_HANDLER: ${{ inputs.DB_HANDLER }} diff --git a/.github/actions/container_build_upload/action.yml b/.github/actions/container_build_upload/action.yml new file mode 100644 index 00000000..ea3c75d3 --- /dev/null +++ b/.github/actions/container_build_upload/action.yml @@ -0,0 +1,37 @@ +name: "container_build_upload" +description: "Build and Upload Container" +inputs: + DB_HANDLER: + description: "Database handler" + required: true + default: "wsgi" + WEB_SRV: + description: "Web server" + required: true + default: "apache2" + +runs: + using: "composite" + steps: + - name: "Build container" + uses: ./.github/actions/container_build + with: + DB_HANDLER: ${{ inputs.DB_HANDLER }} + WEB_SRV: ${{ inputs.WEB_SRV }} + + - name: "Save container" + run: | + docker images + mkdir -p /tmp/a2c + docker save acme2certifier/$DB_HANDLER > /tmp/a2c/a2c-${{ github.run_id }}.$WEB_SRV.$DB_HANDLER.tar + gzip /tmp/a2c/a2c-${{ github.run_id }}.$WEB_SRV.$DB_HANDLER.tar + shell: bash + env: + DB_HANDLER: ${{ inputs.DB_HANDLER }} + WEB_SRV: ${{ inputs.WEB_SRV }} + + - name: "Upload container package" + uses: actions/upload-artifact@master + with: + name: a2c-${{ github.run_id }}.${{ inputs.WEB_SRV }}.${{ inputs.DB_HANDLER }}.tar.gz + path: /tmp/a2c diff --git a/.github/actions/container_check/action.yml b/.github/actions/container_check/action.yml new file mode 100644 index 00000000..4bc12b2e --- /dev/null +++ b/.github/actions/container_check/action.yml @@ -0,0 +1,32 @@ +name: "container_check" +description: "Check container configuration" +inputs: + DB_HANDLER: + description: "Database handler" + required: true + default: "wsgi" + WEB_SRV: + description: "Web server" + required: true + default: "apache2" + DOCKER_COMPOSE_FILE_PATH: + description: "Path to the docker-compose file" + required: false + default: "examples/Docker/" + +runs: + using: "composite" + steps: + - name: "Logs" + working-directory: ${{ inputs.DOCKER_COMPOSE_FILE_PATH }} + run: | + docker-compose logs | grep -i $WEB_SRV + if [ "$DB_HANDLER" == "django" ]; then + docker-compose logs | grep -i migrations + else + docker-compose logs | grep -i $DB_HANDLER + fi + env: + WEB_SRV: ${{ inputs.WEB_SRV }} + DB_HANDLER: ${{ inputs.DB_HANDLER }} + shell: bash \ No newline at end of file diff --git a/.github/actions/container_prep/action.yml b/.github/actions/container_prep/action.yml new file mode 100644 index 00000000..75a6f30a --- /dev/null +++ b/.github/actions/container_prep/action.yml @@ -0,0 +1,92 @@ +name: "container_prep" +description: "Prepare environment for container installation" +inputs: + DB_HANDLER: + description: "Database handler" + required: true + default: "wsgi" + WEB_SRV: + description: "Web server" + required: true + default: "apache2" + DJANGO_DB: + description: "Django database" + required: false + CONTAINER_BUILD: + description: "Build container" + required: true + default: "true" + NAME_SPACE: + description: "namespace" + required: true + default: "acme" + IPV6: + description: "IPv6" + required: true + default: "false" + +runs: + using: "composite" + steps: + - name: "Setup environment" + run: | + echo "IPv6 is $IPV6" + if [ "$IPV6" == "false" ]; then + echo "create v4 namespace" + docker network create $NAME_SPACE + else + echo "create v6 namespace" + docker network create $NAME_SPACE --ipv6 --subnet "fdbb:6445:65b4:0a60::/64" + fi + sudo mkdir -p examples/Docker/data + sudo cp .github/acme2certifier.pem examples/Docker/data/acme2certifier.pem + sudo cp .github/acme2certifier_cert.pem examples/Docker/data/acme2certifier_cert.pem + sudo cp .github/acme2certifier_key.pem examples/Docker/data/acme2certifier_key.pem + if [ -z "$DJANGO_DB" ]; then + sudo cp .github/django_settings.py examples/Docker/data/settings.py + else + sudo cp .github/django_settings_$DJANGO_DB.py examples/Docker/data/settings.py + fi + env: + DJANGO_DB: ${{ inputs.DJANGO_DB }} + NAME_SPACE: ${{ inputs.NAME_SPACE }} + IPV6: ${{ inputs.IPV6 }} + shell: bash + + - name: "Build docker-compose (${{ inputs.WEB_SRV }}_${{ inputs.DB_HANDLER }})" + if: inputs.CONTAINER_BUILD == 'true' + uses: ./.github/actions/container_build + with: + WEB_SRV: ${{ inputs.WEB_SRV }} + DB_HANDLER: ${{ inputs.DB_HANDLER }} + + - name: "Prepare container environment file (${{ inputs.WEB_SRV }}_${{ inputs.DB_HANDLER }})" + if: inputs.CONTAINER_BUILD != 'true' + working-directory: examples/Docker/ + run: | + sed -i "s/wsgi/$DB_HANDLER/g" .env + sed -i "s/apache2/$WEB_SRV/g" .env + env: + WEB_SRV: ${{ inputs.WEB_SRV }} + DB_HANDLER: ${{ inputs.DB_HANDLER }} + shell: bash + + - name: "Spin-up a2c instance (${{ inputs.WEB_SRV }}_${{ inputs.DB_HANDLER }})" + if: inputs.CONTAINER_BUILD == 'true' + uses: ./.github/actions/container_up + with: + WEB_SRV: ${{ inputs.WEB_SRV }} + DB_HANDLER: ${{ inputs.DB_HANDLER }} + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "Instanciate Mariadb" + if: inputs.DJANGO_DB == 'mariadb' + uses: ./.github/actions/mariadb_prep + with: + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "Instanciate Postgres" + if: inputs.DJANGO_DB == 'psql' + uses: ./.github/actions/psql_prep + with: + NAME_SPACE: ${{ inputs.NAME_SPACE }} \ No newline at end of file diff --git a/.github/actions/container_up/action.yml b/.github/actions/container_up/action.yml new file mode 100644 index 00000000..8be2dc9f --- /dev/null +++ b/.github/actions/container_up/action.yml @@ -0,0 +1,31 @@ +name: "container_up" +description: "instanciate a2c container" +inputs: + DB_HANDLER: + description: "Database handler" + required: true + default: "wsgi" + WEB_SRV: + description: "Web server" + required: true + default: "apache2" + DOCKER_COMPOSE_FILE_PATH: + description: "Path to the docker-compose file" + required: false + default: "examples/Docker/" + NAME_SPACE: + description: "namespace" + required: true + default: "acme" + +runs: + using: "composite" + steps: + - name: "Spin-up a2c instance (${{ inputs.WEB_SRV }}_${{ inputs.DB_HANDLER }})" + working-directory: ${{ inputs.DOCKER_COMPOSE_FILE_PATH }} + run: | + sed -i "s/name: acme/name: $NAME_SPACE/g" docker-compose.yml + docker-compose up -d --no-build + env: + NAME_SPACE: ${{ inputs.NAME_SPACE }} + shell: bash \ No newline at end of file diff --git a/.github/actions/deb_build/action.yml b/.github/actions/deb_build/action.yml new file mode 100644 index 00000000..cb41df40 --- /dev/null +++ b/.github/actions/deb_build/action.yml @@ -0,0 +1,72 @@ +name: "deb_build" +description: "Build deb package" +outputs: + deb_file_name: + description: "Name of the debian package file" + value: acme2certifier_${{ env.TAG_NAME }}-1_all.deb + +runs: + using: "composite" + steps: + + - name: Retrieve Version from version.py + run: | + echo TAG_NAME=$(cat acme_srv/version.py | grep -i __version__ | head -n 1 | sed 's/__version__ = //g' | sed s/\'//g) >> $GITHUB_ENV + shell: bash + + - run: echo "Latest tag is ${{ env.TAG_NAME }}" + shell: bash + + - name: "Install Firefox from Mozilla" + run: | + sudo apt-get update + sudo install -d -m 0755 /etc/apt/keyrings + wget -q https://packages.mozilla.org/apt/repo-signing-key.gpg -O- | sudo tee /etc/apt/keyrings/packages.mozilla.org.asc > /dev/null + echo "deb [signed-by=/etc/apt/keyrings/packages.mozilla.org.asc] https://packages.mozilla.org/apt mozilla main" | sudo tee -a /etc/apt/sources.list.d/mozilla.list > /dev/null + echo ' + Package: * + Pin: origin packages.mozilla.org + Pin-Priority: 1000 + ' | sudo tee /etc/apt/preferences.d/mozilla + sudo apt update && sudo apt install -y firefox --allow-downgrades + shell: bash + + - name: "Prepare environment to build deb package" + run: | + sudo apt-get update && sudo apt-get -y upgrade + sudo apt-get -y install build-essential fakeroot dpkg-dev devscripts debhelper --allow-downgrades + rm setup.py + rm -f examples/ngnix/acme2certifier.te + rm -f examples/nginx/supervisord.conf + rm -f examples/nginx/uwsgi.service + sed -i "s/run\/uwsgi\/acme.sock/var\/www\/acme2certifier\/acme.sock/g" examples/nginx/nginx_acme_srv.conf + sed -i "s/run\/uwsgi\/acme.sock/var\/www\/acme2certifier\/acme.sock/g" examples/nginx/nginx_acme_srv_ssl.conf + sed -i "s/\/run\/uwsgi\/acme.sock/acme.sock/g" examples/nginx/acme2certifier.ini + sed -i "s/nginx/www-data/g" examples/nginx/acme2certifier.ini + echo "plugins=python3" >> examples/nginx/acme2certifier.ini + cat < examples/nginx/acme2certifier.service + [Unit] + Description=uWSGI instance to serve acme2certifier + After=network.target + + [Service] + User=www-data + Group=www-data + WorkingDirectory=/var/www/acme2certifier + Environment="PATH=/var/www/acme2certifier" + ExecStart=uwsgi --ini /var/www/acme2certifier/acme2certifier.ini + + [Install] + WantedBy=multi-user.target + EOT + cp -R examples/install_scripts/debian ./ + sudo sed -i "s/__version__/${{ env.TAG_NAME }}/g" debian/changelog + cd ../ + tar cvfz ../acme2certifier_${{ env.TAG_NAME }}.orig.tar.gz ./ + shell: bash + + - name: "Build debian package" + run: | + dpkg-buildpackage -uc -us + dpkg -c ../acme2certifier_${{ env.TAG_NAME }}-1_all.deb + shell: bash diff --git a/.github/actions/deb_build_upload/action.yml b/.github/actions/deb_build_upload/action.yml new file mode 100644 index 00000000..5ffd4a7b --- /dev/null +++ b/.github/actions/deb_build_upload/action.yml @@ -0,0 +1,27 @@ +name: "rpm_build_upload" +description: "Build and Upload package" +outputs: + deb_file_name: + description: "Name of the RPM package file" + value: acme2certifier_${{ env.TAG_NAME }}-${{ github.run_id }}-1_all.deb + +runs: + using: "composite" + steps: + + - name: "Build deb package" + id: deb_build + uses: ./.github/actions/deb_build + + - name: "Rename deb package" + run: | + sudo mv ../acme2certifier_${{ env.TAG_NAME }}-1_all.deb ./acme2certifier_${{ env.TAG_NAME }}-${{ github.run_id }}-1_all.deb + shell: bash + + - name: "Upload deb package" + uses: actions/upload-artifact@v4 + with: + name: acme2certifier_${{ env.TAG_NAME }}-${{ github.run_id }}-1_all.deb + path: acme2certifier_${{ env.TAG_NAME }}-${{ github.run_id }}-1_all.deb + + diff --git a/.github/actions/deb_prep/action.yml b/.github/actions/deb_prep/action.yml new file mode 100644 index 00000000..e12aa39d --- /dev/null +++ b/.github/actions/deb_prep/action.yml @@ -0,0 +1,85 @@ +name: "deb_prep" +description: "Prepare environment for deb installation" +inputs: + GH_SBOM_USER: + description: "GIT user for SBOM repo" + required: true + GH_SBOM_TOKEN: + description: "GIT token for SBOM repo" + required: true + DJANGO_DB: + description: "Django database" + DEB_BUILD: + description: "Build DEB" + required: true + default: "true" + NAME_SPACE: + description: "Name space" + required: true + default: "acme" + IPV6: + description: "IPv6" + required: true + default: "false" + +runs: + using: "composite" + steps: + + - name: "Build deb package" + if: inputs.DEB_BUILD == 'true' + id: deb_build + uses: ./.github/actions/deb_build + + - name: "Setup environment for ubuntu installation" + run: | + echo "IPv6 is $IPV6" + if [ "$IPV6" == "false" ]; then + echo "create v4 namespace" + docker network create $NAME_SPACE + else + echo "create v6 namespace" + docker network create $NAME_SPACE --ipv6 --subnet "fdbb:6445:65b4:0a60::/64" + fi + sudo mkdir -p data/volume/acme2certifier + sudo mkdir -p data/nginx + sudo chmod -R 777 data + sudo cp examples/Docker/ubuntu-systemd/deb_tester.sh data + sudo cp examples/Docker/ubuntu-systemd/django_tester.sh data + sudo cp .github/acme2certifier_cert.pem data/volume/acme2certifier_cert.pem + sudo cp .github/acme2certifier_key.pem data/volume/acme2certifier_key.pem + sudo cp .github/acme2certifier.pem data/volume/acme2certifier.pem + + if [ -z "$DJANGO_DB" ]; then + sudo cp .github/django_settings.py data/volume/acme2certifier/settings.py + else + sudo cp .github/django_settings_$DJANGO_DB.py data/volume/acme2certifier/settings.py + fi + env: + DJANGO_DB: ${{ inputs.DJANGO_DB }} + NAME_SPACE: ${{ inputs.NAME_SPACE }} + IPV6: ${{ inputs.IPV6 }} + shell: bash + + - name: "Instanciate Ubuntu 22.04" + run: | + docker run -d --name acme-srv --network $NAME_SPACE --privileged -v /sys/fs/cgroup:/sys/fs/cgroup:rw --cgroupns=host -v "$(pwd)/data":/tmp/acme2certifier jrei/systemd-ubuntu:22.04 + shell: bash + env: + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "Instanciate Mariadb" + if: inputs.DJANGO_DB == 'mariadb' + uses: ./.github/actions/mariadb_prep + with: + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "Instanciate Postgres" + if: inputs.DJANGO_DB == 'psql' + uses: ./.github/actions/psql_prep + with: + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + + + diff --git a/.github/actions/mariadb_prep/action.yml b/.github/actions/mariadb_prep/action.yml new file mode 100644 index 00000000..95cba61b --- /dev/null +++ b/.github/actions/mariadb_prep/action.yml @@ -0,0 +1,36 @@ +name: "maria_prep" +description: "bring up and configure mariadb instance" +inputs: + NAME_SPACE: + description: "Name space" + required: true + default: "acme" + +runs: + using: "composite" + steps: + - name: "Instanciate Mariadb" + run: | + # sudo mkdir -p data/mysql + docker run --name mariadbsrv --network acme -e MARIADB_ROOT_PASSWORD=foobar -d mariadb + shell: bash + env: + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "Sleep for 10s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 10s + + - name: "Configure mariadb" + working-directory: examples/Docker/ + run: | + docker exec mariadbsrv mariadb -u root --password=foobar -e"CREATE DATABASE acme2certifier CHARACTER SET UTF8;" + docker exec mariadbsrv mariadb -u root --password=foobar -e"GRANT ALL PRIVILEGES ON acme2certifier.* TO 'acme2certifier'@'%' IDENTIFIED BY '1mmSvDFl';" + docker exec mariadbsrv mariadb -u root --password=foobar -e"FLUSH PRIVILEGES;" + shell: bash + + - name: "Sleep for 5s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 5s \ No newline at end of file diff --git a/.github/actions/psql_prep/action.yml b/.github/actions/psql_prep/action.yml new file mode 100644 index 00000000..573cc29b --- /dev/null +++ b/.github/actions/psql_prep/action.yml @@ -0,0 +1,45 @@ +name: "psql_prep" +description: "bring up and configure psql instance" +inputs: + NAME_SPACE: + description: "Name space" + required: true + default: "acme" + +runs: + using: "composite" + steps: + + - name: "postgres environment" + run: | + sudo mkdir -p /tmp/data/pgsql + sudo cp .github/a2c.psql /tmp/data/pgsql/a2c.psql + sudo cp .github/pgpass /tmp//data/pgsql/pgpass + sudo chmod 600 /tmp/data/pgsql/pgpass + shell: bash + + - name: "Install postgres" + working-directory: /tmp + run: | + docker run --name postgresdbsrv --network $NAME_SPACE -e POSTGRES_PASSWORD=foobar -d postgres + shell: bash + env: + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "Sleep for 10s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 10s + + - name: "Configure postgres" + working-directory: /tmp + run: | + docker run -v "$(pwd)/data/pgsql/a2c.psql":/tmp/a2c.psql -v "$(pwd)/data/pgsql/pgpass:/root/.pgpass" --rm --network $NAME_SPACE postgres psql -U postgres -h postgresdbsrv -f /tmp/a2c.psql + shell: bash + env: + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "Sleep for 5s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 5s \ No newline at end of file diff --git a/.github/actions/rpm_build/action.yml b/.github/actions/rpm_build/action.yml new file mode 100644 index 00000000..05777323 --- /dev/null +++ b/.github/actions/rpm_build/action.yml @@ -0,0 +1,41 @@ +name: "rpm_build" +description: "Build RPM package" +outputs: + rpm_dir_path: + description: "Path to the directory containing the RPM package" + value: ${{ steps.rpm.outputs.rpm_dir_path }} + rpm_file_name: + description: "Name of the RPM package file" + value: acme2certifier-${{ env.TAG_NAME }}-1.0.noarch.rpm + +runs: + using: "composite" + steps: + + - name: "Retrieve Version from version.py" + run: | + echo TAG_NAME=$(cat acme_srv/version.py | grep -i __version__ | head -n 1 | sed 's/__version__ = //g' | sed s/\'//g) >> $GITHUB_ENV + shell: bash + + - run: echo "Latest tag is ${{ env.TAG_NAME }}" + shell: bash + + - name: "Update version number in spec file and path in nginx ssl config" + run: | + sudo sed -i "s/__version__/${{ env.TAG_NAME }}/g" examples/install_scripts/rpm/acme2certifier.spec + sudo sed -i "s/\/var\/www\/acme2certifier\/volume/\/etc\/nginx/g" examples/nginx/nginx_acme_srv_ssl.conf + git config --global user.email "grindelsack@gmail.com" + git config --global user.name "rpm update" + git add examples/nginx + git commit -a -m "rpm update" + shell: bash + + - name: "Build RPM package" + id: rpm + uses: grindsa/rpmbuild@alma9 + with: + spec_file: "examples/install_scripts/rpm/acme2certifier.spec" + + - run: echo "path is ${{ steps.rpm.outputs.rpm_dir_path }}" + shell: bash + diff --git a/.github/actions/rpm_build_upload/action.yml b/.github/actions/rpm_build_upload/action.yml new file mode 100644 index 00000000..4fee394f --- /dev/null +++ b/.github/actions/rpm_build_upload/action.yml @@ -0,0 +1,26 @@ +name: "rpm_build_upload" +description: "Build and Upload package" +outputs: + rpm_file_name: + description: "Name of the RPM package file" + value: acme2certifier-${{ github.run_id }}.noarch.rpm + +runs: + using: "composite" + steps: + + - name: "Build rpm package" + id: rpm_build + uses: ./.github/actions/rpm_build + + - name: "Rename rpm package" + run: | + sudo mv ${{ steps.rpm_build.outputs.rpm_dir_path }}/noarch/acme2certifier-*.noarch.rpm ${{ steps.rpm_build.outputs.rpm_dir_path }}/noarch/acme2certifier-${{ github.run_id }}.noarch.rpm + shell: bash + + - name: "Upload RPM package" + uses: actions/upload-artifact@master + with: + name: acme2certifier-${{ github.run_id }}.noarch.rpm + path: ${{ steps.rpm_build.outputs.rpm_dir_path }}/noarch/ + diff --git a/.github/actions/rpm_prep/action.yml b/.github/actions/rpm_prep/action.yml new file mode 100644 index 00000000..2e9cd363 --- /dev/null +++ b/.github/actions/rpm_prep/action.yml @@ -0,0 +1,109 @@ +name: "rpm_prep" +description: "Prepare environment for RPM installation" +inputs: + GH_SBOM_USER: + description: "GIT user for SBOM repo" + required: true + GH_SBOM_TOKEN: + description: "GIT token for SBOM repo" + required: true + RH_VERSION: + description: "RHEL version" + required: true + DJANGO_DB: + description: "Django database" + RPM_BUILD: + description: "Build RPM" + required: true + default: "true" + NAME_SPACE: + description: "Name space" + required: true + default: "acme" + IPV6: + description: "IPv6" + required: true + default: "false" + +runs: + using: "composite" + steps: + + - name: "Build rpm package" + if: inputs.RPM_BUILD == 'true' + id: rpm_build + uses: ./.github/actions/rpm_build + + - name: "Setup environment for alma installation" + run: | + echo "IPv6 is $IPV6" + if [ "$IPV6" == "false" ]; then + echo "create v4 namespace" + docker network create $NAME_SPACE + else + echo "create v6 namespace" + docker network create $NAME_SPACE --ipv6 --subnet "fdbb:6445:65b4:0a60::/64" + fi + sudo mkdir -p data/volume + sudo mkdir -p data/acme2certifier + sudo mkdir -p data/nginx + sudo chmod -R 777 data + sudo cp examples/Docker/almalinux-systemd/django_tester.sh data + sudo cp examples/Docker/almalinux-systemd/rpm_tester.sh data + sudo cp .github/acme2certifier_cert.pem data/nginx/acme2certifier_cert.pem + sudo cp .github/acme2certifier_key.pem data/nginx/acme2certifier_key.pem + if [ -f ${{ steps.rpm_build.outputs.rpm_dir_path }}noarch/acme2certifier-${{ env.TAG_NAME }}-1.0.noarch.rpm ]; then + echo "RPM exists" + sudo cp ${{ steps.rpm_build.outputs.rpm_dir_path }}noarch/acme2certifier-${{ env.TAG_NAME }}-1.0.noarch.rpm data + else + echo "RPM does not exist" + fi + if [ -z "$DJANGO_DB" ]; then + sudo cp .github/django_settings.py data/acme2certifier/settings.py + else + sudo cp .github/django_settings_$DJANGO_DB.py data/acme2certifier/settings.py + fi + sudo sed -i "s/\/var\/www\//\/opt\//g" data/acme2certifier/settings.py + sudo sed -i "s/USE_I18N = True/USE_I18N = False/g" data/acme2certifier/settings.py + env: + DJANGO_DB: ${{ inputs.DJANGO_DB }} + NAME_SPACE: ${{ inputs.NAME_SPACE }} + IPV6: ${{ inputs.IPV6 }} + + shell: bash + + - run: echo "RH_VERSION is ${{ inputs.RH_VERSION }}" + shell: bash + + - name: "Retrieve rpms from SBOM repo" + run: | + git clone https://$GH_SBOM_USER:$GH_SBOM_TOKEN@github.com/$GH_SBOM_USER/sbom /tmp/sbom + cp /tmp/sbom/rpm-repo/RPMs/rhel$RH_VERSION/*.rpm data + env: + GH_SBOM_USER: ${{ inputs.GH_SBOM_USER }} + GH_SBOM_TOKEN: ${{ inputs.GH_SBOM_TOKEN }} + RH_VERSION: ${{ inputs.RH_VERSION }} + shell: bash + + - name: "Spin-up alma instance" + run: | + sudo cp examples/Docker/almalinux-systemd/Dockerfile data + sudo sed -i "s/FROM almalinux:9/FROM almalinux:$RH_VERSION/g" data/Dockerfile + cat data/Dockerfile | docker build -t almalinux-systemd -f - . --no-cache + docker run -d -id --privileged --network $NAME_SPACE -p 22280:80 --name=acme-srv -v "$(pwd)/data":/tmp/acme2certifier almalinux-systemd + env: + RH_VERSION: ${{ inputs.RH_VERSION }} + NAME_SPACE: ${{ inputs.NAME_SPACE }} + shell: bash + + - name: "Instanciate Mariadb" + if: inputs.DJANGO_DB == 'mariadb' + uses: ./.github/actions/mariadb_prep + with: + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "Instanciate Postgres" + if: inputs.DJANGO_DB == 'psql' + uses: ./.github/actions/psql_prep + with: + NAME_SPACE: ${{ inputs.NAME_SPACE }} \ No newline at end of file diff --git a/.github/actions/wf_specific/acme_ca_handler/enrollment_profiling/action.yml b/.github/actions/wf_specific/acme_ca_handler/enrollment_profiling/action.yml new file mode 100644 index 00000000..279d89f5 --- /dev/null +++ b/.github/actions/wf_specific/acme_ca_handler/enrollment_profiling/action.yml @@ -0,0 +1,150 @@ +name: "enrollment_profiling" +description: "le-enrollment_profiling" + +runs: + using: "composite" + steps: + + - name: "Sleep for 10s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 10s + + - name: "Test http://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory + shell: bash + + - name: "EAB - 01 - Enroll acme.sh without acme_url" + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_00 --eab-hmac-key V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv -d acme-sh.acme --standalone --debug 3 --output-insecure + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -issuer --noout | grep -i root-ca + shell: bash + + - name: "EAB - 01 - Enroll lego without acme_url" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw -d lego.acme --http run + sudo openssl x509 -in lego/certificates/lego.acme.crt -issuer --noout | grep -i root-ca + shell: bash + + - name: "EAB with headerinfo - 02a - Enroll acme with a template_name taken from header_info NOT included in kid.json (to fail)" + id: acmefail01 + continue-on-error: true + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_00 --eab-hmac-key V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv --useragent acme_url=http://foo.bar -d acme-sh.acme --standalone --debug 3 --output-insecure + shell: bash + + - name: "EAB with headerinfo - 02a - check result " + if: steps.acmefail01.outcome != 'failure' + run: | + echo "acmefail outcome is ${{steps.acmefail01.outcome }}" + exit 1 + shell: bash + + - name: "EAB with headerinfo - 02b - Enroll acme with a template_name taken from header_info included in kid.json" + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_00 --eab-hmac-key V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv --useragent acme_url=http://acme-le-sim-1.acme -d acme-sh.acme --standalone --debug 3 --output-insecure + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -text -noout + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -issuer --noout | grep -i sub-ca + shell: bash + + - name: "EAB with headerinfo - 02a - Enroll lego with a template_name taken from header_info NOT included in kid.json (to fail)" + id: legofail01 + continue-on-error: true + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --user-agent acme_url=http://foo.bar -d lego.acme --http run + shell: bash + + - name: "EAB with headerinfo - 02a - check result " + if: steps.legofail01.outcome != 'failure' + run: | + echo "legofail outcome is ${{steps.legofail01.outcome }}" + exit 1 + shell: bash + + - name: "EAB with headerinfo - 02b - Enroll lego with a template_name taken from header_info included in kid.json" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --user-agent acme_url=http://acme-le-sim-1.acme -d lego.acme --http run + sudo openssl x509 -in lego/certificates/lego.acme.crt -ext extendedKeyUsage -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -issuer --noout + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl x509 -in lego/certificates/lego.acme.crt -issuer --noout | grep -i sub-ca + shell: bash + + - name: "EAB - 03 - Enroll acme with a acme_url and key taken from kid.json" + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_01 --eab-hmac-key YW5vdXRoZXJfdmVyeV9sb25nX2htYWNfZm9yX2tleWlkXzAxX3doaWNoIHdpbGxfYmUgdXNlZF9kdXJpbmcgcmVncmVzc2lvbg --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv -d acme-sh.acme --standalone --debug 3 --output-insecure + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -text -noout + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -issuer --noout | grep -i root-ca + shell: bash + + - name: "EAB without headerinfo - 03 - Enroll lego with a profile_name/ca_name taken from kid.json" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_01 --hmac YW5vdXRoZXJfdmVyeV9sb25nX2htYWNfZm9yX2tleWlkXzAxX3doaWNoIHdpbGxfYmUgdXNlZF9kdXJpbmcgcmVncmVzc2lvbg -k rsa2048 -d lego.acme --http run + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -issuer --noout | grep -i root-ca + shell: bash + + - name: "EAB with headerinfo - 04 - Enroll acme with a not allowed fqdn in kid.json (to fail)" + id: acmefail02 + continue-on-error: true + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_02 --eab-hmac-key dGhpc19pc19hX3ZlcnlfbG9uZ19obWFjX3RvX21ha2Vfc3VyZV90aGF0X2l0c19tb3JlX3RoYW5fMjU2X2JpdHM --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv -d acme-sh. --standalone --keylength 2048 --debug 3 --output-insecure + shell: bash + + - name: "EAB with headerinfo - 04 - check result " + if: steps.acmefail02.outcome != 'failure' + run: | + echo "acmefail outcome is ${{steps.acmefail02.outcome }}" + exit 1 + shell: bash + + - name: "EAB with headerinfo - 04 - Enroll lego with a not allowed fqdn in kid.json (to fail)" + id: legofail02 + continue-on-error: true + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_02 --hmac dGhpc19pc19hX3ZlcnlfbG9uZ19obWFjX3RvX21ha2Vfc3VyZV90aGF0X2l0c19tb3JlX3RoYW5fMjU2X2JpdHM -k rsa2048 -d lego.acme --http run + shell: bash + + - name: "EAB with headerinfo - 04a - check result " + if: steps.legofail02.outcome != 'failure' + run: | + echo "legofail outcome is ${{steps.legofail02.outcome }}" + exit 1 + shell: bash + + - name: "EAB with headerinfo - 05 - Enroll acme with default values from acme.cfg" + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_03 --eab-hmac-key YW5kX2ZpbmFsbHlfdGhlX2xhc3RfaG1hY19rZXlfd2hpY2hfaXNfbG9uZ2VyX3RoYW5fMjU2X2JpdHNfYW5kX3Nob3VsZF93b3Jr --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv -d acme-sh.acme --standalone --keylength 2048 --debug 3 --output-insecure + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme/ca.cer + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme/acme-sh.acme.cer + openssl x509 -in acme-sh/acme-sh.acme/acme-sh.acme.cer -text -noout + openssl x509 -in acme-sh/acme-sh.acme/acme-sh.acme.cer -issuer --noout | grep -i sub-ca + shell: bash + + - name: "EAB with headerinfo - 05 - Enroll lego with default values from acme.cfg" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_03 --hmac YW5kX2ZpbmFsbHlfdGhlX2xhc3RfaG1hY19rZXlfd2hpY2hfaXNfbG9uZ2VyX3RoYW5fMjU2X2JpdHNfYW5kX3Nob3VsZF93b3Jr -k rsa2048 -d lego.acme --http run + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -issuer --noout | grep -i sub-ca + shell: bash \ No newline at end of file diff --git a/.github/actions/wf_specific/acme_ca_handler/le-sim_prep/action.yml b/.github/actions/wf_specific/acme_ca_handler/le-sim_prep/action.yml new file mode 100644 index 00000000..a207b839 --- /dev/null +++ b/.github/actions/wf_specific/acme_ca_handler/le-sim_prep/action.yml @@ -0,0 +1,53 @@ +name: "le-sim_prep" +description: "le-sim_prep" +inputs: + LESIM_NAME: + description: "Name of the le-sim" + required: true + default: "le-sim" + NAME_SPACE: + description: "Name space of the le-sim" + required: true + default: "acme" + SECTIGO_SIM: + description: "Sectigo sim" + required: true + default: "false" + +runs: + using: "composite" + steps: + + - name: "Setup le-sim" + run: | + sudo mkdir -p ${{ inputs.LESIM_NAME }}/acme_ca/certs + sudo cp examples/ca_handler/openssl_ca_handler.py ${{ inputs.LESIM_NAME }}/ca_handler.py + sudo cp test/ca/sub-ca-key.pem test/ca/sub-ca-crl.pem test/ca/sub-ca-cert.pem test/ca/root-ca-cert.pem ${{ inputs.LESIM_NAME }}/acme_ca/ + sudo cp .github/openssl_ca_handler.py_acme_srv_choosen_handler.cfg ${{ inputs.LESIM_NAME }}/acme_srv.cfg + sudo chmod 777 ${{ inputs.LESIM_NAME }}/acme_srv.cfg + if [ "${{ inputs.SECTIGO_SIM }}" == "true" ]; then + echo "Sectigo sim enabled" + sudo sed -i "s/challenge_validation_disable: False/challenge_validation_disable: True\nsectigo_sim: True/g" ${{ inputs.LESIM_NAME }}/acme_srv.cfg + fi + sudo sed -i "s/challenge_validation_disable: False/challenge_validation_disable: True/g" ${{ inputs.LESIM_NAME }}/acme_srv.cfg + docker run -d --rm -id --network ${{ inputs.NAME_SPACE }} --name=${{ inputs.LESIM_NAME }} -v "$(pwd)/${{ inputs.LESIM_NAME }}":/var/www/acme2certifier/volume/ grindsa/acme2certifier:apache2-wsgi + cat ${{ inputs.LESIM_NAME }}/acme_srv.cfg + shell: bash + + - name: "Sleep for 10s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 10s + + - name: "Test http://acme-le-sim/directory is accessible" + run: docker run -i --rm --network ${{ inputs.NAME_SPACE }} curlimages/curl -f http://${{ inputs.LESIM_NAME }}/directory + shell: bash + + - name: "Enroll from le-sim" + run: | + mkdir -p acme-sh/ + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http:///${{ inputs.LESIM_NAME }} --accountemail 'acme-sh@example.com' -d acme-sh.acme --standalone --debug 3 --output-insecure --force + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer + sudo rm -rf acme-sh/* + shell: bash \ No newline at end of file diff --git a/.github/actions/wf_specific/acme_ca_handler/smallstep_prep/action.yml b/.github/actions/wf_specific/acme_ca_handler/smallstep_prep/action.yml new file mode 100644 index 00000000..c614973b --- /dev/null +++ b/.github/actions/wf_specific/acme_ca_handler/smallstep_prep/action.yml @@ -0,0 +1,49 @@ +name: "smallstep_prep" +description: "smallstep_prep" + +runs: + using: "composite" + steps: + + - name: "Setup smallstep" + run: | + sudo mkdir -p step + sudo chmod -R 777 step + docker run -d -v "$(pwd)/step":/home/step \ + -p 9000:9000 -p 443:443 \ + --network acme \ + --name step-ca \ + -e "DOCKER_STEPCA_INIT_NAME=Smallstep" \ + -e "DOCKER_STEPCA_INIT_DNS_NAMES=localhost,$(hostname -f)" \ + smallstep/step-ca + shell: bash + + - name: "Sleep for 20s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 20s + + - name: "Configure smallstep" + run: | + docker ps + docker exec -i step-ca step ca provisioner add acme --type ACME + docker exec -i step-ca step ca provisioner update acme --remove-challenge=tls-alpn-01 + docker exec -i step-ca step ca provisioner update acme --remove-challenge=dns-01 + docker restart step-ca + shell: bash + + - name: "Sleep for 20s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 20s + + - name: "Test https://step-ca.acme/acme/acme/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl -f https://step-ca:9000/acme/acme/directory --insecure + shell: bash + + - name: "Enroll from smallstep using acme-sh" + run: | + mkdir -p acme-sh + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server https://step-ca:9000/acme/acme/directory --accountemail 'acme-sh@example.com' -d acme-sh.acme --standalone --debug 3 --insecure --output-insecure --force + sudo rm -rf acme-sh/* + shell: bash \ No newline at end of file diff --git a/.github/actions/wf_specific/asa_ca_handler/enroll_eab_w_headerinfo/action.yml b/.github/actions/wf_specific/asa_ca_handler/enroll_eab_w_headerinfo/action.yml new file mode 100644 index 00000000..bb0c6bf6 --- /dev/null +++ b/.github/actions/wf_specific/asa_ca_handler/enroll_eab_w_headerinfo/action.yml @@ -0,0 +1,206 @@ +name: "enroll_w_headerinfo" +description: "enroll_w_headerinfo" +inputs: + ASA_CA_NAME1: + description: "ASA CA 1" + required: true + ASA_CA_NAME2: + description: "ASA CA 2" + required: true + +runs: + using: "composite" + steps: + - name: "EAB with headerinfo - Sleep for 10s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 10s + + - name: "EAB with headerinfo - Test http://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory + shell: bash + + - name: "EAB with headerinfo - Test if https://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory + shell: bash + + - name: "EAB with headerinfo - 01 - Enroll acme.sh without profile_name" + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_00 --eab-hmac-key V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv -d acme-sh.acme --standalone --keylength 2048 --debug 3 --output-insecure + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme/ca.cer + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme/acme-sh.acme.cer + openssl x509 -in acme-sh/acme-sh.acme/acme-sh.acme.cer -text -noout + openssl x509 -in acme-sh/acme-sh.acme/acme-sh.acme.cer -issuer --noout | grep -i "${{ inputs.ASA_CA_NAME1 }}" + openssl x509 -in acme-sh/acme-sh.acme/acme-sh.acme.cer -ext keyUsage -noout | grep -i "Key Encipherment, Data Encipherment" + shell: bash + + - name: "EAB with headerinfo - 01 - Enroll lego without profile_name" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw -k rsa2048 -d lego.acme --http run + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -issuer --noout | grep -i "${{ inputs.ASA_CA_NAME1 }}" + sudo openssl x509 -in lego/certificates/lego.acme.crt -ext keyUsage -noout | grep -i "Key Encipherment, Data Encipherment" + shell: bash + + - name: "EAB with headerinfo - 02a - Enroll acme with a profile_name taken from header_info NOT included in kid.json (to fail)" + id: acmefail01 + continue-on-error: true + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_00 --eab-hmac-key V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv --useragent profile_name=unknown -d acme-sh.acme --standalone --keylength 2048 --debug 3 --output-insecure + shell: bash + + - name: "EAB with headerinfo - 02a - check result " + if: steps.acmefail01.outcome != 'failure' + run: | + echo "acmefail outcome is ${{steps.acmefail01.outcome }}" + exit 1 + shell: bash + + - name: "EAB with headerinfo - 02b - Enroll acme with a profile_name taken from header_info included in kid.json" + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_00 --eab-hmac-key V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv --useragent profile_name=ACME -d acme-sh.acme --standalone --keylength 2048 --debug 3 --output-insecure + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme/ca.cer + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme/acme-sh.acme.cer + openssl x509 -in acme-sh/acme-sh.acme/acme-sh.acme.cer -text -noout + openssl x509 -in acme-sh/acme-sh.acme/acme-sh.acme.cer -issuer --noout | grep -i "${{ inputs.ASA_CA_NAME1 }}" + openssl x509 -in acme-sh/acme-sh.acme/acme-sh.acme.cer -ext keyUsage -noout | grep "Digital Signature" + shell: bash + + - name: "EAB with headerinfo - 02a - Enroll lego with a profile_name taken from header_info NOT included in kid.json (to fail)" + id: legofail01 + continue-on-error: true + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --user-agent profile_name=unknown -k rsa2048 -d lego.acme --http run + shell: bash + + - name: "EAB with headerinfo - 02a - check result " + if: steps.legofail01.outcome != 'failure' + run: | + echo "legofail outcome is ${{steps.legofail01.outcome }}" + exit 1 + shell: bash + + - name: "EAB with headerinfo - 02b - Enroll lego with a profile_name taken from header_info included in kid.json" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --user-agent profile_name=ACME -k rsa2048 -d lego.acme --http run + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -issuer --noout | grep -i "${{ inputs.ASA_CA_NAME1 }}" + sudo openssl x509 -in lego/certificates/lego.acme.crt -ext keyUsage -noout | grep "Digital Signature" + shell: bash + + - name: "EAB with headerinfo - 03 - Enroll acme with a profile_name/ca_name taken from kid.json" + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_01 --eab-hmac-key YW5vdXRoZXJfdmVyeV9sb25nX2htYWNfZm9yX2tleWlkXzAxX3doaWNoIHdpbGxfYmUgdXNlZF9kdXJpbmcgcmVncmVzc2lvbg --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv -d acme-sh.acme --standalone --keylength 2048 --debug 3 --output-insecure + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme/ca.cer + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme/acme-sh.acme.cer + openssl x509 -in acme-sh/acme-sh.acme/acme-sh.acme.cer -text -noout + openssl x509 -in acme-sh/acme-sh.acme/acme-sh.acme.cer -issuer --noout | grep -i "${{ inputs.ASA_CA_NAME2 }}" + openssl x509 -in acme-sh/acme-sh.acme/acme-sh.acme.cer -ext keyUsage -noout | grep -i "Digital Signature" + shell: bash + + - name: "EAB with headerinfo - 03 - Enroll lego with a profile_name/ca_name taken from kid.json" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_01 --hmac YW5vdXRoZXJfdmVyeV9sb25nX2htYWNfZm9yX2tleWlkXzAxX3doaWNoIHdpbGxfYmUgdXNlZF9kdXJpbmcgcmVncmVzc2lvbg -k rsa2048 -d lego.acme --http run + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -issuer --noout | grep -i "${{ inputs.ASA_CA_NAME2 }}" + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -ext keyUsage | grep -i "Digital Signature" + shell: bash + + - name: "EAB with headerinfo - 04 - Enroll acme with a not allowed fqdn in kid.json (to fail)" + id: acmefail021 + continue-on-error: true + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_02 --eab-hmac-key dGhpc19pc19hX3ZlcnlfbG9uZ19obWFjX3RvX21ha2Vfc3VyZV90aGF0X2l0c19tb3JlX3RoYW5fMjU2X2JpdHM --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv -d acme-sh.acme --standalone --keylength 2048 --debug 3 --output-insecure + shell: bash + + - name: "EAB with headerinfo - 04 - check result " + if: steps.acmefail021.outcome != 'failure' + run: | + echo "acmefail outcome is ${{steps.acmefail021.outcome }}" + exit 1 + shell: bash + + - name: "EAB with headerinfo - 04 - Enroll lego with a not allowed fqdn in kid.json (to fail)" + id: legofail021 + continue-on-error: true + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_02 --hmac dGhpc19pc19hX3ZlcnlfbG9uZ19obWFjX3RvX21ha2Vfc3VyZV90aGF0X2l0c19tb3JlX3RoYW5fMjU2X2JpdHM -k rsa2048 -d lego.acme --http run + shell: bash + + - name: "EAB with headerinfo - 04a - check result " + if: steps.legofail021.outcome != 'failure' + run: | + echo "legofail outcome is ${{steps.legofail021.outcome }}" + exit 1 + shell: bash + + - name: "EAB with headerinfo - 05 - Enroll acme with default values from acme.cfg" + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_03 --eab-hmac-key YW5kX2ZpbmFsbHlfdGhlX2xhc3RfaG1hY19rZXlfd2hpY2hfaXNfbG9uZ2VyX3RoYW5fMjU2X2JpdHNfYW5kX3Nob3VsZF93b3Jr --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv -d acme-sh.acme --standalone --keylength 2048 --debug 3 --output-insecure + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme/ca.cer + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme/acme-sh.acme.cer + openssl x509 -in acme-sh/acme-sh.acme/acme-sh.acme.cer -text -noout + openssl x509 -in acme-sh/acme-sh.acme/acme-sh.acme.cer -issuer --noout | grep -i "${{ inputs.ASA_CA_NAME1 }}" + openssl x509 -in acme-sh/acme-sh.acme/acme-sh.acme.cer -ext keyUsage -noout | grep "Digital Signature" + shell: bash + + - name: "EAB with headerinfo - 05 - Enroll lego with default values from acme.cfg" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_03 --hmac YW5kX2ZpbmFsbHlfdGhlX2xhc3RfaG1hY19rZXlfd2hpY2hfaXNfbG9uZ2VyX3RoYW5fMjU2X2JpdHNfYW5kX3Nob3VsZF93b3Jr -k rsa2048 -d lego.acme --http run + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -issuer --noout | grep -i "${{ inputs.ASA_CA_NAME1 }}" + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -ext keyUsage | grep "Digital Signature" + shell: bash + + - name: "EAB with headerinfo - 06 - Enroll acme with not allowed headerinfo-field (should fail)" + id: acmefail03 + continue-on-error: true + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_02 --eab-hmac-key dGhpc19pc19hX3ZlcnlfbG9uZ19obWFjX3RvX21ha2Vfc3VyZV90aGF0X2l0c19tb3JlX3RoYW5fMjU2X2JpdHM --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv --useragent profile_id=101 -d acme-sh.acme --keylength 2048 --standalone --debug 3 --output-insecure + shell: bash + + - name: "EAB with headerinfo - 06 - check result " + if: steps.acmefail03.outcome != 'failure' + run: | + echo "acmefail outcome is ${{steps.acmefail03.outcome }}" + exit 1 + shell: bash + + - name: "EAB with headerinfo - 06 - Enroll lego with not allowed headerinfo-field (should fail)" + id: legofail03 + continue-on-error: true + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_02 --hmac dGhpc19pc19hX3ZlcnlfbG9uZ19obWFjX3RvX21ha2Vfc3VyZV90aGF0X2l0c19tb3JlX3RoYW5fMjU2X2JpdHM --user-agent profile_id=101 -k rsa2048 -d lego.acme --http run + shell: bash + + - name: "EAB with headerinfo - 06 - check result " + if: steps.legofail03.outcome != 'failure' + run: | + echo "legofail outcome is ${{steps.legofail03.outcome }}" + exit 1 + shell: bash diff --git a/.github/actions/wf_specific/asa_ca_handler/enroll_eab_wo_headerinfo/action.yml b/.github/actions/wf_specific/asa_ca_handler/enroll_eab_wo_headerinfo/action.yml new file mode 100644 index 00000000..96956930 --- /dev/null +++ b/.github/actions/wf_specific/asa_ca_handler/enroll_eab_wo_headerinfo/action.yml @@ -0,0 +1,143 @@ +name: "enroll_wo_headerinfo" +description: "enroll_wo_headerinfo" +inputs: + ASA_CA_NAME1: + description: "ASA CA 1" + required: true + ASA_CA_NAME2: + description: "ASA CA 2" + required: true + +runs: + using: "composite" + steps: + - name: "EAB without headerinfo - Sleep for 10s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 10s + + - name: "EAB without headerinfo - Test http://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory + shell: bash + + - name: "EAB without headerinfo - Test if https://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory + shell: bash + + - name: "EAB without headerinfo - 01 - Enroll acme.sh without profile_name" + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_00 --eab-hmac-key V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv -d acme-sh.acme --standalone --keylength 2048 --debug 3 --output-insecure + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme/ca.cer + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme/acme-sh.acme.cer + openssl x509 -in acme-sh/acme-sh.acme/acme-sh.acme.cer -text -noout + openssl x509 -in acme-sh/acme-sh.acme/acme-sh.acme.cer -issuer --noout | grep -i "${{ inputs.ASA_CA_NAME1 }}" + openssl x509 -in acme-sh/acme-sh.acme/acme-sh.acme.cer -ext keyUsage -noout | grep -i "Key Encipherment, Data Encipherment" + shell: bash + + - name: "EAB without headerinfo - 01 - Enroll lego without profile_name" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw -k rsa2048 -d lego.acme --http run + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -issuer --noout | grep -i "${{ inputs.ASA_CA_NAME1 }}" + sudo openssl x509 -in lego/certificates/lego.acme.crt -ext keyUsage -noout | grep -i "Key Encipherment, Data Encipherment" + shell: bash + + - name: "EAB without headerinfo - 02 - Enroll acme with a profile_name taken from header_info NOT included in kid.json (to be ignored)" + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_00 --eab-hmac-key V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv --useragent profile_name=unknown -d acme-sh.acme --standalone --keylength 2048 --debug 3 --output-insecure + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme/acme-sh.acme.cer + openssl x509 -in acme-sh/acme-sh.acme/acme-sh.acme.cer -text -noout + openssl x509 -in acme-sh/acme-sh.acme/acme-sh.acme.cer -issuer --noout | grep -i "${{ inputs.ASA_CA_NAME1 }}" + openssl x509 -in acme-sh/acme-sh.acme/acme-sh.acme.cer -ext keyUsage -noout | grep -i "Key Encipherment, Data Encipherment" + shell: bash + + - name: "EAB without headerinfo - 02 - Enroll lego with a profile_name taken from header_info NOT included in kid.json (to be ignored)" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --user-agent profile_name=unknown -k rsa2048 -d lego.acme --http run + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -issuer --noout | grep -i "${{ inputs.ASA_CA_NAME1 }}" + sudo openssl x509 -in lego/certificates/lego.acme.crt -ext keyUsage -noout | grep "Key Encipherment, Data Encipherment" + shell: bash + + - name: "EAB without headerinfo - 03 - Enroll acme with a profile_name/ca_name taken from kid.json" + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_01 --eab-hmac-key YW5vdXRoZXJfdmVyeV9sb25nX2htYWNfZm9yX2tleWlkXzAxX3doaWNoIHdpbGxfYmUgdXNlZF9kdXJpbmcgcmVncmVzc2lvbg --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv -d acme-sh.acme --standalone --keylength 2048 --debug 3 --output-insecure + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme/ca.cer + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme/acme-sh.acme.cer + openssl x509 -in acme-sh/acme-sh.acme/acme-sh.acme.cer -text -noout + openssl x509 -in acme-sh/acme-sh.acme/acme-sh.acme.cer -issuer --noout | grep -i "${{ inputs.ASA_CA_NAME2 }}" + openssl x509 -in acme-sh/acme-sh.acme/acme-sh.acme.cer -ext keyUsage -noout | grep -i "Digital Signature" + shell: bash + + - name: "EAB without headerinfo - 03 - Enroll lego with a profile_name/ca_name taken from kid.json" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_01 --hmac YW5vdXRoZXJfdmVyeV9sb25nX2htYWNfZm9yX2tleWlkXzAxX3doaWNoIHdpbGxfYmUgdXNlZF9kdXJpbmcgcmVncmVzc2lvbg -k rsa2048 -d lego.acme --http run + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -issuer --noout | grep -i "${{ inputs.ASA_CA_NAME2 }}" + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -ext keyUsage | grep -i "Digital Signature" + shell: bash + + - name: "EAB without headerinfo - 04 - Enroll acme with a not allowed fqdn in kid.json (to fail)" + id: acmefail02 + continue-on-error: true + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_02 --eab-hmac-key dGhpc19pc19hX3ZlcnlfbG9uZ19obWFjX3RvX21ha2Vfc3VyZV90aGF0X2l0c19tb3JlX3RoYW5fMjU2X2JpdHM --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv -d acme-sh.acme --standalone --keylength 2048 --debug 3 --output-insecure + shell: bash + + - name: "EAB without headerinfo - 04 - check result " + if: steps.acmefail02.outcome != 'failure' + run: | + echo "acmefail outcome is ${{steps.acmefail02.outcome }}" + exit 1 + shell: bash + + - name: "EAB without headerinfo - 04 - Enroll lego with a not allowed fqdn in kid.json (to fail)" + id: legofail02 + continue-on-error: true + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_02 --hmac dGhpc19pc19hX3ZlcnlfbG9uZ19obWFjX3RvX21ha2Vfc3VyZV90aGF0X2l0c19tb3JlX3RoYW5fMjU2X2JpdHM -k rsa2048 -d lego.acme --http run + shell: bash + + - name: "EAB without headerinfo - 04a - check result " + if: steps.legofail02.outcome != 'failure' + run: | + echo "legofail outcome is ${{steps.legofail02.outcome }}" + exit 1 + shell: bash + + - name: "EAB without headerinfo - 05 - Enroll acme with default values from acme.cfg" + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_03 --eab-hmac-key YW5kX2ZpbmFsbHlfdGhlX2xhc3RfaG1hY19rZXlfd2hpY2hfaXNfbG9uZ2VyX3RoYW5fMjU2X2JpdHNfYW5kX3Nob3VsZF93b3Jr --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv -d acme-sh.acme --standalone --keylength 2048 --debug 3 --output-insecure + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme/ca.cer + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme/acme-sh.acme.cer + openssl x509 -in acme-sh/acme-sh.acme/acme-sh.acme.cer -text -noout + openssl x509 -in acme-sh/acme-sh.acme/acme-sh.acme.cer -issuer --noout | grep -i "${{ inputs.ASA_CA_NAME1 }}" + openssl x509 -in acme-sh/acme-sh.acme/acme-sh.acme.cer -ext keyUsage -noout | grep "Digital Signature" + shell: bash + + - name: "EAB without headerinfo - 05 - Enroll lego with default values from acme.cfg" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_03 --hmac YW5kX2ZpbmFsbHlfdGhlX2xhc3RfaG1hY19rZXlfd2hpY2hfaXNfbG9uZ2VyX3RoYW5fMjU2X2JpdHNfYW5kX3Nob3VsZF93b3Jr -k rsa2048 -d lego.acme --http run + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -issuer --noout | grep -i "${{ inputs.ASA_CA_NAME1 }}" + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -ext keyUsage | grep "Digital Signature" + shell: bash \ No newline at end of file diff --git a/.github/actions/wf_specific/asa_ca_handler/enroll_headerinfo/action.yml b/.github/actions/wf_specific/asa_ca_handler/enroll_headerinfo/action.yml new file mode 100644 index 00000000..d5c6e75a --- /dev/null +++ b/.github/actions/wf_specific/asa_ca_handler/enroll_headerinfo/action.yml @@ -0,0 +1,63 @@ +name: "enroll_102_profile" +description: "wf enrollment 102 profile" +inputs: + ASA_PROFILE1: + description: "ASA Profile 1" + required: true + ASA_PROFILE2: + description: "ASA Profile 2" + required: true + +runs: + using: "composite" + steps: + - name: "Sleep for 10s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 10s + + - name: "Header-info - Test http://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory + shell: bash + + - name: "Header-info - Test if https://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory + shell: bash + + - name: "Header-info - 01 - Enroll acme.sh with Profile 1" + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv --accountemail 'acme-sh@example.com' --useragent profile_name=${{ inputs.ASA_PROFILE1 }} -d acme-sh.acme --alpn --standalone --keylength 2048 --debug 3 --output-insecure + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme/ca.cer + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme/acme-sh.acme.cer + openssl x509 -in acme-sh/acme-sh.acme/acme-sh.acme.cer -texte -noout + openssl x509 -in acme-sh/acme-sh.acme/acme-sh.acme.cer -ext keyUsage -noout | grep "Digital Signature" + shell: bash + + - name: "Header-info - 01 - Enroll lego with Profile 1" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --user-agent profile_name=${{ inputs.ASA_PROFILE1 }} -d lego.acme --key-type rsa2048 --http run + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -ext keyUsage -noout | grep "Digital Signature" + shell: bash + + - name: "Header-info - 02 - Enroll acme.sh with Profile 2" + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv --accountemail 'acme-sh@example.com' --useragent profile_name=${{ inputs.ASA_PROFILE2 }} -d acme-sh.acme --alpn --standalone --keylength 2048 --debug 3 --output-insecure + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme/ca.cer + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme/acme-sh.acme.cer + openssl x509 -in acme-sh/acme-sh.acme/acme-sh.acme.cer -texte -noout + openssl x509 -in acme-sh/acme-sh.acme/acme-sh.acme.cer -ext keyUsage -noout | grep "Key Encipherment, Data Encipherment" + shell: bash + + - name: "Header-info - 02 - Enroll lego with Profile 2" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --user-agent profile_name=${{ inputs.ASA_PROFILE2 }} -d lego.acme --key-type rsa2048 --http run + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + # sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -ext keyUsage -noout | grep "Key Encipherment, Data Encipherment" + shell: bash \ No newline at end of file diff --git a/.github/actions/wf_specific/asa_ca_handler/enroll_profile_1/action.yml b/.github/actions/wf_specific/asa_ca_handler/enroll_profile_1/action.yml new file mode 100644 index 00000000..456c5a71 --- /dev/null +++ b/.github/actions/wf_specific/asa_ca_handler/enroll_profile_1/action.yml @@ -0,0 +1,61 @@ +name: "enroll_profile_1" +description: "wf enroll_profile_1" +runs: + using: "composite" + steps: + - name: "Profile 1 - Sleep for 10s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 10s + + - name: "Profile 1 - Test http://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory + shell: bash + + - name: "Profile 1 - Test if https://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory + shell: bash + + - name: "Profile 1 - Enroll acme.sh" + run: | + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv --accountemail 'acme-sh@example.com' -d acme-sh.acme --alpn --standalone --keylength 2048 --debug 3 --output-insecure + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme/ca.cer + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme/acme-sh.acme.cer + openssl x509 -in acme-sh/acme-sh.acme/acme-sh.acme.cer -ext keyUsage -noout | grep "Digital Signature" + shell: bash + + - name: "Profile 1 - Revoke via acme.sh" + run: | + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --revoke --server http://acme-srv -d acme-sh.acme --standalone --debug 3 --output-insecure + shell: bash + + - name: "Profile 1 - Register certbot" + run: | + docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email + shell: bash + + - name: "Profile 1 - Enroll HTTP-01 single domain certbot" + run: | + docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot --key-type rsa --rsa-key-size 2048 + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem + sudo openssl x509 -in certbot/live/certbot/cert.pem -ext keyUsage -noout | grep "Digital Signature" + # sudo openssl x509 -in certbot/live/certbot/cert.pem -text -noout + shell: bash + + - name: "Profile 1 - Revoke HTTP-01 single domain certbot" + run: | + docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot revoke --delete-after-revoke --server http://acme-srv -d certbot.acme --cert-name certbot + shell: bash + + - name: "Profile 1 - Enroll lego" + run: | + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --key-type rsa2048 --http run + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl x509 -in lego/certificates/lego.acme.crt -ext keyUsage -noout | grep "Digital Signature" + # sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + shell: bash + + - name: "Profile 1 - revoke HTTP-01 single domain lego" + run: | + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme revoke + shell: bash diff --git a/.github/actions/wf_specific/asa_ca_handler/enroll_profile_2/action.yml b/.github/actions/wf_specific/asa_ca_handler/enroll_profile_2/action.yml new file mode 100644 index 00000000..ad08ac92 --- /dev/null +++ b/.github/actions/wf_specific/asa_ca_handler/enroll_profile_2/action.yml @@ -0,0 +1,59 @@ +name: "enroll_2_profile" +description: "wf enrollment 2 profile" + +runs: + using: "composite" + steps: + - name: "Profile 2 - Sleep for 10s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 10s + + - name: "Profile 2 - create letsencrypt and lego folder" + run: | + sudo rm -rf certbot/* + sudo rm -rf lego/* + sudo rm -rf acme-sh/* + shell: bash + + - name: "Profile 2 - Enroll acme.sh" + run: | + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv --accountemail 'acme-sh@example.com' -d acme-sh.acme --alpn --standalone --keylength 2048 --debug 3 --output-insecure + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme/ca.cer + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme/acme-sh.acme.cer + openssl x509 -in acme-sh/acme-sh.acme/acme-sh.acme.cer -ext keyUsage -noout | grep "Key Encipherment, Data Encipherment" + shell: bash + + - name: "Profile 2 - Revoke via acme.sh" + run: | + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --revoke --server http://acme-srv -d acme-sh.acme --standalone --debug 3 --output-insecure + shell: bash + + - name: "Profile 2 - Register certbot" + run: | + docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email + shell: bash + + - name: "Profile 2 - Enroll HTTP-01 single domain certbot" + run: | + docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot --force-renewal --key-type rsa --rsa-key-size 2048 + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem + sudo openssl x509 -in certbot/live/certbot/cert.pem -ext keyUsage -noout | grep "Key Encipherment, Data Encipherment" + shell: bash + + - name: "Profile 2 - Revoke HTTP-01 single domain certbot" + run: | + docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot revoke --delete-after-revoke --server http://acme-srv -d certbot.acme --cert-name certbot + shell: bash + + - name: "Profile 2 - Enroll lego" + run: | + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --key-type rsa2048 --http run + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl x509 -in lego/certificates/lego.acme.crt -ext keyUsage -noout | grep "Key Encipherment, Data Encipherment" + shell: bash + + - name: "Profile 2 - Revoke HTTP-01 single domain lego" + run: | + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme revoke + shell: bash diff --git a/.github/actions/wf_specific/certifier_ca_handler/certifier_setup_no_profile/action.yml b/.github/actions/wf_specific/certifier_ca_handler/certifier_setup_no_profile/action.yml new file mode 100644 index 00000000..ad1ebd31 --- /dev/null +++ b/.github/actions/wf_specific/certifier_ca_handler/certifier_setup_no_profile/action.yml @@ -0,0 +1,81 @@ +name: "certifier_setup_no_profile" +description: "certifier_setup_no_profile" +inputs: + WCCE_SSH_ACCESS_KEY: + description: "SSH access key" + required: true + WCCE_SSH_KNOWN_HOSTS: + description: "SSH known hosts" + required: true + WCCE_SSH_USER: + description: "SSH user" + required: true + WCCE_SSH_HOST: + description: "SSH host" + required: true + WCCE_SSH_PORT: + description: "SSH port" + required: true + NAME_SPACE: + description: "namespace" + required: true + default: "acme" + NCM_API_HOST: + description: "NCM API host" + required: true + NCM_API_USER: + description: "NCM API user" + required: true + NCM_API_PASSWORD: + description: "NCM API password" + required: true + ACME_SRV_CFG: + description: "acme_srv.cfg" + required: true + default: "acme_srv.cfg" + DATA_PATH: + description: "data path" + required: true + ACME_SRV_SRC: + description: "acme_srv.cfg source file" + required: true + default: ".github/openssl_ca_handler.py_acme_srv_default_handler.cfg" + +runs: + using: "composite" + steps: + - name: "Setup tunnel" + uses: ./.github/actions/wf_specific/certifier_ca_handler/tunnel_setup + with: + WCCE_SSH_USER: ${{ inputs.WCCE_SSH_USER }} + WCCE_SSH_HOST: ${{ inputs.WCCE_SSH_HOST }} + WCCE_SSH_PORT: ${{ inputs.WCCE_SSH_PORT }} + NCM_API_HOST: ${{ inputs.NCM_API_HOST }} + WCCE_SSH_KNOWN_HOSTS: ${{ inputs.WCCE_SSH_KNOWN_HOSTS }} + WCCE_SSH_ACCESS_KEY: ${{ inputs.WCCE_SSH_ACCESS_KEY }} + NCM_API_USER: ${{ inputs.NCM_API_USER }} + NCM_API_PASSWORD: ${{ inputs.NCM_API_PASSWORD }} + + - name: "Setup a2c with certifier_ca_handler" + run: | + sudo cp .github/openssl_ca_handler.py_acme_srv_default_handler.cfg $DATA_PATH/$ACME_SRV_CFG + sudo chmod 777 $DATA_PATH/$ACME_SRV_CFG + sudo cp test/ca/certsrv_ca_certs.pem $DATA_PATH/ca_certs.pem + sudo head -n -8 $ACME_SRV_SRC > $DATA_PATH/$ACME_SRV_CFG + sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> $DATA_PATH/$ACME_SRV_CFG + sudo echo "api_host: https://forwarder.acme:8084" >> $DATA_PATH/$ACME_SRV_CFG + sudo echo "ca_bundle: False" >> $DATA_PATH/$ACME_SRV_CFG + sudo echo "api_user: $NCM_API_USER" >> $DATA_PATH/$ACME_SRV_CFG + sudo echo "api_password: $NCM_API_PASSWORD" >> $DATA_PATH/$ACME_SRV_CFG + sudo echo "ca_name: $NCM_CA_NAME" >> $DATA_PATH/$ACME_SRV_CFG + # sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> $DATA_PATH/$ACME_SRV_CFG + env: + NCM_API_HOST: ${{ inputs.NCM_API_HOST }} + NCM_API_USER: ${{ inputs.NCM_API_USER }} + NCM_API_PASSWORD: ${{ inputs.NCM_API_PASSWORD }} + NCM_CA_NAME: ${{ inputs.NCM_CA_NAME }} + NCM_CA_BUNDLE: ${{ inputs.NCM_CA_BUNDLE }} + DATA_PATH: ${{ inputs.DATA_PATH }} + ACME_SRV_CFG: ${{ inputs.ACME_SRV_CFG }} + ACME_SRV_SRC: ${{ inputs.ACME_SRV_SRC }} + shell: bash \ No newline at end of file diff --git a/.github/actions/wf_specific/certifier_ca_handler/enroll_101_profile/action.yml b/.github/actions/wf_specific/certifier_ca_handler/enroll_101_profile/action.yml new file mode 100644 index 00000000..69cc9627 --- /dev/null +++ b/.github/actions/wf_specific/certifier_ca_handler/enroll_101_profile/action.yml @@ -0,0 +1,61 @@ +name: "enroll_101_profile" +description: "wf enrollment 101 profile" + +runs: + using: "composite" + steps: + - name: "Profile 101 - Sleep for 10s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 10s + + - name: "Profile 101 - Test http://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory + shell: bash + + - name: "Profile 101 - Test if https://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory + shell: bash + + - name: "Profile 101 - Enroll acme.sh" + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv --accountemail 'acme-sh@example.com' -d acme-sh.acme --alpn --standalone --debug 3 --output-insecure + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer + shell: bash + + - name: "Profile 101 - Revoke via acme.sh" + run: | + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --revoke --server http://acme-srv -d acme-sh.acme --standalone --debug 3 --output-insecure + shell: bash + + - name: "Profile 101 - Register certbot" + run: | + sudo rm -rf certbot/* + docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email + shell: bash + + - name: "Profile 101 - Enroll HTTP-01 single domain certbot" + run: | + docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem + sudo openssl x509 -in certbot/live/certbot/cert.pem -ext extendedKeyUsage -noout | grep -i "TLS Web Client" + shell: bash + + - name: "Profile 101 - Revoke HTTP-01 single domain certbot" + run: | + docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot revoke --delete-after-revoke --server http://acme-srv -d certbot.acme --cert-name certbot + shell: bash + + - name: "Profile 101 - Enroll lego" + run: | + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --http run + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl x509 -in lego/certificates/lego.acme.crt -ext extendedKeyUsage -noout | grep -i "TLS Web Client" + shell: bash + + - name: "Profile 101 - Revoke HTTP-01 single domain lego" + run: | + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme revoke + shell: bash \ No newline at end of file diff --git a/.github/actions/wf_specific/certifier_ca_handler/enroll_102_profile/action.yml b/.github/actions/wf_specific/certifier_ca_handler/enroll_102_profile/action.yml new file mode 100644 index 00000000..9362a05f --- /dev/null +++ b/.github/actions/wf_specific/certifier_ca_handler/enroll_102_profile/action.yml @@ -0,0 +1,61 @@ +name: "enroll_102_profile" +description: "wf enrollment 102 profile" + +runs: + using: "composite" + steps: + - name: "Profile 102 - Sleep for 10s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 10s + + - name: "Profile 102 - Test http://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory + shell: bash + + - name: "Profile 102 - Test if https://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory + shell: bash + + - name: "Profile 102 - Enroll acme.sh" + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv --accountemail 'acme-sh@example.com' -d acme-sh.acme --alpn --standalone --debug 3 --output-insecure + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer + shell: bash + + - name: "Profile 102 - Revoke via acme.sh" + run: | + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --revoke --server http://acme-srv -d acme-sh.acme --standalone --debug 3 --output-insecure + shell: bash + + - name: "Profile 102 - Register certbot" + run: | + sudo rm -rf certbot/* + docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email + shell: bash + + - name: "Profile 102 - Enroll HTTP-01 single domain certbot" + run: | + docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem + sudo openssl x509 -in certbot/live/certbot/cert.pem -ext extendedKeyUsage -noout | grep -i "TLS Web Server" + shell: bash + + - name: "Profile 102 - Revoke HTTP-01 single domain certbot" + run: | + docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot revoke --delete-after-revoke --server http://acme-srv -d certbot.acme --cert-name certbot + shell: bash + + - name: "Profile 102 - Enroll lego" + run: | + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --http run + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl x509 -in lego/certificates/lego.acme.crt -ext extendedKeyUsage -noout | grep -i "TLS Web Server" + shell: bash + + - name: "Profile 102 - Revoke HTTP-01 single domain lego" + run: | + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme revoke + shell: bash \ No newline at end of file diff --git a/.github/actions/wf_specific/certifier_ca_handler/enroll_eab_w_headerinfo/action.yml b/.github/actions/wf_specific/certifier_ca_handler/enroll_eab_w_headerinfo/action.yml new file mode 100644 index 00000000..45f98fa9 --- /dev/null +++ b/.github/actions/wf_specific/certifier_ca_handler/enroll_eab_w_headerinfo/action.yml @@ -0,0 +1,219 @@ +name: "enroll_102_profile" +description: "wf enrollment 102 profile" +inputs: + RECONFIGURE: + description: "Reconfigure the workflow" + required: true + default: "false" + +runs: + using: "composite" + steps: + - name: "EAB with headerinfo - Sleep for 10s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 10s + + - name: "EAB with headerinfo - Test http://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory + shell: bash + + - name: "EAB with headerinfo - Test if https://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory + shell: bash + + - name: "EAB with headerinfo - 01 - Enroll acme.sh without profile_id" + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_00 --eab-hmac-key V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv -d acme-sh.acme --standalone --debug 3 --output-insecure + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -text -noout + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -ext extendedKeyUsage -noout | grep -i "TLS Web Server Authentication" + shell: bash + + - name: "EAB with headerinfo - 01 - Enroll lego without profile_id" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw -d lego.acme --http run + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -ext extendedKeyUsage -noout | grep -i "TLS Web Server Authentication" + shell: bash + + - name: "EAB with headerinfo - 02a - Enroll acme with a template_name taken from header_info NOT included in kid.json (to fail)" + id: acmefail01 + continue-on-error: true + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_00 --eab-hmac-key V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv --useragent profile_id=unknown -d acme-sh.acme --standalone --debug 3 --output-insecure + shell: bash + + - name: "EAB with headerinfo - 02a - check result " + if: steps.acmefail01.outcome != 'failure' + run: | + echo "acmefail outcome is ${{steps.acmefail01.outcome }}" + exit 1 + shell: bash + + - name: "EAB with headerinfo - 02b - Enroll acme with a template_name taken from header_info included in kid.json" + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_00 --eab-hmac-key V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv --useragent profile_id=101 -d acme-sh.acme --standalone --debug 3 --output-insecure + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -text -noout + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -ext extendedKeyUsage -noout | grep "TLS Web Client Authentication" + shell: bash + + - name: "EAB with headerinfo - 02a - Enroll lego with a template_name taken from header_info NOT included in kid.json (to fail)" + id: legofail01 + continue-on-error: true + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --user-agent profile_id=unknown -d lego.acme --http run + shell: bash + + - name: "EAB with headerinfo - 02a - check result " + if: steps.legofail01.outcome != 'failure' + run: | + echo "legofail outcome is ${{steps.legofail01.outcome }}" + exit 1 + shell: bash + + - name: "EAB with headerinfo - 02b - Enroll lego with a template_name taken from header_info included in kid.json" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --user-agent profile_id=101 -d lego.acme --http run + sudo openssl x509 -in lego/certificates/lego.acme.crt -ext extendedKeyUsage -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -issuer --noout + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -ext extendedKeyUsage | grep "TLS Web Client Authentication" + shell: bash + + - name: "EAB with headerinfo - 03 - Enroll acme with a template_name/ca_name taken from kid.json" + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_01 --eab-hmac-key YW5vdXRoZXJfdmVyeV9sb25nX2htYWNfZm9yX2tleWlkXzAxX3doaWNoIHdpbGxfYmUgdXNlZF9kdXJpbmcgcmVncmVzc2lvbg --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv -d acme-sh.acme --standalone --debug 3 --output-insecure + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -text -noout + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -ext extendedKeyUsage -noout | grep "TLS Web Server Authentication" + shell: bash + + - name: "EAB with headerinfo - 03 - Enroll lego with a template_name/ca_name taken from kid.json" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_01 --hmac YW5vdXRoZXJfdmVyeV9sb25nX2htYWNfZm9yX2tleWlkXzAxX3doaWNoIHdpbGxfYmUgdXNlZF9kdXJpbmcgcmVncmVzc2lvbg -d lego.acme --http run + sudo openssl x509 -in lego/certificates/lego.acme.crt -ext extendedKeyUsage -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -issuer --noout + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -ext extendedKeyUsage | grep "TLS Web Server Authentication" + shell: bash + + - name: "EAB with headerinfo - 04 - Enroll acme with a not allowed fqdn in kid.json (to fail)" + if: ${{ inputs.RECONFIGURE == 'false' }} + id: acmefail02 + continue-on-error: true + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_02 --eab-hmac-key dGhpc19pc19hX3ZlcnlfbG9uZ19obWFjX3RvX21ha2Vfc3VyZV90aGF0X2l0c19tb3JlX3RoYW5fMjU2X2JpdHM --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv -d acme-sh.acme --standalone --debug 3 --output-insecure + shell: bash + + - name: "EAB with headerinfo - 04 - check result " + if: ${{ (inputs.RECONFIGURE == 'false') && (steps.acmefail02.outcome != 'failure') }} + run: | + echo "acmefail outcome is ${{steps.acmefail02.outcome }}" + exit 1 + shell: bash + + - name: "EAB with headerinfo - 04 - Enroll acme with a allowed fqdn after reconfiguration" + if: ${{ inputs.RECONFIGURE == 'true' }} + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_02 --eab-hmac-key dGhpc19pc19hX3ZlcnlfbG9uZ19obWFjX3RvX21ha2Vfc3VyZV90aGF0X2l0c19tb3JlX3RoYW5fMjU2X2JpdHM --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv -d acme-sh.acme --standalone --debug 3 --output-insecure + shell: bash + + - name: "EAB with headerinfo - 04 - Enroll lego with a not allowed fqdn in kid.json (to fail)" + if: ${{ inputs.RECONFIGURE == 'false' }} + id: legofail02 + continue-on-error: true + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_02 --hmac dGhpc19pc19hX3ZlcnlfbG9uZ19obWFjX3RvX21ha2Vfc3VyZV90aGF0X2l0c19tb3JlX3RoYW5fMjU2X2JpdHM -d lego.acme --http run + shell: bash + + - name: "EAB with headerinfo - 04a - check result" + if: ${{ (inputs.RECONFIGURE == 'false') && (steps.legofail02.outcome != 'failure') }} + run: | + echo "legofail outcome is ${{steps.legofail02.outcome }}" + exit 1 + shell: bash + + - name: "EAB with headerinfo - 04 - Enroll legowith a allowed fqdn after reconfiguration" + if: ${{ inputs.RECONFIGURE == 'true' }} + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_02 --hmac dGhpc19pc19hX3ZlcnlfbG9uZ19obWFjX3RvX21ha2Vfc3VyZV90aGF0X2l0c19tb3JlX3RoYW5fMjU2X2JpdHM -d lego.acme --http run + shell: bash + + - name: "EAB with headerinfo - 05 - Enroll acme with default values from acme.cfg" + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_03 --eab-hmac-key YW5kX2ZpbmFsbHlfdGhlX2xhc3RfaG1hY19rZXlfd2hpY2hfaXNfbG9uZ2VyX3RoYW5fMjU2X2JpdHNfYW5kX3Nob3VsZF93b3Jr --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv -d acme-sh.acme --standalone --debug 3 --output-insecure + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -text -noout + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -ext extendedKeyUsage -noout | grep "Code Signing" + shell: bash + + - name: "EAB with headerinfo - 05 - Enroll lego with default values from acme.cfg" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_03 --hmac YW5kX2ZpbmFsbHlfdGhlX2xhc3RfaG1hY19rZXlfd2hpY2hfaXNfbG9uZ2VyX3RoYW5fMjU2X2JpdHNfYW5kX3Nob3VsZF93b3Jr -d lego.acme --http run + sudo openssl x509 -in lego/certificates/lego.acme.crt -ext extendedKeyUsage -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -issuer --noout + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -ext extendedKeyUsage | grep "Code Signing" + shell: bash + + - name: "EAB with headerinfo - 06 - Enroll acme with not allowed headerinfo-field (should fail)" + id: acmefail03 + continue-on-error: true + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_02 --eab-hmac-key dGhpc19pc19hX3ZlcnlfbG9uZ19obWFjX3RvX21ha2Vfc3VyZV90aGF0X2l0c19tb3JlX3RoYW5fMjU2X2JpdHM --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv --useragent profile_id=101 -d acme-sh.acme --standalone --debug 3 --output-insecure + shell: bash + + - name: "EAB with headerinfo - 06 - check result " + if: steps.acmefail03.outcome != 'failure' + run: | + echo "acmefail outcome is ${{steps.acmefail03.outcome }}" + exit 1 + shell: bash + + - name: "EAB with headerinfo - 06 - Enroll lego with not allowed headerinfo-field (should fail)" + id: legofail03 + continue-on-error: true + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_02 --hmac dGhpc19pc19hX3ZlcnlfbG9uZ19obWFjX3RvX21ha2Vfc3VyZV90aGF0X2l0c19tb3JlX3RoYW5fMjU2X2JpdHM --user-agent profile_id=101 -d lego.acme --http run + shell: bash + + - name: "EAB with headerinfo - 06 - check result " + if: steps.legofail03.outcome != 'failure' + run: | + echo "legofail outcome is ${{steps.legofail03.outcome }}" + exit 1 + shell: bash \ No newline at end of file diff --git a/.github/actions/wf_specific/certifier_ca_handler/enroll_eab_wo_headerinfo/action.yml b/.github/actions/wf_specific/certifier_ca_handler/enroll_eab_wo_headerinfo/action.yml new file mode 100644 index 00000000..3c4554c9 --- /dev/null +++ b/.github/actions/wf_specific/certifier_ca_handler/enroll_eab_wo_headerinfo/action.yml @@ -0,0 +1,134 @@ +name: "enroll_102_profile" +description: "wf enrollment 102 profile" + +runs: + using: "composite" + steps: + - name: "EAB without headerinfo - Sleep for 10s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 10s + + - name: "EAB without headerinfo - Test http://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory + shell: bash + + - name: "EAB without headerinfo - Test if https://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory + shell: bash + + - name: "EAB without headerinfo - Enroll acme.sh without profile_id" + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_00 --eab-hmac-key V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv -d acme-sh.acme --standalone --debug 3 --output-insecure + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -text -noout + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -ext extendedKeyUsage -noout | grep -i "TLS Web Server Authentication" + shell: bash + + - name: "EAB without headerinfo - Enroll lego without profile_id" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw -d lego.acme --http run + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -ext extendedKeyUsage -noout | grep -i "TLS Web Server Authentication" + shell: bash + + - name: "EAB without headerinfo - 02 - Enroll acme with a template_name taken from header_info NOT included in kid.json (to be ignored)" + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_00 --eab-hmac-key V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv --useragent profile_id=unknown -d acme-sh.acme --standalone --debug 3 --output-insecure + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -text -noout + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -ext extendedKeyUsage -noout | grep -i "TLS Web Server Authentication" + shell: bash + + - name: "EAB without headerinfo - 02 - Enroll lego with a template_name taken from header_info NOT included in kid.json (to be ignored)" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --user-agent profile_id=unknown -d lego.acme --http run + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --user-agent profile_id=101 -d lego.acme --http run + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -ext extendedKeyUsage | grep "TLS Web Server Authentication" + shell: bash + + - name: "EAB without headerinfo - 03 - Enroll acme with a template_name/ca_name taken from kid.json" + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_01 --eab-hmac-key YW5vdXRoZXJfdmVyeV9sb25nX2htYWNfZm9yX2tleWlkXzAxX3doaWNoIHdpbGxfYmUgdXNlZF9kdXJpbmcgcmVncmVzc2lvbg --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv -d acme-sh.acme --standalone --debug 3 --output-insecure + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -text -noout + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -ext extendedKeyUsage -noout | grep "TLS Web Server Authentication" + shell: bash + + - name: "EAB without headerinfo - 03 - Enroll lego with a template_name/ca_name taken from kid.json" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_01 --hmac YW5vdXRoZXJfdmVyeV9sb25nX2htYWNfZm9yX2tleWlkXzAxX3doaWNoIHdpbGxfYmUgdXNlZF9kdXJpbmcgcmVncmVzc2lvbg -d lego.acme --http run + sudo openssl x509 -in lego/certificates/lego.acme.crt -ext extendedKeyUsage -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -issuer --noout + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -ext extendedKeyUsage | grep "TLS Web Server Authentication" + shell: bash + + - name: "EAB without headerinfo - 04 - Enroll acme with a not allowed fqdn in kid.json (to fail)" + id: acmefail021 + continue-on-error: true + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_02 --eab-hmac-key dGhpc19pc19hX3ZlcnlfbG9uZ19obWFjX3RvX21ha2Vfc3VyZV90aGF0X2l0c19tb3JlX3RoYW5fMjU2X2JpdHM --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv -d acme-sh.acme --standalone --debug 3 --output-insecure + shell: bash + + - name: "EAB without headerinfo - 04 - check result " + if: steps.acmefail021.outcome != 'failure' + run: | + echo "acmefail outcome is ${{steps.acmefail021.outcome }}" + exit 1 + shell: bash + + - name: "EAB without headerinfo - 04 - Enroll lego with a not allowed fqdn in kid.json (to fail)" + id: legofail021 + continue-on-error: true + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_02 --hmac dGhpc19pc19hX3ZlcnlfbG9uZ19obWFjX3RvX21ha2Vfc3VyZV90aGF0X2l0c19tb3JlX3RoYW5fMjU2X2JpdHM -d lego.acme --http run + shell: bash + + - name: "EAB without headerinfo - 04a - check result " + if: steps.legofail021.outcome != 'failure' + run: | + echo "legofail outcome is ${{steps.legofail021.outcome }}" + exit 1 + shell: bash + + - name: "EAB without headerinfo - 05 - Enroll acme with default values from acme.cfg" + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_03 --eab-hmac-key YW5kX2ZpbmFsbHlfdGhlX2xhc3RfaG1hY19rZXlfd2hpY2hfaXNfbG9uZ2VyX3RoYW5fMjU2X2JpdHNfYW5kX3Nob3VsZF93b3Jr --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv -d acme-sh.acme --standalone --debug 3 --output-insecure + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -text -noout + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -ext extendedKeyUsage -noout | grep "Code Signing" + shell: bash + + - name: "EAB without headerinfo - 05 - Enroll lego with default values from acme.cfg" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_03 --hmac YW5kX2ZpbmFsbHlfdGhlX2xhc3RfaG1hY19rZXlfd2hpY2hfaXNfbG9uZ2VyX3RoYW5fMjU2X2JpdHNfYW5kX3Nob3VsZF93b3Jr -d lego.acme --http run + sudo openssl x509 -in lego/certificates/lego.acme.crt -ext extendedKeyUsage -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -issuer --noout + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -ext extendedKeyUsage | grep "Code Signing" + shell: bash diff --git a/.github/actions/wf_specific/certifier_ca_handler/enroll_headerinfo/action.yml b/.github/actions/wf_specific/certifier_ca_handler/enroll_headerinfo/action.yml new file mode 100644 index 00000000..bca8e196 --- /dev/null +++ b/.github/actions/wf_specific/certifier_ca_handler/enroll_headerinfo/action.yml @@ -0,0 +1,51 @@ +name: "enroll_102_profile" +description: "wf enrollment 102 profile" + +runs: + using: "composite" + steps: + - name: "Sleep for 10s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 10s + + - name: "Header-info - Test http://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory + shell: bash + + - name: "Header-info - Test if https://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory + shell: bash + + - name: "Header-info - 01 - Enroll acme.sh with profile_id 101" + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv --accountemail 'acme-sh@example.com' --useragent profile_id=101 -d acme-sh.acme --alpn --standalone --debug 3 --output-insecure + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -ext extendedKeyUsage -noout | grep -i "TLS Web Client" + shell: bash + + - name: "Header-info - 01 - Enroll lego with profile_id 101" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --user-agent profile_id=101 -d lego.acme --http run + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl x509 -in lego/certificates/lego.acme.crt -ext extendedKeyUsage -noout | grep -i "TLS Web Client" + shell: bash + + - name: "Header-info - 02 - Enroll acme.sh with profile_id 102" + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv --accountemail 'acme-sh@example.com' --useragent profile_id=102 -d acme-sh.acme --alpn --standalone --debug 3 --output-insecure + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -ext extendedKeyUsage -noout | grep -i "TLS Web Server" + shell: bash + + - name: "Header-info - 02 - Enroll lego with profile_id 102" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --user-agent profile_id=102 -d lego.acme --http run + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl x509 -in lego/certificates/lego.acme.crt -ext extendedKeyUsage -noout | grep -i "TLS Web Server" + shell: bash \ No newline at end of file diff --git a/.github/actions/wf_specific/certifier_ca_handler/enroll_no_profile/action.yml b/.github/actions/wf_specific/certifier_ca_handler/enroll_no_profile/action.yml new file mode 100644 index 00000000..50a30fc4 --- /dev/null +++ b/.github/actions/wf_specific/certifier_ca_handler/enroll_no_profile/action.yml @@ -0,0 +1,65 @@ +name: "enroll_no_profile" +description: "wf enrollment without profile" + +runs: + using: "composite" + steps: + + - name: "Create folders" + run: | + sudo mkdir -p lego + sudo mkdir -p acme-sh + sudo mkdir -p certbot + shell: bash + + - name: "No profile - Sleep for 10s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 10s + + - name: "No profile - Test http://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory + shell: bash + + - name: "No profile - Test if https://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory + shell: bash + + - name: "No profile - Enroll acme.sh" + run: | + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv --accountemail 'acme-sh@example.com' -d acme-sh.acme --alpn --standalone --debug 3 --output-insecure + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer + shell: bash + + - name: "No profile - Revoke via acme.sh" + run: | + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --revoke --server http://acme-srv -d acme-sh.acme --standalone --debug 3 --output-insecure + shell: bash + + - name: "No profile - Register certbot" + run: | + docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email + shell: bash + + - name: "No profile - Enroll HTTP-01 single domain certbot" + run: | + docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem + shell: bash + + - name: "No profile - Revoke HTTP-01 single domain certbot" + run: | + docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot revoke --delete-after-revoke --server http://acme-srv -d certbot.acme --cert-name certbot + shell: bash + + - name: "No profile - Enroll lego" + run: | + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --http run + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + shell: bash + + - name: "No profile - Revoke HTTP-01 single domain lego" + run: | + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme revoke + shell: bash \ No newline at end of file diff --git a/.github/actions/wf_specific/certifier_ca_handler/tunnel_setup/action.yml b/.github/actions/wf_specific/certifier_ca_handler/tunnel_setup/action.yml new file mode 100644 index 00000000..c84961b4 --- /dev/null +++ b/.github/actions/wf_specific/certifier_ca_handler/tunnel_setup/action.yml @@ -0,0 +1,71 @@ +name: "tunnel_setup" +description: "tunnel_setup" +inputs: + WCCE_SSH_ACCESS_KEY: + description: "SSH access key" + required: true + WCCE_SSH_KNOWN_HOSTS: + description: "SSH known hosts" + required: true + WCCE_SSH_USER: + description: "SSH user" + required: true + WCCE_SSH_HOST: + description: "SSH host" + required: true + WCCE_SSH_PORT: + description: "SSH port" + required: true + NAME_SPACE: + description: "namespace" + required: true + default: "acme" + NCM_API_HOST: + description: "NCM API host" + required: true + NCM_API_USER: + description: "NCM API user" + required: true + NCM_API_PASSWORD: + description: "NCM API password" + required: true +runs: + using: "composite" + steps: + - name: "Prepare ssh environment on ramdisk " + run: | + sudo mkdir -p /tmp/rd + sudo mount -t tmpfs -o size=5M none /tmp/rd + sudo echo "$SSH_KEY" > /tmp/rd/ak.tmp + sudo chmod 600 /tmp/rd/ak.tmp + sudo echo "$KNOWN_HOSTS" > /tmp/rd/known_hosts + env: + SSH_KEY: ${{ inputs.WCCE_SSH_ACCESS_KEY }} + KNOWN_HOSTS: ${{ inputs.WCCE_SSH_KNOWN_HOSTS }} + shell: bash + + - name: "Setup ssh forwarder" + run: | + docker run -d --rm --network $NAME_SPACE --name=forwarder -e "MAPPINGS=8084:127.0.0.1:8084" -e "SSH_HOST=$SSH_HOST" -e "SSH_PORT=$SSH_PORT" -e "SSH_USER=$SSH_USER" -p 8080:8084 -v "/tmp/rd/ak.tmp:/ssh_key:ro" davidlor/ssh-port-forward-client:dev + env: + SSH_USER: ${{ inputs.WCCE_SSH_USER }} + SSH_HOST: ${{ inputs.WCCE_SSH_HOST }} + SSH_PORT: ${{ inputs.WCCE_SSH_PORT }} + NAME_SPACE: ${{ inputs.NAME_SPACE }} + NCM_API_HOST: ${{ inputs.NCM_API_HOST }} + shell: bash + + - name: "Sleep for 5s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 5s + + - name: "Test conection to mscertsrv via ssh tunnel" + run: | + docker run -i --rm --network $NAME_SPACE curlimages/curl --insecure https://$NCM_API_USER:$NCM_API_PASSWORD@forwarder.acme:8084 + env: + NCM_API_HOST: ${{ inputs.NCM_API_HOST }} + NAME_SPACE: ${{ inputs.NAME_SPACE }} + NCM_API_USER: ${{ inputs.NCM_API_USER }} + NCM_API_PASSWORD: ${{ inputs.NCM_API_PASSWORD }} + shell: bash \ No newline at end of file diff --git a/.github/actions/wf_specific/digicert_ca_handler/enroll_eab/action.yml b/.github/actions/wf_specific/digicert_ca_handler/enroll_eab/action.yml new file mode 100644 index 00000000..cc9e027c --- /dev/null +++ b/.github/actions/wf_specific/digicert_ca_handler/enroll_eab/action.yml @@ -0,0 +1,98 @@ +name: "enroll_eab" +description: "enroll_eab" + +runs: + using: "composite" + steps: + - name: "Sleep for 5s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 5s + + - name: "EAB - Test http://acme-srv/directory is accessible" + run: docker run -i --rm --network acme.dynamop.de curlimages/curl -f http://acme-srv/directory + shell: bash + + - name: "EAB - Test if https://acme-srv/directory is accessible" + run: docker run -i --rm --network acme.dynamop.de curlimages/curl --insecure -f https://acme-srv/directory + shell: bash + + - name: "EAB - 01 - Enroll lego with a template_name taken from list in kid.json" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme.dynamop.de goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw -d lego.acme.dynamop.de --http run + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.dynamop.de.crt + sudo openssl x509 -in lego/certificates/lego.acme.dynamop.de.crt -text -noout + sudo docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme.dynamop.de goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw -d lego.acme.dynamop.de revoke + shell: bash + + - name: "EAB - 02a - Enroll lego with a template_name taken from header_info NOT included in kid.json (to fail)" + id: legofail01 + continue-on-error: true + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme.dynamop.de goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --user-agent cert_type=unknown -d lego.acme.dynamop.de --http run + shell: bash + + - name: "EAB - 02a - check result " + if: steps.legofail01.outcome != 'failure' + run: | + echo "legofail outcome is ${{steps.legofail01.outcome }}" + exit 1 + shell: bash + + - name: "EAB - 02b - Enroll lego with a template_name taken from header_info included in kid.json" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme.dynamop.de goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --user-agent cert_type=ssl_securesite_pro -d lego.acme.dynamop.de --http run + sudo openssl x509 -in lego/certificates/lego.acme.dynamop.de.crt -ext extendedKeyUsage -noout + sudo openssl x509 -in lego/certificates/lego.acme.dynamop.de.crt -issuer --noout + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.dynamop.de.crt + sudo docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme.dynamop.de goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw -d lego.acme.dynamop.de revoke + shell: bash + + - name: "EAB - 03 - Enroll lego with a template_name/ca_name taken from kid.json" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme.dynamop.de goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_01 --hmac YW5vdXRoZXJfdmVyeV9sb25nX2htYWNfZm9yX2tleWlkXzAxX3doaWNoIHdpbGxfYmUgdXNlZF9kdXJpbmcgcmVncmVzc2lvbg -d lego.acme.dynamop.de --http run + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.dynamop.de.crt + sudo docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme.dynamop.de goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw -d lego.acme.dynamop.de revoke + shell: bash + + - name: "EAB - 04 - Enroll lego with a not allowed fqdn in kid.json (to fail)" + id: legofail02 + continue-on-error: true + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme.dynamop.de goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_02 --hmac dGhpc19pc19hX3ZlcnlfbG9uZ19obWFjX3RvX21ha2Vfc3VyZV90aGF0X2l0c19tb3JlX3RoYW5fMjU2X2JpdHM -d lego.acme1.dynamop.de --http run + shell: bash + + - name: "EAB - 04a - check result " + if: steps.legofail02.outcome != 'failure' + run: | + echo "legofail outcome is ${{steps.legofail02.outcome }}" + exit 1 + shell: bash + + - name: "EAB - 05 - Enroll lego with default values from acme.cfg" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme.dynamop.de goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_03 --hmac YW5kX2ZpbmFsbHlfdGhlX2xhc3RfaG1hY19rZXlfd2hpY2hfaXNfbG9uZ2VyX3RoYW5fMjU2X2JpdHNfYW5kX3Nob3VsZF93b3Jr -d lego.acme.dynamop.de --http run + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.dynamop.de.crt + sudo docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme.dynamop.de goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw -d lego.acme.dynamop.de revoke + shell: bash + + - name: "EAB - 06 - Enroll lego with not allowed headerinfo-field (should fail)" + id: legofail03 + continue-on-error: true + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme.dynamop.de goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_02 --hmac dGhpc19pc19hX3ZlcnlfbG9uZ19obWFjX3RvX21ha2Vfc3VyZV90aGF0X2l0c19tb3JlX3RoYW5fMjU2X2JpdHM --user-agent cert_type=ssl_securesite_pro -d lego.acme.dynamop.de --http run + shell: bash + + - name: "EAB - 06 - check result " + if: steps.legofail03.outcome != 'failure' + run: | + echo "legofail outcome is ${{steps.legofail03.outcome }}" + exit 1 + shell: bash \ No newline at end of file diff --git a/.github/actions/wf_specific/ejbca_ca_handler/ejbca_prep/action.yml b/.github/actions/wf_specific/ejbca_ca_handler/ejbca_prep/action.yml new file mode 100644 index 00000000..11799525 --- /dev/null +++ b/.github/actions/wf_specific/ejbca_ca_handler/ejbca_prep/action.yml @@ -0,0 +1,100 @@ +name: "ejbca_prep" +description: "ejbca_prep" +inputs: + RUNNER_IP: + description: "Runner IP" + required: true + WORKING_DIR: + description: "Working directory" + required: true + default: ${{ github.workspace }} +outputs: + SAEC: + description: "Superadmin password" + value: ${{ env.SAEC }} + CAID: + description: "CAID of acmeca" + value: ${{ env.CAID }} + +runs: + using: "composite" + steps: + - name: "Prepare Environment" + working-directory: ${{ inputs.WORKING_DIR }} + run: | + mkdir -p data/acme_ca + sudo chmod -R 777 data/acme_ca + sudo sh -c "echo '$EJBCA_IP ejbca' >> /etc/hosts" + env: + EJBCA_IP: ${{ inputs.RUNNER_IP }} + shell: bash + + - name: "Instanciate ejbca server" + run: | + docker run -id --rm -p 80:8080 -p 443:8443 -e TLS_SETUP_ENABLED=true -v $(pwd)/examples/ejbca:/tmp/data -v ${{ inputs.WORKING_DIR }}/data:/tmp/store --name "ejbca" -h ejbca keyfactor/ejbca-ce + shell: bash + + - name: "Sleep for 180s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 180s + + - name: "Get randmonly generated Superadmin password for ejbca instance" + run: | + echo SAEC=$(docker logs ejbca | grep /opt/keyfactor/bin/start.sh | grep Password: | awk -F'Password: ' '{print $2}' | awk -F ' ' '{print $1}') >> $GITHUB_ENV + shell: bash + + - run: echo "Randmonly generated Superadmin password is ${{ env.SAEC }}" + shell: bash + + - run: sudo echo ${{ env.SAEC }} > ${{ inputs.WORKING_DIR }}/data/passphrase.txt + shell: bash + + - name: "Configure ejbca" + run: | + docker exec -i ejbca bin/ejbca.sh ca getcacert --caname ManagementCA -f /tmp/store/acme_ca/ca_bundle.pem + docker exec -i ejbca bin/ejbca.sh config protocols enable --name "REST Certificate Management" + docker exec -i ejbca bin/ejbca.sh config protocols enable --name "REST Certificate Management V2" + docker exec -i ejbca bin/ejbca.sh ca init acmeca "CN=acmeca" soft foo123 4096 RSA -v 365 --policy 2.5.29.32.0 -s SHA256WithRSA + shell: bash + + - name: "Get CAID" + run: | + echo CAID=$(docker logs ejbca | grep "msg=CA with id" | grep "and name acmeca added" | awk -F'with id ' '{print $2}' | awk -F' and name' '{print $1}') >> $GITHUB_ENV + shell: bash + + - run: echo "CAID of acmeca is ${{ env.CAID }}" + shell: bash + + - name: "Create subca" + run: | + docker exec -i ejbca bin/ejbca.sh ca init acmesubca "CN=acmesubca" soft foo123 4096 RSA -v 365 --policy 2.5.29.32.0 -s SHA256WithRSA --signedby $CAID + docker exec -i ejbca bin/ejbca.sh ca importprofiles -d /tmp/data/ + env: + CAID: ${{ env.CAID }} + shell: bash + + - name: "Sleep for 10s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 10s + + - name: "Fetch superadmin certificate and key" + working-directory: ${{ inputs.WORKING_DIR }} + run: | + docker exec -i ejbca bin/ejbca.sh ra setendentitystatus superadmin 10 + docker exec -i ejbca bin/ejbca.sh ra setclearpwd superadmin $SAEC + docker exec -i ejbca bin/ejbca.sh batch + docker cp ejbca:/opt/keyfactor/p12/superadmin.p12 data/acme_ca/ + env: + SAEC: ${{ env.SAEC }} + shell: bash + + - name: "Test superadmin certificate and key" + working-directory: ${{ inputs.WORKING_DIR }} + run: | + curl https://127.0.0.1/ejbca/ejbca-rest-api/v1/certificate/status --cert-type P12 --cert data/acme_ca/superadmin.p12:$SAEC --insecure + curl https://ejbca/ejbca/ejbca-rest-api/v1/certificate/status --cert-type P12 --cert data/acme_ca/superadmin.p12:$SAEC --cacert data/acme_ca/ca_bundle.pem + env: + SAEC: ${{ env.SAEC }} + shell: bash \ No newline at end of file diff --git a/.github/actions/wf_specific/ejbca_ca_handler/enroll_eab_w_headerinfo/action.yml b/.github/actions/wf_specific/ejbca_ca_handler/enroll_eab_w_headerinfo/action.yml new file mode 100644 index 00000000..4ebcabe0 --- /dev/null +++ b/.github/actions/wf_specific/ejbca_ca_handler/enroll_eab_w_headerinfo/action.yml @@ -0,0 +1,109 @@ +name: "enroll_w_headerinfo" +description: "enroll_w_headerinfo" +inputs: + ASA_CA_NAME1: + description: "ASA CA 1" + required: true + ASA_CA_NAME2: + description: "ASA CA 2" + required: true + +runs: + using: "composite" + steps: + - name: "Sleep for 10s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 10s + + - name: "EAB with headerinfo - Test http://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory + shell: bash + + - name: "EAB wit headerinfo - Test if https://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory + shell: bash + + - name: "EAB with headerinfo - 01a - enrollment without header-info field (first value in list)" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --http run + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -issuer -noout | grep -i acmesubca + sudo openssl x509 -in lego/certificates/lego.acme.crt -ext extendedKeyUsage -noout | grep "TLS Web Client" + shell: bash + + - name: "EAB with headerinfo - 01b - enrollment with header-info field (pick value from list)" + run: | + sudo rm -rf lego/* + sudo docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --user-agent cert_profile_name=acmeca1 -d lego.acme --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --http run + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -issuer -noout | grep -i acmesubca + sudo openssl x509 -in lego/certificates/lego.acme.crt -ext extendedKeyUsage -noout | grep "TLS Web Server" + shell: bash + + - name: "EAB with headerinfo - 01c - enrollment with header-info field containing value not included in list (to fail)" + id: legofail02 + continue-on-error: true + run: | + sudo rm -rf lego/* + sudo docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --user-agent cert_profile_name=acmeca3 -d lego.acme --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --http run + shell: bash + + - name: EAB with headerinfo 01c - check result " + if: steps.legofail02.outcome != 'failure' + run: | + echo "legofail outcome is ${{steps.legofail02.outcome }}" + exit 1 + shell: bash + + - name: "EAB with headerinfo - 01d - enrollment with header-info field cotaining an invalid parameter (silent overwrite)" + run: | + sudo rm -rf lego/* + sudo docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --user-agent ca_name=foo -d lego.acme --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --http run + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -issuer -noout | grep -i acmesubca + sudo openssl x509 -in lego/certificates/lego.acme.crt -ext extendedKeyUsage -noout | grep "TLS Web Client" + shell: bash + + - name: "EAB with headerinfo - 01e - enrollment with header-info field containing parameter not in json (silent overwrite)" + run: | + sudo rm -rf lego/* + sudo docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --user-agent cert_profile_name=acmeca2 -d lego.acme --eab --kid keyid_01 --hmac YW5vdXRoZXJfdmVyeV9sb25nX2htYWNfZm9yX2tleWlkXzAxX3doaWNoIHdpbGxfYmUgdXNlZF9kdXJpbmcgcmVncmVzc2lvbg --http run + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -issuer -noout | grep -i acmeca + sudo openssl x509 -in lego/certificates/lego.acme.crt -ext extendedKeyUsage -noout | grep "TLS Web Client" + shell: bash + + - name: "EAB with headerinfo - 02 - profilinging ca and cert_profile" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --eab --kid keyid_01 --hmac YW5vdXRoZXJfdmVyeV9sb25nX2htYWNfZm9yX2tleWlkXzAxX3doaWNoIHdpbGxfYmUgdXNlZF9kdXJpbmcgcmVncmVzc2lvbg --http run + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -issuer -noout | grep -i acmeca + sudo openssl x509 -in lego/certificates/lego.acme.crt -ext extendedKeyUsage -noout | grep "TLS Web Client" + shell: bash + + - name: "EAB with headerinfo - 03 - domainlist validation fails (to fail)" + id: legofail03 + continue-on-error: true + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --eab --kid keyid_02 --hmac dGhpc19pc19hX3ZlcnlfbG9uZ19obWFjX3RvX21ha2Vfc3VyZV90aGF0X2l0c19tb3JlX3RoYW5fMjU2X2JpdHM --http run + shell: bash + + - name: EAB with headerinfo - 03 - check result " + if: steps.legofail03.outcome != 'failure' + run: | + echo "legofail outcome is ${{steps.legofail03.outcome }}" + exit 1 + shell: bash + + - name: "EAB with headerinfo - 04 - Settings from acme_srv.cfg" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --eab --kid keyid_03 --hmac YW5kX2ZpbmFsbHlfdGhlX2xhc3RfaG1hY19rZXlfd2hpY2hfaXNfbG9uZ2VyX3RoYW5fMjU2X2JpdHNfYW5kX3Nob3VsZF93b3Jr --http run + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -issuer -noout | grep -i acmesubca + sudo openssl x509 -in lego/certificates/lego.acme.crt -ext extendedKeyUsage -noout | grep "TLS Web Server" + shell: bash \ No newline at end of file diff --git a/.github/actions/wf_specific/ejbca_ca_handler/enroll_eab_wo_headerinfo/action.yml b/.github/actions/wf_specific/ejbca_ca_handler/enroll_eab_wo_headerinfo/action.yml new file mode 100644 index 00000000..bbf85f97 --- /dev/null +++ b/.github/actions/wf_specific/ejbca_ca_handler/enroll_eab_wo_headerinfo/action.yml @@ -0,0 +1,79 @@ +name: "enroll_wo_headerinfo" +description: "enroll_wo_headerinfo" + + +runs: + using: "composite" + steps: + - name: "Sleep for 10s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 10s + + - name: "EAB without headerinfo - Test http://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory + shell: bash + + - name: "EAB without headerinfo - Test if https://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory + shell: bash + + - name: "EAB without headerinfo - 01a - enrollment without header-info field (first value in list)" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --http run + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -issuer -noout | grep -i acmesubca + sudo openssl x509 -in lego/certificates/lego.acme.crt -ext extendedKeyUsage -noout | grep "TLS Web Client" + shell: bash + + - name: "EAB without headerinfo - 01b - enrollment with header-info field included in list (silent ignore)" + run: | + sudo rm -rf lego/* + sudo docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --user-agent cert_profile_name=acmeca1 -d lego.acme --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --http run + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -issuer -noout | grep -i acmesubca + sudo openssl x509 -in lego/certificates/lego.acme.crt -ext extendedKeyUsage -noout | grep "TLS Web Client" + shell: bash + + - name: "EAB without headerinfo - 01c - with header-info field containing value not included in list (silent ignore)" + run: | + sudo rm -rf lego/* + sudo docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --user-agent cert_profile_name=acmeca3 -d lego.acme --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --http run + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -issuer -noout | grep -i acmesubca + sudo openssl x509 -in lego/certificates/lego.acme.crt -ext extendedKeyUsage -noout | grep "TLS Web Client" + shell: bash + + - name: "EAB without headerinfo - 02 - profilinging ca and cert_profile" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --eab --kid keyid_01 --hmac YW5vdXRoZXJfdmVyeV9sb25nX2htYWNfZm9yX2tleWlkXzAxX3doaWNoIHdpbGxfYmUgdXNlZF9kdXJpbmcgcmVncmVzc2lvbg --http run + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -issuer -noout | grep -i acmeca + sudo openssl x509 -in lego/certificates/lego.acme.crt -ext extendedKeyUsage -noout | grep "TLS Web Client" + shell: bash + + - name: "EAB without headerinfo - 03 - domainlist validation fails (to fail)" + id: legofail01 + continue-on-error: true + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --eab --kid keyid_02 --hmac dGhpc19pc19hX3ZlcnlfbG9uZ19obWFjX3RvX21ha2Vfc3VyZV90aGF0X2l0c19tb3JlX3RoYW5fMjU2X2JpdHM --http run + shell: bash + + - name: EAB without headerinfo - 03 - check result " + if: steps.legofail01.outcome != 'failure' + run: | + echo "legofail outcome is ${{steps.legofail01.outcome }}" + exit 1 + shell: bash + + - name: "EAB without headerinfo - 04 - Settings from acme_srv.cfg" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --eab --kid keyid_03 --hmac YW5kX2ZpbmFsbHlfdGhlX2xhc3RfaG1hY19rZXlfd2hpY2hfaXNfbG9uZ2VyX3RoYW5fMjU2X2JpdHNfYW5kX3Nob3VsZF93b3Jr --http run + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -issuer -noout | grep -i acmesubca + sudo openssl x509 -in lego/certificates/lego.acme.crt -ext extendedKeyUsage -noout | grep "TLS Web Server" + shell: bash \ No newline at end of file diff --git a/.github/actions/wf_specific/enrollment_timeout/enroll/action.yml b/.github/actions/wf_specific/enrollment_timeout/enroll/action.yml new file mode 100644 index 00000000..f490f1b1 --- /dev/null +++ b/.github/actions/wf_specific/enrollment_timeout/enroll/action.yml @@ -0,0 +1,88 @@ +name: "enroll_102_profile" +description: "wf enrollment 102 profile" +inputs: + DEPLOYMENT_TYPE: + description: "Deployment type" + required: true + default: "container" + +runs: + using: "composite" + steps: + + - name: "Sleep for 10s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 10s + + - name: "Test http://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory + shell: bash + + - name: "Test if https://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory + shell: bash + + - name: "Enroll acme.sh" + run: | + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv --keylength 2048 --accountemail 'acme-sh@example.com' -d acme-sh.acme --standalone --debug 3 --output-insecure --force + shell: bash + + - name: "Check timeout" + working-directory: examples/Docker/ + run: | + if [ ${{ inputs.DEPLOYMENT_TYPE }} == "container" ]; then + docker-compose logs | grep "Certificate.enroll_and_store() ended with: None:timeout" + sudo truncate -s 0 $(docker inspect --format='{{.LogPath}}' acme2certifier_acme-srv_1) + elif [ ${{ inputs.DEPLOYMENT_TYPE }} == "rpm" ]; then + docker exec acme-srv grep "Certificate.enroll_and_store() ended with: None:timeout" /var/log/messages + fi + shell: bash + + - name: "Enroll acme.sh" + run: | + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv --keylength 2048 --accountemail 'acme-sh@example.com' -d acme-sh.acme --standalone --debug 3 --output-insecure --force + shell: bash + + - name: "Check certificate reusage" + working-directory: examples/Docker/ + run: | + if [ ${{ inputs.DEPLOYMENT_TYPE }} == "container" ]; then + docker-compose logs | grep "Certificate._enroll(): reuse existing certificate" + elif [ ${{ inputs.DEPLOYMENT_TYPE }} == "rpm" ]; then + docker exec acme-srv grep "Certificate._enroll(): reuse existing certificate" /var/log/messages + fi + shell: bash + + - name: "Enroll Lego" + run: | + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --cert.timeout 180 --http run + shell: bash + + - name: "Check timeout" + working-directory: examples/Docker/ + run: | + if [ ${{ inputs.DEPLOYMENT_TYPE }} == "container" ]; then + docker-compose logs | grep "Certificate.enroll_and_store() ended with: None:timeout" + sudo truncate -s 0 $(docker inspect --format='{{.LogPath}}' acme2certifier_acme-srv_1) + fi + shell: bash + + - name: "Register certbot" + run: | + docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email + shell: bash + + - name: "Enroll certbot" + run: | + docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot --issuance-timeout 180 + shell: bash + + - name: "Check timeout" + working-directory: examples/Docker/ + run: | + if [ ${{ inputs.DEPLOYMENT_TYPE }} == "container" ]; then + docker-compose logs | grep "Certificate.enroll_and_store() ended with: None:timeout" + sudo truncate -s 0 $(docker inspect --format='{{.LogPath}}' acme2certifier_acme-srv_1) + fi + shell: bash diff --git a/.github/actions/wf_specific/entrust_ca_handler/enroll/action.yml b/.github/actions/wf_specific/entrust_ca_handler/enroll/action.yml new file mode 100644 index 00000000..697565b0 --- /dev/null +++ b/.github/actions/wf_specific/entrust_ca_handler/enroll/action.yml @@ -0,0 +1,237 @@ +name: "acme_clients - enroll, renew and revoke certificates" +description: "Test if acme.sh, certbot and lego can enroll, renew and certificates" +inputs: + ACME_SERVER: + description: "ACME server URL" + required: true + default: "acme-srv" + REVOCATION: + description: "Revocation method" + required: true + default: "true" + USE_RSA: + description: "Use RSA" + required: true + default: "false" + HTTP_PORT: + description: "HTTP port" + required: true + default: "80" + HTTPS_PORT: + description: "HTTPS port" + required: true + default: "443" + HOSTNAME_SUFFIX: + description: "Hostname suffix" + required: true + NAME_SPACE: + description: "Namespace" + required: true + default: "acme" + +runs: + using: "composite" + steps: + + - name: "Create directories" + run: | + sudo mkdir -p certbot/ + sudo mkdir -p lego/ca + sudo cp .github/acme2certifier_cabundle.pem certbot/ + sudo cp .github/acme2certifier_cabundle.pem lego/ + if [ -f cert-2.pem ]; then + echo "delete cert-2.pem" + rm -f cert-2.pem + fi + if [ -f cert-1.pem ]; then + echo "delete cert-1.pem" + rm -f cert-1.pem + fi + ls -la + shell: bash + + - name: "Sleep for 5s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 5s + + - name: "Test if http://acme-srv/directory is accessible" + run: docker run -i --rm --network $NAME_SPACE curlimages/curl -f http://$ACME_SERVER:$HTTP_PORT/directory + shell: bash + env: + ACME_SERVER: ${{ inputs.ACME_SERVER }} + HTTP_PORT: ${{ inputs.HTTP_PORT }} + HTTPS_PORT: ${{ inputs.HTTPS_PORT }} + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "Test if https://acme-srv/directory is accessible" + run: docker run -i --rm --network $NAME_SPACE curlimages/curl --insecure -f https://$ACME_SERVER:$HTTPS_PORT/directory + shell: bash + env: + ACME_SERVER: ${{ inputs.ACME_SERVER }} + HTTP_PORT: ${{ inputs.HTTP_PORT }} + HTTPS_PORT: ${{ inputs.HTTPS_PORT }} + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "HTTP - Enroll lego" + run: | + echo "##### HTTP - Enroll lego #####" + if [ "$USE_RSA" == "false" ]; then + echo "use ECC" + docker run -i --rm -e LEGO_CA_CERTIFICATES=.lego/acme2certifier_cabundle.pem -v $PWD/lego:/.lego/ --name lego$HOSTNAME_SUFFIX --network $NAME_SPACE goacme/lego -s http://$ACME_SERVER:$HTTP_PORT -a --email "lego@example.com" -d lego$HOSTNAME_SUFFIX.$NAME_SPACE --tls run + else + echo "use RSA" + docker run -i --rm -e LEGO_CA_CERTIFICATES=.lego/acme2certifier_cabundle.pem -v $PWD/lego:/.lego/ --name lego$HOSTNAME_SUFFIX --network $NAME_SPACE goacme/lego -s http://$ACME_SERVER:$HTTP_PORT -a --email "lego@example.com" --key-type=rsa2048 -d lego$HOSTNAME_SUFFIX.$NAME_SPACE --tls run + fi + shell: bash + env: + ACME_SERVER: ${{ inputs.ACME_SERVER }} + HTTP_PORT: ${{ inputs.HTTP_PORT }} + HTTPS_PORT: ${{ inputs.HTTPS_PORT }} + USE_RSA: ${{ inputs.USE_RSA }} + HOSTNAME_SUFFIX: ${{ inputs.HOSTNAME_SUFFIX }} + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "HTTP - Revoke lego" + if: ${{ inputs.REVOCATION == 'true' }} + run: | + echo "#### HTTP - Revoke lego" + docker run -i -v $PWD/lego:/.lego/ --rm --name lego$HOSTNAME_SUFFIX --network $NAME_SPACE goacme/lego -s http://$ACME_SERVER:$HTTP_PORT -a --email "lego@example.com" -d lego$HOSTNAME_SUFFIX.$NAME_SPACE revoke + shell: bash + env: + ACME_SERVER: ${{ inputs.ACME_SERVER }} + HTTP_PORT: ${{ inputs.HTTP_PORT }} + HTTPS_PORT: ${{ inputs.HTTPS_PORT }} + HOSTNAME_SUFFIX: ${{ inputs.HOSTNAME_SUFFIX }} + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "HTTPS - Enroll acme.sh" + run: | + echo "##### HTTPS - Enroll acme.sh #####" + if [ "$USE_RSA" == "false" ]; then + echo "use ECC" + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network $NAME_SPACE --name acme-sh$HOSTNAME_SUFFIX neilpang/acme.sh:latest --issue --server https://$ACME_SERVER:$HTTPS_PORT --accountemail 'acme-sh@example.com' -d acme-sh$HOSTNAME_SUFFIX.$NAME_SPACE --alpn --standalone --debug 1 --output-insecure --insecure + ECC="_ecc" + else + echo "use RSA" + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network $NAME_SPACE --name acme-sh$HOSTNAME_SUFFIX neilpang/acme.sh:latest --issue --server https://$ACME_SERVER:$HTTPS_PORT --accountemail 'acme-sh@example.com' -d acme-sh$HOSTNAME_SUFFIX.$NAME_SPACE --alpn --standalone --keylength 2048 --debug 1 --output-insecure --insecure + fi + + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh$HOSTNAME_SUFFIX.$NAME_SPACE${ECC}/ca.cer + if [ "$VERIFY_CERT" == "true" ]; then + if [ -f cert-2.pem ]; then + echo "Multiple CA certs" + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh$HOSTNAME_SUFFIX.$NAME_SPACE${ECC}/acme-sh$HOSTNAME_SUFFIX.$NAME_SPACE.cer + else + echo "Single Root ca" + openssl verify -CAfile cert-1.pem acme-sh/acme-sh$HOSTNAME_SUFFIX.$NAME_SPACE${ECC}/acme-sh$HOSTNAME_SUFFIX.$NAME_SPACE.cer + fi + fi + shell: bash + env: + VERIFY_CERT: ${{ inputs.VERIFY_CERT }} + ACME_SERVER: ${{ inputs.ACME_SERVER }} + HTTP_PORT: ${{ inputs.HTTP_PORT }} + HTTPS_PORT: ${{ inputs.HTTPS_PORT }} + USE_RSA: ${{ inputs.USE_RSA }} + HOSTNAME_SUFFIX: ${{ inputs.HOSTNAME_SUFFIX }} + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "HTTPS - Revoke HTTP-01 single domain acme.sh" + if: ${{ inputs.REVOCATION == 'true' }} + run: | + echo "##### HTTPS - Revoke HTTP-01 single domain acme.sh #####" + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --name acme-sh$HOSTNAME_SUFFIX --network $NAME_SPACE neilpang/acme.sh:latest --revoke --server https://$ACME_SERVER:$HTTPS_PORT --revoke -d acme-sh$HOSTNAME_SUFFIX.$NAME_SPACE --standalone --debug 2 --output-insecure --insecure + shell: bash + env: + ACME_SERVER: ${{ inputs.ACME_SERVER }} + HTTP_PORT: ${{ inputs.HTTP_PORT }} + HTTPS_PORT: ${{ inputs.HTTPS_PORT }} + HOSTNAME_SUFFIX: ${{ inputs.HOSTNAME_SUFFIX }} + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "HTTPS - Decativate acme.sh #####" + run: | + echo "##### HTTPS - Decativate acme.sh" + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --name acme-sh$HOSTNAME_SUFFIX --network $NAME_SPACE neilpang/acme.sh:latest --deactivate-account --server https://$ACME_SERVER:$HTTPS_PORT --debug 2 --output-insecure --insecure + shell: bash + env: + ACME_SERVER: ${{ inputs.ACME_SERVER }} + HTTP_PORT: ${{ inputs.HTTP_PORT }} + HTTPS_PORT: ${{ inputs.HTTPS_PORT }} + HOSTNAME_SUFFIX: ${{ inputs.HOSTNAME_SUFFIX }} + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "HTTPS - Enroll certbot" + run: | + echo "##### HTTPS - Enroll certbot #####" + if [ "$USE_RSA" == "false" ]; then + docker run -i --rm --name certbot$HOSTNAME_SUFFIX --network $NAME_SPACE -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server https://$ACME_SERVER:$HTTPS_PORT --standalone --preferred-challenges http --no-verify-ssl --agree-tos -m 'certbot@example.com' -d certbot$HOSTNAME_SUFFIX.$NAME_SPACE --cert-name certbot --issuance-timeout 120 + else + docker run -i --rm --name certbot$HOSTNAME_SUFFIX --network $NAME_SPACE -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server https://$ACME_SERVER:$HTTPS_PORT --standalone --preferred-challenges http --no-verify-ssl --agree-tos -m 'certbot@example.com' --key-type rsa -d certbot$HOSTNAME_SUFFIX.$NAME_SPACE --cert-name certbot --issuance-timeout 120 + fi + + if [ "$VERIFY_CERT" == "true" ]; then + if [ -f cert-2.pem ]; then + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem + else + echo "single root ca" + sudo openssl verify -CAfile cert-1.pem certbot/live/certbot/cert.pem + fi + fi + shell: bash + env: + VERIFY_CERT: ${{ inputs.VERIFY_CERT }} + ACME_SERVER: ${{ inputs.ACME_SERVER }} + HTTPS_PORT: ${{ inputs.HTTPS_PORT }} + USE_RSA: ${{ inputs.USE_RSA }} + HOSTNAME_SUFFIX: ${{ inputs.HOSTNAME_SUFFIX }} + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "HTTPS - Revoke certbot" + if: ${{ inputs.REVOCATION == 'true' }} + run: | + echo "##### HTTPS - Revoke certbot #####" + docker run -i --rm --name certbot$HOSTNAME_SUFFIX --network $NAME_SPACE -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot revoke --server https://$ACME_SERVER:$HTTPS_PORT --no-verify-ssl --delete-after-revoke --cert-name certbot + shell: bash + env: + ACME_SERVER: ${{ inputs.ACME_SERVER }} + HTTP_PORT: ${{ inputs.HTTP_PORT }} + HTTPS_PORT: ${{ inputs.HTTPS_PORT }} + HOSTNAME_SUFFIX: ${{ inputs.HOSTNAME_SUFFIX }} + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "HTTP - Enroll lego with wrong domain - should fail" + id: legofail01 + continue-on-error: true + run: | + echo "##### HTTP - Enroll lego #####" + if [ "$USE_RSA" == "false" ]; then + echo "use ECC" + docker run -i --rm -e LEGO_CA_CERTIFICATES=.lego/acme2certifier_cabundle.pem -v $PWD/lego:/.lego/ --name lego$HOSTNAME_SUFFIX --network $NAME_SPACE goacme/lego -s http://$ACME_SERVER:$HTTP_PORT -a --email "lego@example.com" -d lego$HOSTNAME_SUFFIX.acme --tls run + else + echo "use RSA" + docker run -i --rm -e LEGO_CA_CERTIFICATES=.lego/acme2certifier_cabundle.pem -v $PWD/lego:/.lego/ --name lego$HOSTNAME_SUFFIX --network $NAME_SPACE goacme/lego -s http://$ACME_SERVER:$HTTP_PORT -a --email "lego@example.com" --key-type=rsa2048 -d lego$HOSTNAME_SUFFIX.acme --tls run + fi + shell: bash + env: + ACME_SERVER: ${{ inputs.ACME_SERVER }} + HTTP_PORT: ${{ inputs.HTTP_PORT }} + HTTPS_PORT: ${{ inputs.HTTPS_PORT }} + USE_RSA: ${{ inputs.USE_RSA }} + HOSTNAME_SUFFIX: ${{ inputs.HOSTNAME_SUFFIX }} + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "Check result " + if: steps.legofail01.outcome != 'failure' + run: | + echo "legofail outcome is ${{steps.legofail01.outcome }}" + exit 1 + shell: bash + + - name: "Delete acme-sh, letsencypt and lego folders" + run: | + sudo rm -rf lego/* + sudo rm -rf acme-sh/* + sudo rm -rf certbot/* + shell: bash \ No newline at end of file diff --git a/.github/actions/wf_specific/entrust_ca_handler/enroll_eab/action.yml b/.github/actions/wf_specific/entrust_ca_handler/enroll_eab/action.yml new file mode 100644 index 00000000..1ea5936b --- /dev/null +++ b/.github/actions/wf_specific/entrust_ca_handler/enroll_eab/action.yml @@ -0,0 +1,41 @@ +name: "enroll_eab" +description: "enroll_eab" + +runs: + using: "composite" + steps: + - name: "Sleep for 5s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 5s + + - name: "EAB - Test http://acme-srv/directory is accessible" + run: docker run -i --rm --network rm-rf.ninja curlimages/curl -f http://acme-srv/directory + shell: bash + + - name: "EAB - Test if https://acme-srv/directory is accessible" + run: docker run -i --rm --network rm-rf.ninja curlimages/curl --insecure -f https://acme-srv/directory + shell: bash + + - name: "EAB - 01 - Enroll lego with a template_name taken from list in kid.json" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network rm-rf.ninja goacme/lego -s http://acme-srv -a --email "lego@example.com" --key-type=rsa2048 --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw -d lego.rm-rf.ninja --http run + sudo docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network rm-rf.ninja goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw -d lego.rm-rf.ninja revoke + shell: bash + + - name: "EAB - 02 - Enroll lego with a not allowed fqdn in kid.json (to fail)" + id: legofail01 + continue-on-error: true + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network rm-rf.ninja goacme/lego -s http://acme-srv -a --email "lego@example.com" --key-type=rsa2048 --eab --kid keyid_02 --hmac dGhpc19pc19hX3ZlcnlfbG9uZ19obWFjX3RvX21ha2Vfc3VyZV90aGF0X2l0c19tb3JlX3RoYW5fMjU2X2JpdHM -d lego.rm-rf.ninja --http run + shell: bash + + - name: "EAB - 04a - check result " + if: steps.legofail01.outcome != 'failure' + run: | + echo "legofail outcome is ${{steps.legofail01.outcome }}" + exit 1 + shell: bash + diff --git a/.github/actions/wf_specific/ms_ca_handler/enroll_allowed_domain_list/action.yml b/.github/actions/wf_specific/ms_ca_handler/enroll_allowed_domain_list/action.yml new file mode 100644 index 00000000..fd1c6337 --- /dev/null +++ b/.github/actions/wf_specific/ms_ca_handler/enroll_allowed_domain_list/action.yml @@ -0,0 +1,55 @@ +name: "enroll_allowed_domain_list" +description: "enroll_allowed_domain_list" +inputs: + NAME_SPACE: + description: "namespace" + required: true + default: "acme" +runs: + using: "composite" + steps: + - name: "Sleep for 10s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 10s + + - name: "Test http://acme-srv/directory is accessible" + run: docker run -i --rm --network $NAME_SPACE curlimages/curl -f http://acme-srv/directory + shell: bash + env: + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "Test if https://acme-srv/directory is accessible" + run: docker run -i --rm --network $NAME_SPACE curlimages/curl --insecure -f https://acme-srv/directory + shell: bash + env: + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "Enroll acme.sh with fqdn not part of allowed_domainlist (should fail)" + id: acmefail01 + continue-on-error: true + run: | + sudo rm -rf acme-sh/ + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network $NAME_SPACE --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv --accountemail 'acme-sh@example.com' -d acme-sh.local --alpn --standalone --debug 3 --output-insecure + shell: bash + env: + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "Check result " + if: steps.acmefail01.outcome != 'failure' + run: | + echo "acmefail outcome is ${{steps.acmefail01.outcome }}" + exit 1 + shell: bash + env: + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "Enroll acme.sh with fqdn part of allowed_domainlist" + run: | + sudo rm -rf acme-sh/ + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network $NAME_SPACE --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv --accountemail 'acme-sh@example.com' -d acme-sh.acme --alpn --standalone --debug 3 --output-insecure + openssl verify -CAfile cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -ext extendedKeyUsage -noout | grep -i "TLS Web Server" + shell: bash + env: + NAME_SPACE: ${{ inputs.NAME_SPACE }} \ No newline at end of file diff --git a/.github/actions/wf_specific/ms_ca_handler/enroll_default_headerinfo/action.yml b/.github/actions/wf_specific/ms_ca_handler/enroll_default_headerinfo/action.yml new file mode 100644 index 00000000..7aa2dc2c --- /dev/null +++ b/.github/actions/wf_specific/ms_ca_handler/enroll_default_headerinfo/action.yml @@ -0,0 +1,59 @@ +name: "enroll_default_headerinfo" +description: "enroll_default_headerinfo" +inputs: + NAME_SPACE: + description: "namespace" + required: true + default: "acme" +runs: + using: "composite" + steps: + - name: "Sleep for 10s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 10s + + - name: "Test http://acme-srv/directory is accessible" + run: docker run -i --rm --network ${{ inputs.NAME_SPACE }} curlimages/curl -f http://acme-srv/directory + shell: bash + env: + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "Test if https://acme-srv/directory is accessible" + run: docker run -i --rm --network ${{ inputs.NAME_SPACE }} curlimages/curl --insecure -f https://acme-srv/directory + shell: bash + env: + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "Enroll acme.sh with template in acme_srv.cfg (WebServer)" + run: | + sudo rm -rf acme-sh/ + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network ${{ inputs.NAME_SPACE }} --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv --accountemail 'acme-sh@example.com' -d acme-sh.${{ inputs.NAME_SPACE }} --alpn --standalone --debug 3 --output-insecure + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.${{ inputs.NAME_SPACE }}_ecc/ca.cer + openssl verify -CAfile cert-1.pem acme-sh/acme-sh.${{ inputs.NAME_SPACE }}_ecc/acme-sh.${{ inputs.NAME_SPACE }}.cer + openssl x509 -in acme-sh/acme-sh.${{ inputs.NAME_SPACE }}_ecc/acme-sh.${{ inputs.NAME_SPACE }}.cer -ext extendedKeyUsage -noout | grep -i "TLS Web Server" + shell: bash + + - name: "Enroll lego with template in acme_srv.cfg (WebServer)" + run: | + sudo rm -rf lego/ + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network ${{ inputs.NAME_SPACE }} goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.${{ inputs.NAME_SPACE }} --http run + sudo openssl verify -CAfile cert-1.pem lego/certificates/lego.${{ inputs.NAME_SPACE }}.crt + sudo openssl x509 -in lego/certificates/lego.${{ inputs.NAME_SPACE }}.crt -ext extendedKeyUsage -noout | grep -i "TLS Web Server" + shell: bash + + - name: "Enroll acme.sh with template submitted in command line (WebServerModified)" + run: | + sudo rm -rf acme-sh/ + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network ${{ inputs.NAME_SPACE }} --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv --accountemail 'acme-sh@example.com' -d acme-sh.${{ inputs.NAME_SPACE }} --alpn --standalone --useragent template=WebServerModified --keylength 2048 --debug 3 --output-insecure + openssl verify -CAfile cert-1.pem acme-sh/acme-sh.${{ inputs.NAME_SPACE }}/acme-sh.${{ inputs.NAME_SPACE }}.cer + openssl x509 -in acme-sh/acme-sh.${{ inputs.NAME_SPACE }}/acme-sh.${{ inputs.NAME_SPACE }}.cer -ext extendedKeyUsage -noout | grep -i "TLS Web Client" + shell: bash + + - name: "Enroll lego with template submitted in command line (WebServerModified)" + run: | + sudo rm -rf lego/ + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network ${{ inputs.NAME_SPACE }} goacme/lego -s http://acme-srv -a --email "lego@example.com" --user-agent template=WebServerModified --key-type=rsa2048 -d lego.${{ inputs.NAME_SPACE }} --http run + sudo openssl verify -CAfile cert-1.pem lego/certificates/lego.${{ inputs.NAME_SPACE }}.crt + sudo openssl x509 -in lego/certificates/lego.${{ inputs.NAME_SPACE }}.crt -ext extendedKeyUsage -noout | grep -i "TLS Web Client" + shell: bash diff --git a/.github/actions/wf_specific/ms_ca_handler/enroll_eab/action.yml b/.github/actions/wf_specific/ms_ca_handler/enroll_eab/action.yml new file mode 100644 index 00000000..ce649c0e --- /dev/null +++ b/.github/actions/wf_specific/ms_ca_handler/enroll_eab/action.yml @@ -0,0 +1,125 @@ +name: "enroll_default_headerinfo" +description: "enroll_default_headerinfo" +inputs: + NAME_SPACE: + description: "namespace" + required: true + default: "acme" + +runs: + using: "composite" + steps: + - name: "Sleep for 10s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 10s + + - name: "EAB with headerinfo - Test http://acme-srv/directory is accessible" + run: docker run -i --rm --network $NAME_SPACE curlimages/curl -f http://acme-srv/directory + shell: bash + env: + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "EAB with headerinfo - Test if https://acme-srv/directory is accessible" + run: docker run -i --rm --network $NAME_SPACE curlimages/curl --insecure -f https://acme-srv/directory + shell: bash + env: + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "EAB with headerinfo - 01a - enrollment without header-info field (first value in list)" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network $NAME_SPACE goacme/lego -s http://acme-srv -a --email "lego@example.com" --key-type=rsa2048 -d lego.$NAME_SPACE --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --http run + sudo openssl x509 -in lego/certificates/lego.$NAME_SPACE.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.$NAME_SPACE.crt -ext extendedKeyUsage -noout | grep -i "TLS Web Client" + shell: bash + env: + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "EAB with headerinfo - 01b - enrollment with header-info field (pick value from list)" + run: | + sudo rm -rf lego/* + sudo docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network $NAME_SPACE goacme/lego -s http://acme-srv -a --email "lego@example.com" --user-agent template=WebServer --key-type=rsa2048 -d lego.$NAME_SPACE --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --http run + sudo openssl x509 -in lego/certificates/lego.$NAME_SPACE.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.$NAME_SPACE.crt -ext extendedKeyUsage -noout | grep -i "TLS Web Server" + shell: bash + env: + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "EAB with headerinfo - 01c - enrollment with header-info field containing value not included in list (to fail)" + id: legofail02 + continue-on-error: true + run: | + sudo rm -rf lego/* + sudo docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network $NAME_SPACE goacme/lego -s http://acme-srv -a --email "lego@example.com" --user-agent template=Unknown --key-type=rsa2048 -d lego.$NAME_SPACE --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --http run + shell: bash + env: + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: EAB with headerinfo 01c - check result " + if: steps.legofail02.outcome != 'failure' + run: | + echo "legofail outcome is ${{steps.legofail02.outcome }}" + exit 1 + shell: bash + env: + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "EAB with headerinfo - 01d - enrollment with header-info field cotaining an invalid parameter (silent overwrite)" + run: | + sudo rm -rf lego/* + sudo docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network $NAME_SPACE goacme/lego -s http://acme-srv -a --email "lego@example.com" --user-agent ca_name=foo --key-type=rsa2048 -d lego.$NAME_SPACE --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --http run + sudo openssl x509 -in lego/certificates/lego.$NAME_SPACE.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.$NAME_SPACE.crt -ext extendedKeyUsage -noout | grep "TLS Web Client" + shell: bash + env: + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "EAB with headerinfo - 01e - enrollment with header-info field containing parameter not in json (silent overwrite)" + run: | + sudo rm -rf lego/* + sudo docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network $NAME_SPACE goacme/lego -s http://acme-srv -a --email "lego@example.com" --user-agent user=user --key-type=rsa2048 -d lego.$NAME_SPACE --eab --kid keyid_01 --hmac YW5vdXRoZXJfdmVyeV9sb25nX2htYWNfZm9yX2tleWlkXzAxX3doaWNoIHdpbGxfYmUgdXNlZF9kdXJpbmcgcmVncmVzc2lvbg --http run + sudo openssl x509 -in lego/certificates/lego.$NAME_SPACE.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.$NAME_SPACE.crt -ext extendedKeyUsage -noout | grep "TLS Web Client" + shell: bash + env: + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "EAB with headerinfo - 02 - template from profile" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network $NAME_SPACE goacme/lego -s http://acme-srv -a --email "lego@example.com" --key-type=rsa2048 -d lego.$NAME_SPACE --eab --kid keyid_01 --hmac YW5vdXRoZXJfdmVyeV9sb25nX2htYWNfZm9yX2tleWlkXzAxX3doaWNoIHdpbGxfYmUgdXNlZF9kdXJpbmcgcmVncmVzc2lvbg --http run + sudo openssl x509 -in lego/certificates/lego.$NAME_SPACE.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.$NAME_SPACE.crt -ext extendedKeyUsage -noout | grep "TLS Web Client" + shell: bash + env: + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "EAB with headerinfo - 03 - domainlist validation fails (to fail)" + id: legofail03 + continue-on-error: true + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network $NAME_SPACE goacme/lego -s http://acme-srv -a --email "lego@example.com" --key-type=rsa2048 -d lego.$NAME_SPACE --eab --kid keyid_02 --hmac dGhpc19pc19hX3ZlcnlfbG9uZ19obWFjX3RvX21ha2Vfc3VyZV90aGF0X2l0c19tb3JlX3RoYW5fMjU2X2JpdHM --http run + shell: bash + env: + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "EAB with headerinfo - 03 - check result " + if: steps.legofail03.outcome != 'failure' + run: | + echo "legofail outcome is ${{steps.legofail03.outcome }}" + exit 1 + shell: bash + env: + NAME_SPACE: ${{ inputs.NAME_SPACE }} + + - name: "EAB with headerinfo - 04 - Settings from acme_srv.cfg" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network $NAME_SPACE goacme/lego -s http://acme-srv -a --email "lego@example.com" --key-type=rsa2048 -d lego.$NAME_SPACE --eab --kid keyid_03 --hmac YW5kX2ZpbmFsbHlfdGhlX2xhc3RfaG1hY19rZXlfd2hpY2hfaXNfbG9uZ2VyX3RoYW5fMjU2X2JpdHNfYW5kX3Nob3VsZF93b3Jr --http run + sudo openssl x509 -in lego/certificates/lego.$NAME_SPACE.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.$NAME_SPACE.crt -ext extendedKeyUsage -noout | grep "TLS Web Server" + shell: bash + env: + NAME_SPACE: ${{ inputs.NAME_SPACE }} \ No newline at end of file diff --git a/.github/actions/wf_specific/ms_ca_handler/tunnel_setup/action.yml b/.github/actions/wf_specific/ms_ca_handler/tunnel_setup/action.yml new file mode 100644 index 00000000..e3cda1ad --- /dev/null +++ b/.github/actions/wf_specific/ms_ca_handler/tunnel_setup/action.yml @@ -0,0 +1,76 @@ +name: "tunnel_setup" +description: "tunnel_setup" +inputs: + WCCE_SSH_ACCESS_KEY: + description: "SSH access key" + required: true + WCCE_SSH_KNOWN_HOSTS: + description: "SSH known hosts" + required: true + WCCE_FQDN_WOTLD: + description: "FQDN without top level domain" + required: true + WCCE_FQDN: + description: "FQDN" + required: true + WCCE_HOST: + description: "WCCE host" + required: true + WCCE_SSH_USER: + description: "SSH user" + required: true + WCCE_SSH_HOST: + description: "SSH host" + required: true + WCCE_SSH_PORT: + description: "SSH port" + required: true + NAME_SPACE: + description: "namespace" + required: true + default: "acme" + +runs: + using: "composite" + steps: + - name: "Sleep for 10s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 10s + + - name: "Prepare ssh environment on ramdisk " + run: | + sudo mkdir -p /tmp/rd + sudo mount -t tmpfs -o size=5M none /tmp/rd + sudo echo "$SSH_KEY" > /tmp/rd/ak.tmp + sudo chmod 600 /tmp/rd/ak.tmp + sudo echo "$KNOWN_HOSTS" > /tmp/rd/known_hosts + env: + SSH_KEY: ${{ inputs.WCCE_SSH_ACCESS_KEY }} + KNOWN_HOSTS: ${{ inputs.WCCE_SSH_KNOWN_HOSTS }} + shell: bash + + - name: "Setup ssh forwarder" + run: | + docker run -d --rm --network $NAME_SPACE --name=$WCCE_FQDN_WOTLD -e "MAPPINGS=445:$WCCE_HOST:445; 443:$WCCE_HOST:443; 88:$WCCE_HOST:88" -e "SSH_HOST=$SSH_HOST" -e "SSH_PORT=$SSH_PORT" -e "SSH_USER=$SSH_USER" -p 443:443 -p 445:445 -p 88:88 -v "/tmp/rd/ak.tmp:/ssh_key:ro" davidlor/ssh-port-forward-client:dev + env: + SSH_USER: ${{ inputs.WCCE_SSH_USER }} + SSH_HOST: ${{ inputs.WCCE_SSH_HOST }} + SSH_PORT: ${{ inputs.WCCE_SSH_PORT }} + WCCE_HOST: ${{ inputs.WCCE_HOST }} + WCCE_FQDN_WOTLD: ${{ inputs.WCCE_FQDN_WOTLD }} + NAME_SPACE: ${{ inputs.NAME_SPACE }} + shell: bash + + - name: "Sleep for 10s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 10s + + - name: "Test conection to mscertsrv via ssh tunnel" + run: | + docker run -i --rm --network $NAME_SPACE curlimages/curl --insecure -f https://$WCCE_FQDN + env: + WCCE_FQDN: ${{ inputs.WCCE_FQDN }} + NAME_SPACE: ${{ inputs.NAME_SPACE }} + shell: bash \ No newline at end of file diff --git a/.github/actions/wf_specific/openssl_ca_handler/enroll_adjust_cert_validity/action.yml b/.github/actions/wf_specific/openssl_ca_handler/enroll_adjust_cert_validity/action.yml new file mode 100644 index 00000000..67378dc8 --- /dev/null +++ b/.github/actions/wf_specific/openssl_ca_handler/enroll_adjust_cert_validity/action.yml @@ -0,0 +1,44 @@ +name: "enroll_w_headerinfo" +description: "enroll_w_headerinfo" +inputs: + ASA_CA_NAME1: + description: "ASA CA 1" + required: true + ASA_CA_NAME2: + description: "ASA CA 2" + required: true + +runs: + using: "composite" + steps: + - name: "Sleep for 10s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 10s + + - name: "Test http://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory + shell: bash + + - name: "Test if https://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory + shell: bash + + - name: "Register certbot" + run: | + sudo rm -rf certbot/* + docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email + shell: bash + + - name: "Enroll certbot" + run: | + docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem + sudo openssl x509 -in certbot/archive/certbot/cert1.pem -text -noout + sudo openssl x509 -in certbot/archive/certbot/cert1.pem -text -noout | grep "Not After : Jun 9 17:17:00 2030 GMT" + shell: bash + + - name: "Revoke certbot" + run: | + docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot revoke --delete-after-revoke --server http://acme-srv -d certbot.acme --cert-name certbot + shell: bash \ No newline at end of file diff --git a/.github/actions/wf_specific/openssl_ca_handler/enroll_cn_enforce/action.yml b/.github/actions/wf_specific/openssl_ca_handler/enroll_cn_enforce/action.yml new file mode 100644 index 00000000..55566c3d --- /dev/null +++ b/.github/actions/wf_specific/openssl_ca_handler/enroll_cn_enforce/action.yml @@ -0,0 +1,47 @@ +name: "enroll_w_headerinfo" +description: "enroll_w_headerinfo" +inputs: + ASA_CA_NAME1: + description: "ASA CA 1" + required: true + ASA_CA_NAME2: + description: "ASA CA 2" + required: true + +runs: + using: "composite" + steps: + - name: "Sleep for 10s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 10s + + - name: "Test http://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory + shell: bash + + - name: "Test if https://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory + shell: bash + + - name: "Register certbot" + run: | + sudo rm -rf certbot/* + docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email + shell: bash + + - name: "Enroll certbot" + run: | + docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem + sudo openssl x509 -in certbot/archive/certbot/cert1.pem -text -noout + sudo openssl x509 -in certbot/archive/certbot/cert1.pem -text -noout | grep "Basic Constraints: critical" + sudo openssl x509 -in certbot/archive/certbot/cert1.pem -text -noout | grep "Digital Signature, Key Encipherment" + sudo openssl x509 -in certbot/archive/certbot/cert1.pem -text -noout | grep "TLS Web Server Authentication, TLS Web Client Authentication" + sudo openssl x509 -in certbot/archive/certbot/cert1.pem -text -noout | grep "Subject: CN = certbot.acme" + shell: bash + + - name: "Revoke certbot" + run: | + docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot revoke --delete-after-revoke --server http://acme-srv -d certbot.acme --cert-name certbot + shell: bash \ No newline at end of file diff --git a/.github/actions/wf_specific/openssl_ca_handler/enroll_w_teamplate/action.yml b/.github/actions/wf_specific/openssl_ca_handler/enroll_w_teamplate/action.yml new file mode 100644 index 00000000..d21fd789 --- /dev/null +++ b/.github/actions/wf_specific/openssl_ca_handler/enroll_w_teamplate/action.yml @@ -0,0 +1,78 @@ +name: "enroll_w_headerinfo" +description: "enroll_w_headerinfo" +inputs: + ASA_CA_NAME1: + description: "ASA CA 1" + required: true + ASA_CA_NAME2: + description: "ASA CA 2" + required: true + +runs: + using: "composite" + steps: + - name: "Sleep for 5s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 5s + + - name: "Test http://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory + shell: bash + + - name: "Test if https://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory + shell: bash + + - name: "Enroll acme.sh" + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv --accountemail 'acme-sh@example.com' -d acme-sh.acme --alpn --standalone --debug 3 --output-insecure --force + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer + # verify aborts due to unhandled critical extension + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -text -noout + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -text -noout | grep "Basic Constraints: critical" + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -text -noout | grep "Digital Signature, Non Repudiation, Key Encipherment, Key Agreement" + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -text -noout | grep "TLS Web Server Authentication, OCSP Signing" + shell: bash + + - name: "Revoke via acme.sh" + run: | + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --revoke --server http://acme-srv -d acme-sh.acme --standalone --debug 3 --output-insecure + shell: bash + + - name: "Register certbot" + run: | + sudo rm -rf certbot/* + docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email + shell: bash + + - name: "Enroll certbot" + run: | + docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot + # verify aborts due to unhandled critical extension + sudo openssl x509 -in certbot/archive/certbot/cert1.pem -text -noout + sudo openssl x509 -in certbot/archive/certbot/cert1.pem -text -noout | grep "Basic Constraints: critical" + sudo openssl x509 -in certbot/archive/certbot/cert1.pem -text -noout | grep "Digital Signature, Non Repudiation, Key Encipherment, Key Agreement" + sudo openssl x509 -in certbot/archive/certbot/cert1.pem -text -noout | grep "TLS Web Server Authentication, OCSP Signing" + shell: bash + + - name: "Revoke certbot" + run: | + docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot revoke --delete-after-revoke --server http://acme-srv -d certbot.acme --cert-name certbot + shell: bash + + - name: "Enroll lego" + run: | + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --http run + # verify aborts due to unhandled critical extension + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout | grep "Basic Constraints: critical" + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout | grep "Digital Signature, Non Repudiation, Key Encipherment, Key Agreement" + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout | grep "TLS Web Server Authentication, OCSP Signing" + shell: bash + + - name: "Revoke lego" + run: | + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme revoke + shell: bash \ No newline at end of file diff --git a/.github/actions/wf_specific/openxpki_ca_handler/openxpki_prep/action.yml b/.github/actions/wf_specific/openxpki_ca_handler/openxpki_prep/action.yml new file mode 100644 index 00000000..a887d318 --- /dev/null +++ b/.github/actions/wf_specific/openxpki_ca_handler/openxpki_prep/action.yml @@ -0,0 +1,97 @@ +name: "ejbca_prep" +description: "ejbca_prep" +inputs: + RUNNER_IP: + description: "Runner IP" + required: true + WORKING_DIR: + description: "Working directory" + required: true + default: ${{ github.workspace }} + +runs: + using: "composite" + steps: + + - name: "Prepare Environment" + working-directory: ${{ inputs.WORKING_DIR }} + run: | + mkdir -p data/acme_ca + mkdir -p /tmp/openxpki + sudo chmod -R 777 data + sudo sh -c "echo '$OPENXPKI_IP openxpki' >> /etc/hosts" + sudo cat /etc/hosts + env: + OPENXPKI_IP: ${{ inputs.RUNNER_IP }} + shell: bash + + - name: "Instanciate OpenXPKI server" + working-directory: /tmp/openxpki + run: | + sudo apt-get install -y docker-compose + git clone https://github.com/openxpki/openxpki-docker.git + cd openxpki-docker/ + git clone https://github.com/openxpki/openxpki-config.git --single-branch --branch=community + cd openxpki-config/ + # git checkout a86981e2929e68f3fe3530a83bdb7a4436dfd604 + cd .. + sed -i "s/value: 0/value: 1/g" openxpki-config/config.d/realm/democa/est/default.yaml + sed -i "s/cert_profile: tls_server/cert_profile: tls_client/g" openxpki-config/config.d/realm/democa/est/default.yaml + sed -i "s/approval_points: 1/approval_points: 0/g" openxpki-config/config.d/realm/democa/rpc/enroll.yaml + sed -i "s/export_certificate: chain/export_certificate: fullchain/g" openxpki-config/config.d/realm/democa/rpc/enroll.yaml + sed -i "s/dn: CN=\[\% CN.0 \%\],DC=Test Deployment,DC=OpenXPKI,DC=org/dn: CN=\[\% SAN_DNS.0 \%\]/g" openxpki-config/config.d/realm.tpl/profile/tls_server.yaml + cp contrib/wait_on_init.yaml openxpki-config/config.d/system/local.yam + docker-compose up & + shell: bash + + - name: "Sleep for 60s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 60s + + - name: "Fix 1st time start issues with OpenXPKI server" + working-directory: /tmp/openxpki/openxpki-docker + run: | + docker ps + docker stop openxpki-docker_openxpki-server_1 + docker start openxpki-docker_openxpki-server_1 + shell: bash + + - name: "Sleep for 10s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 10s + + - name: "Configure OpenXPKI server" + working-directory: /tmp/openxpki + run: | + docker ps + docker exec -id openxpki-docker_openxpki-server_1 /bin/bash /etc/openxpki/contrib/sampleconfig.sh + docker exec -id openxpki-docker_openxpki-client_1 apt-get install -y libjson-pp-perl + shell: bash + + - name: "Sleep for 45s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 45s + + - name: "Enroll keys for Client-authentication via scep" + working-directory: ${{ inputs.WORKING_DIR }} + run: | + sudo openssl genrsa -out data/acme_ca/client_key.pem 2048 + sudo openssl req -new -key data/acme_ca/client_key.pem -subj '/CN=a2c:pkiclient,O=acme' -outform der | base64 > /tmp/request.pem + curl -v -H "Content-Type: application/pkcs10" --data @/tmp/request.pem https://$OPENXPKI_IP:8443/.well-known/est/simpleenroll --insecure | base64 -d > /tmp/cert.p7b + sudo openssl pkcs7 -print_certs -in /tmp/cert.p7b -inform der -out data/acme_ca/client_crt.pem + sudo openssl pkcs12 -export -out data/acme_ca/client_crt.p12 -inkey data/acme_ca/client_key.pem -in data/acme_ca/client_crt.pem -passout pass:Test1234 + sudo openssl rsa -noout -modulus -in data/acme_ca/client_key.pem | openssl md5 + sudo openssl x509 -noout -modulus -in data/acme_ca/client_crt.pem | openssl md5 + sudo chmod a+r data/acme_ca/client_key.pem + sudo chmod a+r data/acme_ca/client_crt.pem + sudo chmod a+r data/acme_ca/client_crt.p12 + curl https://$OPENXPKI_IP:8443/.well-known/est/cacerts --insecure | base64 -d > /tmp/cacert.p7b + sudo openssl pkcs7 -print_certs -in /tmp/cacert.p7b -inform der -out data/acme_ca/ca_bundle.pem + sudo chmod a+rw data/acme_ca/ca_bundle.pem + sudo openssl s_client -connect $OPENXPKI_IP:8443 2>/dev/null > data/acme_ca/ca_bundle.pem + env: + OPENXPKI_IP: ${{ inputs.RUNNER_IP }} + shell: bash \ No newline at end of file diff --git a/.github/actions/wf_specific/xca_ca_handler/enroll_eab/action.yml b/.github/actions/wf_specific/xca_ca_handler/enroll_eab/action.yml new file mode 100644 index 00000000..3970d494 --- /dev/null +++ b/.github/actions/wf_specific/xca_ca_handler/enroll_eab/action.yml @@ -0,0 +1,210 @@ +name: "enroll_eab" +description: "enroll_eab" + +runs: + using: "composite" + steps: + - name: "Sleep for 5s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 5s + + - name: "EAB - Sleep for 10s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 10s + + - name: "EAB - Test http://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory + shell: bash + + - name: "EAB - Test if https://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory + shell: bash + + - name: "EAB - 01 - Enroll acme with a template_name taken from list in kid.json" + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_00 --eab-hmac-key V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv -d acme-sh.acme --standalone --debug 3 --output-insecure + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -text -noout + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -ext keyUsage -noout | grep "Digital Signature, Non Repudiation" + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -ext extendedKeyUsage -noout | grep "TLS Web Client Authentication, Code Signing" + shell: bash + + - name: "EAB - 01 - Enroll lego with a template_name taken from list in kid.json" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw -d lego.acme --http run + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -ext keyUsage | grep "Digital Signature, Non Repudiation" + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -ext extendedKeyUsage | grep "TLS Web Client Authentication, Code Signing" + shell: bash + + - name: "EAB - 02a - Enroll acme with a template_name taken from header_info NOT included in kid.json (to fail)" + id: acmefail01 + continue-on-error: true + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_00 --eab-hmac-key V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv --useragent template_name=unknown -d acme-sh.acme --standalone --debug 3 --output-insecure + shell: bash + + - name: "EAB - 02a - check result " + if: steps.acmefail01.outcome != 'failure' + run: | + echo "acmefail outcome is ${{steps.acmefail01.outcome }}" + exit 1 + shell: bash + + - name: "EAB - 02b - Enroll acme with a template_name taken from header_info included in kid.json" + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_00 --eab-hmac-key V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv --useragent template_name=acme -d acme-sh.acme --standalone --debug 3 --output-insecure + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -text -noout + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -ext keyUsage -noout | grep "Digital Signature, Non Repudiation, Key Encipherment, Key Agreement" + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -ext extendedKeyUsage -noout | grep "TLS Web Server Authentication, TLS Web Client Authentication" + shell: bash + + - name: "EAB - 02a - Enroll lego with a template_name taken from header_info NOT included in kid.json (to fail)" + id: legofail01 + continue-on-error: true + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --user-agent template_name=unknown -d lego.acme --http run + shell: bash + + - name: "EAB - 02a - check result " + if: steps.legofail01.outcome != 'failure' + run: | + echo "legofail outcome is ${{steps.legofail01.outcome }}" + exit 1 + shell: bash + + - name: "EAB - 02b - Enroll lego with a template_name taken from header_info included in kid.json" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --user-agent template_name=acme -d lego.acme --http run + sudo openssl x509 -in lego/certificates/lego.acme.crt -ext extendedKeyUsage -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -issuer --noout + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -ext keyUsage | grep "Digital Signature, Non Repudiation, Key Encipherment, Key Agreement" + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -ext extendedKeyUsage | grep "TLS Web Server Authentication, TLS Web Client Authentication" + shell: bash + + - name: "EAB - 03 - Enroll acme with a template_name/ca_name taken from kid.json" + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_01 --eab-hmac-key YW5vdXRoZXJfdmVyeV9sb25nX2htYWNfZm9yX2tleWlkXzAxX3doaWNoIHdpbGxfYmUgdXNlZF9kdXJpbmcgcmVncmVzc2lvbg --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv -d acme-sh.acme --standalone --debug 3 --output-insecure + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -text -noout + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -ext keyUsage -noout | grep "Digital Signature, Non Repudiation" + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -ext extendedKeyUsage -noout | grep "TLS Web Client Authentication, Code Signing" + shell: bash + + - name: "EAB - 03 - Enroll lego with a template_name/ca_name taken from kid.json" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_01 --hmac YW5vdXRoZXJfdmVyeV9sb25nX2htYWNfZm9yX2tleWlkXzAxX3doaWNoIHdpbGxfYmUgdXNlZF9kdXJpbmcgcmVncmVzc2lvbg -d lego.acme --http run + sudo openssl x509 -in lego/certificates/lego.acme.crt -ext extendedKeyUsage -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -issuer --noout + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -ext keyUsage | grep "Digital Signature, Non Repudiation" + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -ext extendedKeyUsage | grep "TLS Web Client Authentication, Code Signing" + shell: bash + + - name: "EAB - 04 - Enroll acme with a not allowed fqdn in kid.json (to fail)" + id: acmefail02 + continue-on-error: true + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_02 --eab-hmac-key dGhpc19pc19hX3ZlcnlfbG9uZ19obWFjX3RvX21ha2Vfc3VyZV90aGF0X2l0c19tb3JlX3RoYW5fMjU2X2JpdHM --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv -d acme-sh.acme --standalone --debug 3 --output-insecure + shell: bash + + - name: "EAB - 04 - check result " + if: steps.acmefail02.outcome != 'failure' + run: | + echo "acmefail outcome is ${{steps.acmefail02.outcome }}" + exit 1 + shell: bash + + - name: "EAB - 04 - Enroll lego with a not allowed fqdn in kid.json (to fail)" + id: legofail02 + continue-on-error: true + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_02 --hmac dGhpc19pc19hX3ZlcnlfbG9uZ19obWFjX3RvX21ha2Vfc3VyZV90aGF0X2l0c19tb3JlX3RoYW5fMjU2X2JpdHM -d lego.acme --http run + shell: bash + + - name: "EAB - 04a - check result " + if: steps.legofail02.outcome != 'failure' + run: | + echo "legofail outcome is ${{steps.legofail02.outcome }}" + exit 1 + shell: bash + + - name: "EAB - 05 - Enroll acme with default values from acme.cfg" + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_03 --eab-hmac-key YW5kX2ZpbmFsbHlfdGhlX2xhc3RfaG1hY19rZXlfd2hpY2hfaXNfbG9uZ2VyX3RoYW5fMjU2X2JpdHNfYW5kX3Nob3VsZF93b3Jr --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv -d acme-sh.acme --standalone --debug 3 --output-insecure + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -text -noout + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -ext keyUsage -noout | grep "Digital Signature, Non Repudiation, Key Encipherment, Key Agreement" + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -ext extendedKeyUsage -noout | grep "TLS Web Server Authentication, TLS Web Client Authentication" + shell: bash + + - name: "EAB - 05 - Enroll lego with default values from acme.cfg" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_03 --hmac YW5kX2ZpbmFsbHlfdGhlX2xhc3RfaG1hY19rZXlfd2hpY2hfaXNfbG9uZ2VyX3RoYW5fMjU2X2JpdHNfYW5kX3Nob3VsZF93b3Jr -d lego.acme --http run + sudo openssl x509 -in lego/certificates/lego.acme.crt -ext extendedKeyUsage -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -issuer --noout + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -ext keyUsage | grep "Digital Signature, Non Repudiation, Key Encipherment, Key Agreement" + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -ext extendedKeyUsage | grep "TLS Web Server Authentication, TLS Web Client Authentication" + shell: bash + + - name: "EAB - 06 - Enroll acme with not allowed headerinfo-field (should fail)" + id: acmefail03 + continue-on-error: true + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_02 --eab-hmac-key dGhpc19pc19hX3ZlcnlfbG9uZ19obWFjX3RvX21ha2Vfc3VyZV90aGF0X2l0c19tb3JlX3RoYW5fMjU2X2JpdHM --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv --useragent template_name=acme -d acme-sh.acme --standalone --debug 3 --output-insecure + shell: bash + + - name: "EAB - 06 - check result " + if: steps.acmefail03.outcome != 'failure' + run: | + echo "acmefail outcome is ${{steps.acmefail03.outcome }}" + exit 1 + shell: bash + + - name: "EAB - 06 - Enroll lego with not allowed headerinfo-field (should fail)" + id: legofail03 + continue-on-error: true + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_02 --hmac dGhpc19pc19hX3ZlcnlfbG9uZ19obWFjX3RvX21ha2Vfc3VyZV90aGF0X2l0c19tb3JlX3RoYW5fMjU2X2JpdHM --user-agent template_name=acme -d lego.acme --http run + shell: bash + + - name: "EAB - 06 - check result " + if: steps.legofail03.outcome != 'failure' + run: | + echo "legofail outcome is ${{steps.legofail03.outcome }}" + exit 1 + shell: bash \ No newline at end of file diff --git a/.github/actions/wf_specific/xca_ca_handler/enroll_eab_sp/action.yml b/.github/actions/wf_specific/xca_ca_handler/enroll_eab_sp/action.yml new file mode 100644 index 00000000..9b97905d --- /dev/null +++ b/.github/actions/wf_specific/xca_ca_handler/enroll_eab_sp/action.yml @@ -0,0 +1,362 @@ +name: "enroll_eab" +description: "enroll_eab" +inputs: + DEPLOYMENT_TYPE: + description: "Deployment type" + required: true + default: "container" + + +runs: + using: "composite" + steps: + - name: "EAB - Sleep for 10s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 10s + + - name: "EAB - Test http://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory + shell: bash + + - name: "EAB - Test if https://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory + shell: bash + + - name: "EAB SP - 01a - SUCC - Enroll acme - 1st list entry" + run: | + mkdir -p acme-sh + sudo rm -rf acme-sh/* + openssl genrsa -out acme-sh/acme-sh.acme.key 2048 + openssl req -new -key acme-sh/acme-sh.acme.key -subj '/CN=acme-sh.acme/O=acme corp/OU=acme1/C=AC/serialNumber=00-11-22-33' --addext "subjectAltName = DNS:acme-sh.acme" -outform pem -out acme-sh/acme-sh.acme.csr + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_00 --eab-hmac-key V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name acme-sh neilpang/acme.sh:latest --signcsr --csr acme.sh/acme-sh.acme.csr --server http://acme-srv --standalone --debug 1 --output-insecure --insecure + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme/ca.cer + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme/acme-sh.acme.cer + openssl x509 -in acme-sh/acme-sh.acme/acme-sh.acme.cer -text -noout + shell: bash + + - name: "EAB SP - 01a - SUCC - Enroll lego - 1st list entry" + run: | + sudo mkdir -p lego + sudo rm -rf lego/* + sudo openssl genrsa -out lego/lego.acme.key 2048 + sudo openssl req -new -key lego/lego.acme.key -subj '/CN=lego.acme/O=acme corp/OU=acme1/C=AC/serialNumber=00-11-22-33' --addext "subjectAltName = DNS:lego.acme" -outform pem -out lego/lego.acme.csr + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --csr .lego/lego.acme.csr --http run + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + shell: bash + + - name: "EAB SP - 01B - SUCC - Enroll acme - 2nd list entry" + run: | + sudo rm -rf acme-sh/* + openssl genrsa -out acme-sh/acme-sh.acme.key 2048 + openssl req -new -key acme-sh/acme-sh.acme.key -subj '/CN=acme-sh.acme/O=acme corp/OU=acme2/C=AC/serialNumber=00-11-22-33' --addext "subjectAltName = DNS:acme-sh.acme" -outform pem -out acme-sh/acme-sh.acme.csr + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_00 --eab-hmac-key V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name acme-sh neilpang/acme.sh:latest --signcsr --csr acme.sh/acme-sh.acme.csr --server http://acme-srv --standalone --debug 1 --output-insecure --insecure + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme/acme-sh.acme.cer + openssl x509 -in acme-sh/acme-sh.acme/acme-sh.acme.cer -text -noout + shell: bash + + - name: "EAB SP - 01B - SUCC - Enroll lego - 2nd list entry" + run: | + sudo rm -rf lego/* + sudo openssl genrsa -out lego/lego.acme.key 2048 + sudo openssl req -new -key lego/lego.acme.key -subj '/CN=lego.acme/O=acme corp/OU=acme2/C=AC/serialNumber=00-11-22-33' --addext "subjectAltName = DNS:lego.acme" -outform pem -out lego/lego.acme.csr + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --csr .lego/lego.acme.csr --http run + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + shell: bash + + - name: "EAB SP - 01C - FAIL - Enroll acme - entry not in list" + id: acmefail01 + continue-on-error: true + run: | + sudo rm -rf acme-sh/* + openssl genrsa -out acme-sh/acme-sh.acme.key 2048 + openssl req -new -key acme-sh/acme-sh.acme.key -subj '/CN=acme-sh.acme/O=acme corp/OU=acme3/C=AC/serialNumber=00-11-22-33' --addext "subjectAltName = DNS:acme-sh.acme" -outform pem -out acme-sh/acme-sh.acme.csr + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_00 --eab-hmac-key V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name acme-sh neilpang/acme.sh:latest --signcsr --csr acme.sh/acme-sh.acme.csr --server http://acme-srv --standalone --debug 1 --output-insecure --insecure + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme/acme-sh.acme.cer + openssl x509 -in acme-sh/acme-sh.acme/acme-sh.acme.cer -text -noout + shell: bash + + - name: "Check result" + if: steps.acmefail01.outcome != 'failure' + run: | + echo "acmefail outcome is ${{steps.acmefail01.outcome }}" + exit 1 + shell: bash + + - name: "Sleep for 2s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 2s + + - name: "Check logs for errors" + working-directory: examples/Docker/ + run: | + if [ ${{ inputs.DEPLOYMENT_TYPE }} == "container" ]; then + docker-compose logs > docker-compose.log + cat docker-compose.log | grep "organizationalUnitName: value: acme3 expected: \['acme1', 'acme2'\]" + sudo truncate -s 0 $(docker inspect --format='{{.LogPath}}' acme2certifier_acme-srv_1) + # elif [ ${{ inputs.DEPLOYMENT_TYPE }} == "rpm" ]; then + # docker exec acme-srv grep "organizationalUnitName: value: acme3 expected: \['acme1', 'acme2'\]" /var/log/messages + fi + shell: bash + + - name: "EAB SP - 01C - Fail - Enroll lego - entry not in list" + id: legofail01 + continue-on-error: true + run: | + sudo rm -rf lego/* + sudo openssl genrsa -out lego/lego.acme.key 2048 + sudo openssl req -new -key lego/lego.acme.key -subj '/CN=lego.acme/O=acme corp/OU=acme3/C=AC/serialNumber=00-11-22-33' --addext "subjectAltName = DNS:lego.acme" -outform pem -out lego/lego.acme.csr + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --csr .lego/lego.acme.csr --http run + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + shell: bash + + - name: "Check result" + if: steps.legofail01.outcome != 'failure' + run: | + echo "legofail outcome is ${{steps.legofail01.outcome }}" + exit 1 + shell: bash + + - name: "Sleep for 2s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 2s + + - name: "Check logs for errors" + working-directory: examples/Docker/ + run: | + if [ ${{ inputs.DEPLOYMENT_TYPE }} == "container" ]; then + docker-compose logs > docker-compose.log + cat docker-compose.log | grep "organizationalUnitName: value: acme3 expected: \['acme1', 'acme2'\]" + sudo truncate -s 0 $(docker inspect --format='{{.LogPath}}' acme2certifier_acme-srv_1) + # elif [ ${{ inputs.DEPLOYMENT_TYPE }} == "rpm" ]; then + # docker exec acme-srv grep "organizationalUnitName: value: acme3 expected: \['acme1', 'acme2'\]" /var/log/messages + fi + shell: bash + + - name: "EAB SP - 02 - FAIL - Enroll acme - wildcard entry not present" + id: acmefail02 + continue-on-error: true + run: | + sudo rm -rf acme-sh/* + openssl genrsa -out acme-sh/acme-sh.acme.key 2048 + openssl req -new -key acme-sh/acme-sh.acme.key -subj '/CN=acme-sh.acme/O=acme corp/OU=acme1/C=AC' --addext "subjectAltName = DNS:acme-sh.acme" -outform pem -out acme-sh/acme-sh.acme.csr + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_00 --eab-hmac-key V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name acme-sh neilpang/acme.sh:latest --signcsr --csr acme.sh/acme-sh.acme.csr --server http://acme-srv --standalone --debug 1 --output-insecure --insecure + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme/acme-sh.acme.cer + openssl x509 -in acme-sh/acme-sh.acme/acme-sh.acme.cer -text -noout + shell: bash + + - name: "Check result" + if: steps.acmefail02.outcome != 'failure' + run: | + echo "acmefail outcome is ${{steps.acmefail02.outcome }}" + exit 1 + shell: bash + + - name: "Sleep for 2s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 2s + + - name: "Check logs for errors" + working-directory: examples/Docker/ + run: | + if [ ${{ inputs.DEPLOYMENT_TYPE }} == "container" ]; then + docker-compose logs > docker-compose.log + cat docker-compose.log | grep "failed for: \['serialNumber'\]" + sudo truncate -s 0 $(docker inspect --format='{{.LogPath}}' acme2certifier_acme-srv_1) + # elif [ ${{ inputs.DEPLOYMENT_TYPE }} == "rpm" ]; then + # docker exec acme-srv grep "failed for: \['serialNumber'\]" /var/log/messages + fi + shell: bash + + - name: "EAB SP - 02 - FAIL - Enroll lego - wildcard entry not present" + id: legofail02 + continue-on-error: true + run: | + sudo rm -rf lego/* + sudo openssl genrsa -out lego/lego.acme.key 2048 + sudo openssl req -new -key lego/lego.acme.key -subj '/CN=lego.acme/O=acme corp/OU=acme1/C=AC' --addext "subjectAltName = DNS:lego.acme" -outform pem -out lego/lego.acme.csr + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --csr .lego/lego.acme.csr --http run + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + shell: bash + + - name: "Check result" + if: steps.legofail02.outcome != 'failure' + run: | + echo "legofail outcome is ${{steps.legofail02.outcome }}" + exit 1 + shell: bash + + - name: "Sleep for 2s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 2s + + - name: "Check logs for errors" + working-directory: examples/Docker/ + run: | + if [ ${{ inputs.DEPLOYMENT_TYPE }} == "container" ]; then + docker-compose logs > docker-compose.log + cat docker-compose.log | grep "failed for: \['serialNumber'\]" + sudo truncate -s 0 $(docker inspect --format='{{.LogPath}}' acme2certifier_acme-srv_1) + # elif [ ${{ inputs.DEPLOYMENT_TYPE }} == "rpm" ]; then + # docker exec acme-srv grep "failed for: \['serialNumber'\]" /var/log/messages + fi + shell: bash + + - name: "EAB SP - 03 - FAIL - Enroll acme - string check failed" + id: acmefail03 + continue-on-error: true + run: | + sudo rm -rf acme-sh/* + openssl genrsa -out acme-sh/acme-sh.acme.key 2048 + openssl req -new -key acme-sh/acme-sh.acme.key -subj '/CN=acme-sh.acme/O=noacme corp/OU=acme2/C=AC/serialNumber=00-11-22-33' --addext "subjectAltName = DNS:acme-sh.acme" -outform pem -out acme-sh/acme-sh.acme.csr + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_00 --eab-hmac-key V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name acme-sh neilpang/acme.sh:latest --signcsr --csr acme.sh/acme-sh.acme.csr --server http://acme-srv --standalone --debug 1 --output-insecure --insecure + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme/acme-sh.acme.cer + openssl x509 -in acme-sh/acme-sh.acme/acme-sh.acme.cer -text -noout + shell: bash + + - name: "Check result" + if: steps.acmefail03.outcome != 'failure' + run: | + echo "acmefail outcome is ${{steps.acmefail03.outcome }}" + exit 1 + shell: bash + + - name: "Sleep for 2s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 2s + + - name: "Check logs for errors" + working-directory: examples/Docker/ + run: | + if [ ${{ inputs.DEPLOYMENT_TYPE }} == "container" ]; then + docker-compose logs > docker-compose.log + cat docker-compose.log | grep "failed for: organizationName: value: noacme corp expected: acme corp" + sudo truncate -s 0 $(docker inspect --format='{{.LogPath}}' acme2certifier_acme-srv_1) + # elif [ ${{ inputs.DEPLOYMENT_TYPE }} == "rpm" ]; then + # docker exec acme-srv grep "failed for: organizationName: value: noacme corp expected: acme corp" /var/log/messages + fi + shell: bash + + - name: "EAB SP - 03 - FAIL - Enroll lego - string check failed" + id: legofail03 + continue-on-error: true + run: | + sudo rm -rf lego/* + sudo openssl genrsa -out lego/lego.acme.key 2048 + sudo openssl req -new -key lego/lego.acme.key -subj '/CN=lego.acme/O=noacme corp/OU=acme2/C=AC/serialNumber=00-11-22-33' --addext "subjectAltName = DNS:lego.acme" -outform pem -out lego/lego.acme.csr + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --csr .lego/lego.acme.csr --http run + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + shell: bash + + - name: "Check result" + if: steps.legofail03.outcome != 'failure' + run: | + echo "legofail outcome is ${{steps.legofail03.outcome }}" + exit 1 + shell: bash + + - name: "Sleep for 2s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 2s + + - name: "Check logs for errors" + working-directory: examples/Docker/ + run: | + if [ ${{ inputs.DEPLOYMENT_TYPE }} == "container" ]; then + docker-compose logs > docker-compose.log + cat docker-compose.log | grep "failed for: organizationName: value: noacme corp expected: acme corp" + sudo truncate -s 0 $(docker inspect --format='{{.LogPath}}' acme2certifier_acme-srv_1) + # elif [ ${{ inputs.DEPLOYMENT_TYPE }} == "rpm" ]; then + # docker exec acme-srv grep "failed for: organizationName: value: noacme corp expected: acme corp" /var/log/messages + fi + shell: bash + + - name: "EAB SP - 04 - FAIL - Enroll acme - string parameter not present" + id: acmefail04 + continue-on-error: true + run: | + sudo rm -rf acme-sh/* + openssl genrsa -out acme-sh/acme-sh.acme.key 2048 + openssl req -new -key acme-sh/acme-sh.acme.key -subj '/CN=acme-sh.acme/O=acme corp/OU=acme2/serialNumber=00-11-22-33' --addext "subjectAltName = DNS:acme-sh.acme" -outform pem -out acme-sh/acme-sh.acme.csr + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_00 --eab-hmac-key V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name acme-sh neilpang/acme.sh:latest --signcsr --csr acme.sh/acme-sh.acme.csr --server http://acme-srv --standalone --debug 1 --output-insecure --insecure + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme/acme-sh.acme.cer + openssl x509 -in acme-sh/acme-sh.acme/acme-sh.acme.cer -text -noout + shell: bash + + - name: "Check result" + if: steps.acmefail04.outcome != 'failure' + run: | + echo "acmefail outcome is ${{steps.acmefail04.outcome }}" + exit 1 + shell: bash + + - name: "Sleep for 2s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 2s + + - name: "Check logs for errors" + working-directory: examples/Docker/ + run: | + if [ ${{ inputs.DEPLOYMENT_TYPE }} == "container" ]; then + docker-compose logs > docker-compose.log + cat docker-compose.log | grep "failed for: \['countryName'\]" + sudo truncate -s 0 $(docker inspect --format='{{.LogPath}}' acme2certifier_acme-srv_1) + # elif [ ${{ inputs.DEPLOYMENT_TYPE }} == "rpm" ]; then + # docker exec acme-srv grep "failed for: \['countryName'\]" /var/log/messages + fi + shell: bash + + - name: "EAB SP - 04 - FAIL - Enroll acme - string parameter not present" + id: legofail04 + continue-on-error: true + run: | + sudo rm -rf lego/* + sudo openssl genrsa -out lego/lego.acme.key 2048 + sudo openssl req -new -key lego/lego.acme.key -subj '/CN=lego.acme/O=acme corp/OU=acme2/serialNumber=00-11-22-33' --addext "subjectAltName = DNS:lego.acme" -outform pem -out lego/lego.acme.csr + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_00 --hmac V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw --csr .lego/lego.acme.csr --http run + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + shell: bash + + - name: "Check result" + if: steps.legofail04.outcome != 'failure' + run: | + echo "legofail outcome is ${{steps.legofail04.outcome }}" + exit 1 + shell: bash + + - name: "Sleep for 2s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 2s + + - name: "Check logs for errors" + working-directory: examples/Docker/ + run: | + if [ ${{ inputs.DEPLOYMENT_TYPE }} == "container" ]; then + docker-compose logs > docker-compose.log + cat docker-compose.log | grep "failed for: \['countryName'\]" + sudo truncate -s 0 $(docker inspect --format='{{.LogPath}}' acme2certifier_acme-srv_1) + # elif [ ${{ inputs.DEPLOYMENT_TYPE }} == "rpm" ]; then + # docker exec acme-srv grep "failed for: \['countryName'\]" /var/log/messages + fi + shell: bash + diff --git a/.github/actions/wf_specific/xca_ca_handler/enroll_headerinfo/action.yml b/.github/actions/wf_specific/xca_ca_handler/enroll_headerinfo/action.yml new file mode 100644 index 00000000..ea3c88d7 --- /dev/null +++ b/.github/actions/wf_specific/xca_ca_handler/enroll_headerinfo/action.yml @@ -0,0 +1,68 @@ +name: "enroll_headerinfo" +description: "enroll_headerinfo" + +runs: + using: "composite" + steps: + - name: "Sleep for 5s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 5s + + - name: "Header-info - Test http://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory + shell: bash + + - name: "Header-info - Test if https://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory + shell: bash + + - name: "Header-info - 01 - Enroll acme.sh without template_name" + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv --accountemail 'acme-sh@example.com' -d acme-sh.acme --standalone --debug 3 --output-insecure + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -text -noout + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -ext keyUsage -noout | grep "Digital Signature, Non Repudiation, Key Encipherment, Key Agreement" + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -ext extendedKeyUsage -noout | grep "TLS Web Server Authentication, TLS Web Client Authentication" + shell: bash + + - name: "Header-info - 01 - Enroll lego without template_name" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --http run + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -ext keyUsage | grep "Digital Signature, Non Repudiation, Key Encipherment, Key Agreement" + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -ext extendedKeyUsage | grep "TLS Web Server Authentication, TLS Web Client Authentication" + shell: bash + + - name: "Header-info - 02 - Enroll acme.sh with template_name template" + run: | + sudo rm -rf acme-sh/* + # docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv --accountemail 'acme-sh@example.com' --useragent template_name=template -d acme-sh.acme --standalone --debug 3 --output-insecure + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -text -noout + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -ext keyUsage -noout | grep "Digital Signature, Non Repudiation" + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -ext extendedKeyUsage -noout | grep "TLS Web Client Authentication, Code Signing" + shell: bash + + - name: "Header-info - 02 - Enroll lego with template_name template" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --user-agent template_name=template -d lego.acme --http run + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -ext keyUsage | grep "Digital Signature, Non Repudiation" + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -ext extendedKeyUsage | grep "TLS Web Client Authentication, Code Signing" + shell: bash + + - name: "Delete acme-sh, letsencypt and lego folders" + run: | + sudo rm -rf lego/* + sudo rm -rf acme-sh/* + sudo rm -rf certbot/* + shell: bash \ No newline at end of file diff --git a/.github/actions/wf_specific/xca_ca_handler/enroll_no_template/action.yml b/.github/actions/wf_specific/xca_ca_handler/enroll_no_template/action.yml new file mode 100644 index 00000000..2de41d0f --- /dev/null +++ b/.github/actions/wf_specific/xca_ca_handler/enroll_no_template/action.yml @@ -0,0 +1,56 @@ +name: "enroll_no_template" +description: "enroll_no_template" + +runs: + using: "composite" + steps: + - name: "Sleep for 5s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 5s + + - name: "No template - Test http://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory + shell: bash + + - name: "No template - Enroll acme.sh" + run: | + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv --accountemail 'acme-sh@example.com' -d acme-sh.acme --alpn --standalone --debug 3 --output-insecure + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -text -noout + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -text -noout | grep "Basic Constraints: critical" + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -text -noout | grep "Digital Signature, Key Encipherment" + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -text -noout | grep "TLS Web Server Authentication" + shell: bash + + - name: "No template - Register certbot" + run: | + docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email + shell: bash + + - name: "No template - Enroll HTTP-01 single domain certbot" + run: | + docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem + sudo openssl x509 -in certbot/archive/certbot/cert1.pem -text -noout + sudo openssl x509 -in certbot/archive/certbot/cert1.pem -text -noout | grep "Basic Constraints: critical" + sudo openssl x509 -in certbot/archive/certbot/cert1.pem -text -noout | grep "Digital Signature, Key Encipherment" + sudo openssl x509 -in certbot/archive/certbot/cert1.pem -text -noout | grep "TLS Web Server Authentication" + shell: bash + + - name: "No template - Enroll lego" + run: | + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --http run + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout | grep "Basic Constraints: critical" + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout | grep "Digital Signature, Key Encipherment" + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout | grep "TLS Web Server Authentication" + shell: bash + + - name: "Delete acme-sh, letsencypt and lego folders" + run: | + sudo rm -rf lego/* + sudo rm -rf acme-sh/* + sudo rm -rf certbot/* + shell: bash \ No newline at end of file diff --git a/.github/actions/wf_specific/xca_ca_handler/enroll_template/action.yml b/.github/actions/wf_specific/xca_ca_handler/enroll_template/action.yml new file mode 100644 index 00000000..e0981ce3 --- /dev/null +++ b/.github/actions/wf_specific/xca_ca_handler/enroll_template/action.yml @@ -0,0 +1,60 @@ +name: "enroll_template" +description: "enroll_template" + +runs: + using: "composite" + steps: + - name: "Sleep for 5s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 5s + + - name: "Template - Test http://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory + shell: bash + + - name: "Template - Test if https://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory + shell: bash + + - name: "Template - Enroll acme.sh" + run: | + sudo rm -rf acme-sh/* + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv --accountemail 'acme-sh@example.com' -d acme-sh.acme --alpn --standalone --debug 3 --output-insecure + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -text -noout + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -text -noout | grep "Digital Signature, Non Repudiation, Key Encipherment, Key Agreement" + openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -text -noout | grep "TLS Web Server Authentication, TLS Web Client Authentication" + shell: bash + + - name: "Template - Register certbot" + run: | + sudo rm -rf certbot/* + docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email + shell: bash + + - name: "Template - Enroll certbot" + run: | + docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem + sudo openssl x509 -in certbot/archive/certbot/cert1.pem -text -noout + sudo openssl x509 -in certbot/archive/certbot/cert1.pem -text -noout | grep "Digital Signature, Non Repudiation, Key Encipherment, Key Agreement" + sudo openssl x509 -in certbot/archive/certbot/cert1.pem -text -noout | grep "TLS Web Server Authentication, TLS Web Client Authentication" + shell: bash + + - name: "Template - Enroll lego" + run: | + sudo rm -rf lego/* + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --http run + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout | grep "Digital Signature, Non Repudiation, Key Encipherment, Key Agreement" + sudo openssl x509 -in lego/certificates/lego.acme.crt -text -noout | grep "TLS Web Server Authentication, TLS Web Client Authentication" + shell: bash + + - name: "Delete acme-sh, letsencypt and lego folders" + run: | + sudo rm -rf lego/* + sudo rm -rf acme-sh/* + sudo rm -rf certbot/* + shell: bash \ No newline at end of file diff --git a/.github/k8s-acme-srv.yml b/.github/k8s-acme-srv.yml index 4de1bd9a..7ccd8027 100644 --- a/.github/k8s-acme-srv.yml +++ b/.github/k8s-acme-srv.yml @@ -14,11 +14,20 @@ metadata: spec: hostname: acme-srv dnsPolicy: "None" + automountServiceAccountToken: false dnsConfig: nameservers: - DNSMASQ_IP containers: - name: acme2certifier + resources: + requests: + cpu: "250m" + memory: "256Mi" + ephemeral-storage: "1Gi" + limits: + memory: "512Mi" + ephemeral-storage: "1Gi" image: grindsa/acme2certifier:devel imagePullPolicy: Never ports: diff --git a/.github/k8s-cert-mgr-http-01.yml b/.github/k8s-cert-mgr-http-01.yml index 73f46812..340b8b18 100644 --- a/.github/k8s-cert-mgr-http-01.yml +++ b/.github/k8s-cert-mgr-http-01.yml @@ -12,9 +12,19 @@ spec: labels: app: webserver-app spec: + automountServiceAccountToken: false containers: - name: webserver-app image: nginx:1.8 + resources: + requests: + cpu: "100m" + memory: "128Mi" + ephemeral-storage: "1Gi" + limits: + cpu: "500m" + memory: "256Mi" + ephemeral-storage: "1Gi" --- apiVersion: v1 kind: Service diff --git a/.github/workflows/acme_sh-application-test.yml b/.github/workflows/acme_sh-application-test.yml deleted file mode 100644 index c4908b75..00000000 --- a/.github/workflows/acme_sh-application-test.yml +++ /dev/null @@ -1,523 +0,0 @@ -name: Application Tests - acme_sh - -on: - push: - pull_request: - branches: [ devel ] - schedule: - # * is a special character in YAML so you have to quote this string - - cron: '0 2 * * 6' - -jobs: - acme_sh_apache2_wsgi: - name: "acme_sh_apache2_wsgi" - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - accountkeylength: [2048, ec-256, ec-521] - keylength: [2048, 4096, ec-521] - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "[ PREPARE ] Build docker-compose (apache2_wsgi)" - working-directory: examples/Docker/ - run: | - sudo mkdir -p data - docker network create acme - docker-compose up -d - docker-compose logs - - - name: "Test http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - cd examples/Docker/ - docker-compose restart - docker-compose logs - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ ENROLL ] HTTP-01 single domain acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --keylength ${{ matrix.keylength }} --accountkeylength ${{ matrix.accountkeylength }} --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --standalone --debug 3 --output-insecure - if ([ "${{ matrix.keylength }}" == "ec-256" ] || [ "${{ matrix.keylength }}" == "ec-384" ] || [ "${{ matrix.keylength }}" == "ec-521" ]) ; then - ECC="_ecc" - fi - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme${ECC}/ca.cer - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme${ECC}/acme-sh.acme.cer - - - name: "[ RENEW ] HTTP-01 single domain acme.sh" - run: | - if ([ "${{ matrix.keylength }}" == "ec-256" ] || [ "${{ matrix.keylength }}" == "ec-384" ] || [ "${{ matrix.keylength }}" == "ec-521" ]) ; then - ECC="--ecc" - fi - docker exec -i acme-sh acme.sh --server http://acme-srv --keylength ${{ matrix.keylength }} --renew --force ${ECC} -d acme-sh.acme --standalone --debug 3 --output-insecure - if ([ "${{ matrix.keylength }}" == "ec-256" ] || [ "${{ matrix.keylength }}" == "ec-384" ] || [ "${{ matrix.keylength }}" == "ec-521" ]) ; then - ECC="_ecc" - fi - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme${ECC}/acme-sh.acme.cer - - - name: "[ REVOKE ] HTTP-01 single domain acme.sh" - run: | - if ([ "${{ matrix.keylength }}" == "ec-256" ] || [ "${{ matrix.keylength }}" == "ec-384" ] || [ "${{ matrix.keylength }}" == "ec-521" ]) ; then - ECC="--ecc" - fi - docker exec -i acme-sh acme.sh --server http://acme-srv --revoke ${ECC} -d acme-sh.acme --standalone --debug 2 --output-insecure - - - name: "[ ENROLL ] HTTP-01 2x domain acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --keylength ${{ matrix.keylength }} --issue -d acme-sh.acme -d acme-sh. --standalone --debug 3 --output-insecure - if ([ "${{ matrix.keylength }}" == "ec-256" ] || [ "${{ matrix.keylength }}" == "ec-384" ] || [ "${{ matrix.keylength }}" == "ec-521" ]) ; then - ECC="_ecc" - fi - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme${ECC}/acme-sh.acme.cer - - - name: "[ RENEW ] HTTP-01 2x domain acme.sh" - run: | - if ([ "${{ matrix.keylength }}" == "ec-256" ] || [ "${{ matrix.keylength }}" == "ec-384" ] || [ "${{ matrix.keylength }}" == "ec-521" ]) ; then - ECC="--ecc" - fi - docker exec -i acme-sh acme.sh --server http://acme-srv --keylength ${{ matrix.keylength }} --renew --force ${ECC} -d acme-sh.acme -d acme-sh. --standalone --debug 3 --output-insecure - if ([ "${{ matrix.keylength }}" == "ec-256" ] || [ "${{ matrix.keylength }}" == "ec-384" ] || [ "${{ matrix.keylength }}" == "ec-521" ]) ; then - ECC="_ecc" - fi - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme${ECC}/acme-sh.acme.cer - - - name: "[ REVOKE ] HTTP-01 2x domain acme.sh" - run: | - if ([ "${{ matrix.keylength }}" == "ec-256" ] || [ "${{ matrix.keylength }}" == "ec-384" ] || [ "${{ matrix.keylength }}" == "ec-521" ]) ; then - ECC="--ecc" - fi - docker exec -i acme-sh acme.sh --server http://acme-srv --revoke ${ECC} -d acme-sh.acme -d acme-sh. --standalone --debug 3 --output-insecure - - - name: "[ DEACTIVATE ] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --deactivate-account --debug 2 --output-insecure - - - name: "[ * ] collecting test data" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp acme-sh/ ${{ github.workspace }}/artifact/acme-sh/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data acme-sh - - - name: "[ * ] uploading artifacts" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: acme_sh_apache2_wsgi-${{ matrix.accountkeylength }}_key-${{ matrix.keylength }}.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - - acme_sh_apache2_django: - name: "acme_sh_apache2_django" - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - accountkeylength: [2048, ec-256, ec-521] - keylength: [2048, 4096, ec-521] - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "[ PREPARE ] Build docker-compose (apache2_django)" - working-directory: examples/Docker/ - run: | - sed -i "s/wsgi/django/g" .env - sudo mkdir -p data - docker network create acme - docker-compose up -d - docker-compose logs - - - name: "[ WAIT ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "Test http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - sudo cp .github/django_settings.py examples/Docker/data/settings.py - cd examples/Docker/ - docker-compose restart - docker-compose logs - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ ENROLL ] HTTP-01 single domain acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --keylength ${{ matrix.keylength }} --accountkeylength ${{ matrix.accountkeylength }} --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --standalone --debug 3 --output-insecure - if ([ "${{ matrix.keylength }}" == "ec-256" ] || [ "${{ matrix.keylength }}" == "ec-384" ] || [ "${{ matrix.keylength }}" == "ec-521" ]) ; then - ECC="_ecc" - fi - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme${ECC}/ca.cer - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme${ECC}/acme-sh.acme.cer - - - name: "[ RENEW ] HTTP-01 single domain acme.sh" - run: | - if ([ "${{ matrix.keylength }}" == "ec-256" ] || [ "${{ matrix.keylength }}" == "ec-384" ] || [ "${{ matrix.keylength }}" == "ec-521" ]) ; then - ECC="--ecc" - fi - docker exec -i acme-sh acme.sh --server http://acme-srv --keylength ${{ matrix.keylength }} --renew --force ${ECC} -d acme-sh.acme --standalone --debug 3 --output-insecure - if ([ "${{ matrix.keylength }}" == "ec-256" ] || [ "${{ matrix.keylength }}" == "ec-384" ] || [ "${{ matrix.keylength }}" == "ec-521" ]) ; then - ECC="_ecc" - fi - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme${ECC}/acme-sh.acme.cer - - - name: "[ REVOKE ] HTTP-01 single domain acme.sh" - run: | - if ([ "${{ matrix.keylength }}" == "ec-256" ] || [ "${{ matrix.keylength }}" == "ec-384" ] || [ "${{ matrix.keylength }}" == "ec-521" ]) ; then - ECC="--ecc" - fi - docker exec -i acme-sh acme.sh --server http://acme-srv --revoke ${ECC} -d acme-sh.acme --standalone --debug 2 --output-insecure - - - name: "[ ENROLL ] HTTP-01 2x domain acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --keylength ${{ matrix.keylength }} --issue -d acme-sh.acme -d acme-sh. --standalone --debug 3 --output-insecure - if ([ "${{ matrix.keylength }}" == "ec-256" ] || [ "${{ matrix.keylength }}" == "ec-384" ] || [ "${{ matrix.keylength }}" == "ec-521" ]) ; then - ECC="_ecc" - fi - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme${ECC}/acme-sh.acme.cer - - - name: "[ RENEW ] HTTP-01 2x domain acme.sh" - run: | - if ([ "${{ matrix.keylength }}" == "ec-256" ] || [ "${{ matrix.keylength }}" == "ec-384" ] || [ "${{ matrix.keylength }}" == "ec-521" ]) ; then - ECC="--ecc" - fi - docker exec -i acme-sh acme.sh --server http://acme-srv --keylength ${{ matrix.keylength }} --renew --force ${ECC} -d acme-sh.acme -d acme-sh. --standalone --debug 3 --output-insecure - if ([ "${{ matrix.keylength }}" == "ec-256" ] || [ "${{ matrix.keylength }}" == "ec-384" ] || [ "${{ matrix.keylength }}" == "ec-521" ]) ; then - ECC="_ecc" - fi - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme${ECC}/acme-sh.acme.cer - - - name: "[ REVOKE ] HTTP-01 2x domain acme.sh" - run: | - if ([ "${{ matrix.keylength }}" == "ec-256" ] || [ "${{ matrix.keylength }}" == "ec-384" ] || [ "${{ matrix.keylength }}" == "ec-521" ]) ; then - ECC="--ecc" - fi - docker exec -i acme-sh acme.sh --server http://acme-srv --revoke ${ECC} -d acme-sh.acme -d acme-sh. --standalone --debug 3 --output-insecure - - - name: "[ DEACTIVATE ] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --deactivate-account --debug 2 --output-insecure - - - name: "[ * ] collecting test data" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp acme-sh/ ${{ github.workspace }}/artifact/acme-sh/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data acme-sh - - - name: "[ * ] uploading artifacts" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: acme_sh_apache2_django-${{ matrix.accountkeylength }}_key-${{ matrix.keylength }}.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - - acme_sh_nginx_wsgi: - name: "acme_sh_nginx_wsgi" - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - accountkeylength: [2048, ec-256, ec-521] - keylength: [2048, 4096, ec-521] - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "[ PREPARE ] Build docker-compose (nginx_django)" - working-directory: examples/Docker/ - run: | - sed -i "s/apache2/nginx/g" .env - sudo mkdir -p data - docker network create acme - docker-compose up -d - docker-compose logs - - - name: "[ WAIT ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "Test http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - cd examples/Docker/ - docker-compose restart - docker-compose logs - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ ENROLL ] HTTP-01 single domain acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --keylength ${{ matrix.keylength }} --accountkeylength ${{ matrix.accountkeylength }} --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --standalone --debug 3 --output-insecure - if ([ "${{ matrix.keylength }}" == "ec-256" ] || [ "${{ matrix.keylength }}" == "ec-384" ] || [ "${{ matrix.keylength }}" == "ec-521" ]) ; then - ECC="_ecc" - fi - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme${ECC}/ca.cer - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme${ECC}/acme-sh.acme.cer - - - name: "[ RENEW ] HTTP-01 single domain acme.sh" - run: | - if ([ "${{ matrix.keylength }}" == "ec-256" ] || [ "${{ matrix.keylength }}" == "ec-384" ] || [ "${{ matrix.keylength }}" == "ec-521" ]) ; then - ECC="--ecc" - fi - docker exec -i acme-sh acme.sh --server http://acme-srv --keylength ${{ matrix.keylength }} --renew --force ${ECC} -d acme-sh.acme --standalone --debug 3 --output-insecure - if ([ "${{ matrix.keylength }}" == "ec-256" ] || [ "${{ matrix.keylength }}" == "ec-384" ] || [ "${{ matrix.keylength }}" == "ec-521" ]) ; then - ECC="_ecc" - fi - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme${ECC}/acme-sh.acme.cer - - - name: "[ REVOKE ] HTTP-01 single domain acme.sh" - run: | - if ([ "${{ matrix.keylength }}" == "ec-256" ] || [ "${{ matrix.keylength }}" == "ec-384" ] || [ "${{ matrix.keylength }}" == "ec-521" ]) ; then - ECC="--ecc" - fi - docker exec -i acme-sh acme.sh --server http://acme-srv --revoke ${ECC} -d acme-sh.acme --standalone --debug 2 --output-insecure - - - name: "[ ENROLL ] HTTP-01 2x domain acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --keylength ${{ matrix.keylength }} --issue -d acme-sh.acme -d acme-sh. --standalone --debug 3 --output-insecure - if ([ "${{ matrix.keylength }}" == "ec-256" ] || [ "${{ matrix.keylength }}" == "ec-384" ] || [ "${{ matrix.keylength }}" == "ec-521" ]) ; then - ECC="_ecc" - fi - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme${ECC}/acme-sh.acme.cer - - - name: "[ RENEW ] HTTP-01 2x domain acme.sh" - run: | - if ([ "${{ matrix.keylength }}" == "ec-256" ] || [ "${{ matrix.keylength }}" == "ec-384" ] || [ "${{ matrix.keylength }}" == "ec-521" ]) ; then - ECC="--ecc" - fi - docker exec -i acme-sh acme.sh --server http://acme-srv --keylength ${{ matrix.keylength }} --renew --force ${ECC} -d acme-sh.acme -d acme-sh. --standalone --debug 3 --output-insecure - if ([ "${{ matrix.keylength }}" == "ec-256" ] || [ "${{ matrix.keylength }}" == "ec-384" ] || [ "${{ matrix.keylength }}" == "ec-521" ]) ; then - ECC="_ecc" - fi - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme${ECC}/acme-sh.acme.cer - - - name: "[ REVOKE ] HTTP-01 2x domain acme.sh" - run: | - if ([ "${{ matrix.keylength }}" == "ec-256" ] || [ "${{ matrix.keylength }}" == "ec-384" ] || [ "${{ matrix.keylength }}" == "ec-521" ]) ; then - ECC="--ecc" - fi - docker exec -i acme-sh acme.sh --server http://acme-srv --revoke ${ECC} -d acme-sh.acme -d acme-sh. --standalone --debug 3 --output-insecure - - - name: "[ DEACTIVATE ] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --deactivate-account --debug 2 --output-insecure - - - name: "[ * ] collecting test data" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp acme-sh/ ${{ github.workspace }}/artifact/acme-sh/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data acme-sh - - - name: "[ * ] uploading artifacts" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: acme_sh_nginx_wsgi-${{ matrix.accountkeylength }}_key-${{ matrix.keylength }}.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - - acme_sh_nginx_django: - name: "acme_sh_nginx_django" - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - accountkeylength: [2048, ec-256, ec-521] - keylength: [2048, 4096, ec-521] - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "[ PREPARE ] Build docker-compose (nginx_django)" - working-directory: examples/Docker/ - run: | - sed -i "s/wsgi/django/g" .env - sed -i "s/apache2/nginx/g" .env - sudo mkdir -p data - docker network create acme - docker-compose up -d - docker-compose logs - - - name: "[ WAIT ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "Test http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - sudo cp .github/django_settings.py examples/Docker/data/settings.py - cd examples/Docker/ - docker-compose restart - docker-compose logs - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ ENROLL ] HTTP-01 single domain acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --keylength ${{ matrix.keylength }} --accountkeylength ${{ matrix.accountkeylength }} --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --standalone --debug 3 --output-insecure - if ([ "${{ matrix.keylength }}" == "ec-256" ] || [ "${{ matrix.keylength }}" == "ec-384" ] || [ "${{ matrix.keylength }}" == "ec-521" ]) ; then - ECC="_ecc" - fi - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme${ECC}/ca.cer - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme${ECC}/acme-sh.acme.cer - - - name: "[ RENEW ] HTTP-01 single domain acme.sh" - run: | - if ([ "${{ matrix.keylength }}" == "ec-256" ] || [ "${{ matrix.keylength }}" == "ec-384" ] || [ "${{ matrix.keylength }}" == "ec-521" ]) ; then - ECC="--ecc" - fi - docker exec -i acme-sh acme.sh --server http://acme-srv --keylength ${{ matrix.keylength }} --renew --force ${ECC} -d acme-sh.acme --standalone --debug 3 --output-insecure - if ([ "${{ matrix.keylength }}" == "ec-256" ] || [ "${{ matrix.keylength }}" == "ec-384" ] || [ "${{ matrix.keylength }}" == "ec-521" ]) ; then - ECC="_ecc" - fi - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme${ECC}/acme-sh.acme.cer - - - name: "[ REVOKE ] HTTP-01 single domain acme.sh" - run: | - if ([ "${{ matrix.keylength }}" == "ec-256" ] || [ "${{ matrix.keylength }}" == "ec-384" ] || [ "${{ matrix.keylength }}" == "ec-521" ]) ; then - ECC="--ecc" - fi - docker exec -i acme-sh acme.sh --server http://acme-srv --revoke ${ECC} -d acme-sh.acme --standalone --debug 2 --output-insecure - - - name: "[ ENROLL ] HTTP-01 2x domain acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --keylength ${{ matrix.keylength }} --issue -d acme-sh.acme -d acme-sh. --standalone --debug 3 --output-insecure - if ([ "${{ matrix.keylength }}" == "ec-256" ] || [ "${{ matrix.keylength }}" == "ec-384" ] || [ "${{ matrix.keylength }}" == "ec-521" ]) ; then - ECC="_ecc" - fi - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme${ECC}/acme-sh.acme.cer - - - name: "[ RENEW ] HTTP-01 2x domain acme.sh" - run: | - if ([ "${{ matrix.keylength }}" == "ec-256" ] || [ "${{ matrix.keylength }}" == "ec-384" ] || [ "${{ matrix.keylength }}" == "ec-521" ]) ; then - ECC="--ecc" - fi - docker exec -i acme-sh acme.sh --server http://acme-srv --keylength ${{ matrix.keylength }} --renew --force ${ECC} -d acme-sh.acme -d acme-sh. --standalone --debug 3 --output-insecure - if ([ "${{ matrix.keylength }}" == "ec-256" ] || [ "${{ matrix.keylength }}" == "ec-384" ] || [ "${{ matrix.keylength }}" == "ec-521" ]) ; then - ECC="_ecc" - fi - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme${ECC}/acme-sh.acme.cer - - - name: "[ REVOKE ] HTTP-01 2x domain acme.sh" - run: | - if ([ "${{ matrix.keylength }}" == "ec-256" ] || [ "${{ matrix.keylength }}" == "ec-384" ] || [ "${{ matrix.keylength }}" == "ec-521" ]) ; then - ECC="--ecc" - fi - docker exec -i acme-sh acme.sh --server http://acme-srv --revoke ${ECC} -d acme-sh.acme -d acme-sh. --standalone --debug 3 --output-insecure - - - name: "[ DEACTIVATE ] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --deactivate-account --debug 2 --output-insecure - - - name: "[ * ] collecting test data" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp acme-sh/ ${{ github.workspace }}/artifact/acme-sh/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data acme-sh - - - name: "[ * ] uploading artifacts" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: acme_sh_nginx_django-${{ matrix.accountkeylength }}_key-${{ matrix.keylength }}.tar.gz - path: ${{ github.workspace }}/artifact/upload/ diff --git a/.github/workflows/alpn-test.yml b/.github/workflows/alpn-test.yml index 568e829e..33075720 100644 --- a/.github/workflows/alpn-test.yml +++ b/.github/workflows/alpn-test.yml @@ -9,69 +9,77 @@ on: - cron: '0 2 * * 6' jobs: - alpn_apache2_wsgi: - name: "alpn_apache2_wsgi" + alpn_container_tests: + name: "alpn_container_tests" runs-on: ubuntu-latest + strategy: + fail-fast: false + max-parallel: 2 + matrix: + websrv: ['apache2', 'nginx'] + dbhandler: ['wsgi', 'django'] steps: - name: "checkout GIT" - uses: actions/checkout@v3 + uses: actions/checkout@v4 - - name: "[ PREPARE ] create letsencrypt and lego folder" - run: | - mkdir acmme-sh - mkdir lego - - - name: "[ PREPARE ] Build docker-compose (apache2_wsgi)" - working-directory: examples/Docker/ - run: | - sudo mkdir -p data - docker network create acme - docker-compose up -d - docker-compose logs + - name: "Build container" + uses: ./.github/actions/container_prep + with: + DB_HANDLER: ${{ matrix.dbhandler }} + WEB_SRV: ${{ matrix.websrv }} - - name: "Test http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory + - name: "Prepare acme_srv.cfg with certifier_ca_handler" + uses: ./.github/actions/wf_specific/certifier_ca_handler/certifier_setup_no_profile + with: + WCCE_SSH_ACCESS_KEY: ${{ secrets.WCCE_SSH_ACCESS_KEY }} + WCCE_SSH_KNOWN_HOSTS: ${{ secrets.WCCE_SSH_KNOWN_HOSTS }} + WCCE_SSH_USER: ${{ secrets.WCCE_SSH_USER }} + WCCE_SSH_HOST: ${{ secrets.WCCE_SSH_HOST }} + WCCE_SSH_PORT: ${{ secrets.WCCE_SSH_PORT }} + NCM_API_HOST: ${{ secrets.NCM_API_HOST }} + NCM_API_USER: ${{ secrets.NCM_API_USER }} + NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} + NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} + DATA_PATH: examples/Docker/data - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" + - name: "Restart a2c" run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg cd examples/Docker/ docker-compose restart docker-compose logs - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - name: "Test http://acme-srv/directory is accessable again" + - name: "Create folders" + run: | + mkdir acmme-sh + mkdir lego + + - name: "Sleep for 10s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 10s + + - name: "Test http://acme-srv/directory is accessible" run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - name: "[ PREPARE ] prepare acme.sh container" - run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon + - name: "Test if https://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory - - name: "[ ENROLL ] acme.sh" + - name: "Enroll acme.sh" run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --alpn --standalone --debug 3 --output-insecure --force + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv --accountemail 'acme-sh@example.com' -d acme-sh.acme --alpn --standalone --debug 3 --output-insecure awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer - ls -la *.pem - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - name: "[ ENROLL ] lego" + - name: "Enroll lego" run: | docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --tls run - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + + - name: "Check container configuration" + uses: ./.github/actions/container_check + with: + DB_HANDLER: ${{ matrix.dbhandler }} + WEB_SRV: ${{ matrix.websrv }} - name: "[ * ] collecting test logs" if: ${{ failure() }} @@ -82,101 +90,72 @@ jobs: sudo cp -rp lego/ ${{ github.workspace }}/artifact/lego/ cd examples/Docker docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data acme-sh lego - + sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: ${{ failure() }} with: - name: alpn.tar.gz + name: alpn_containercontainer-${{ matrix.websrv }}-${{ matrix.dbhandler }}.tar.gz path: ${{ github.workspace }}/artifact/upload/ - alpn_apache2_wsgi_rpm: - name: "alpn_apache2_wsgi_rpm" + alpn_wsgi_rpm: + name: "alpn_wsgi_rpm" runs-on: ubuntu-latest + strategy: + fail-fast: false + max-parallel: 1 + matrix: + rhversion: [8, 9] steps: - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: Retrieve Version from version.py - run: | - echo TAG_NAME=$(cat acme_srv/version.py | grep -i __version__ | head -n 1 | sed 's/__version__ = //g' | sed s/\'//g) >> $GITHUB_ENV - - run: echo "Latest tag is ${{ env.TAG_NAME }}" + uses: actions/checkout@v4 - - name: update version number in spec file - run: | - # sudo sed -i "s/Source0:.*/Source0: %{name}-%{version}.tar.gz/g" examples/install_scripts/rpm/acme2certifier.spec - sudo sed -i "s/__version__/${{ env.TAG_NAME }}/g" examples/install_scripts/rpm/acme2certifier.spec - cat examples/install_scripts/rpm/acme2certifier.spec + - name: "Prepare Alma environment" + uses: ./.github/actions/rpm_prep + with: + GH_SBOM_USER: ${{ secrets.GH_SBOM_USER }} + GH_SBOM_TOKEN: ${{ secrets.GH_SBOM_TOKEN }} + RH_VERSION: ${{ matrix.rhversion }} - - name: "[ PREPARE ] create letsencrypt and lego folder" + - name: "Create letsencrypt and lego folder" run: | mkdir acmme-sh mkdir lego - - name: build RPM package - id: rpm - uses: grindsa/rpmbuild@alma9 + - name: "Prepare acme_srv.cfg with certifier_ca_handler" + uses: ./.github/actions/wf_specific/certifier_ca_handler/certifier_setup_no_profile with: - spec_file: "examples/install_scripts/rpm/acme2certifier.spec" - - - run: echo "path is ${{ steps.rpm.outputs.rpm_dir_path }}" - - - name: "[ PREPARE ] setup environment for alma installation" - run: | - docker network create acme - sudo mkdir -p data - sudo chmod -R 777 data - sudo cp ${{ steps.rpm.outputs.rpm_dir_path }}noarch/acme2certifier-${{ env.TAG_NAME }}-1.0.noarch.rpm data - sudo cp examples/Docker/almalinux-systemd/rpm_tester.sh data - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - mkdir -p data/acme_ca - sudo cp test/ca/certsrv_ca_certs.pem data/acme_ca/ca_certs.pem - sudo touch data/acme_srv.cfg - sudo chmod 777 data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> data/acme_srv.cfg - sudo echo "profile_id: 101" >> data/acme_srv.cfg - env: + WCCE_SSH_ACCESS_KEY: ${{ secrets.WCCE_SSH_ACCESS_KEY }} + WCCE_SSH_KNOWN_HOSTS: ${{ secrets.WCCE_SSH_KNOWN_HOSTS }} + WCCE_SSH_USER: ${{ secrets.WCCE_SSH_USER }} + WCCE_SSH_HOST: ${{ secrets.WCCE_SSH_HOST }} + WCCE_SSH_PORT: ${{ secrets.WCCE_SSH_PORT }} NCM_API_HOST: ${{ secrets.NCM_API_HOST }} NCM_API_USER: ${{ secrets.NCM_API_USER }} NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} + DATA_PATH: data - - name: "[ PREPARE ] Almalinux instance" - run: | - cat examples/Docker/almalinux-systemd/Dockerfile | docker build -t almalinux-systemd -f - . --no-cache - docker run -d -id --privileged --network acme --name=acme-srv -v "$(pwd)/data":/tmp/acme2certifier almalinux-systemd - - - name: "[ RUN ] Execute install scipt" + - name: "Execute install script" run: | docker exec acme-srv sh /tmp/acme2certifier/rpm_tester.sh - name: "Test http://acme-srv/directory is accessible" run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - name: "[ PREPARE ] prepare acme.sh container" - run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon + - name: "Test if https://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory - - name: "[ ENROLL ] acme.sh" + - name: "Enroll acme.sh" run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --alpn --standalone --debug 3 --output-insecure --force + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv --accountemail 'acme-sh@example.com' -d acme-sh.acme --alpn --standalone --debug 3 --output-insecure awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - name: "[ ENROLL ] lego" + - name: "Enroll lego" run: | docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --tls run - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt - name: "[ * ] collecting test logs" if: ${{ failure() }} @@ -184,13 +163,16 @@ jobs: mkdir -p ${{ github.workspace }}/artifact/upload docker exec acme-srv tar cvfz /tmp/acme2certifier/a2c.tgz /opt/acme2certifier sudo cp -rp data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp acme-sh/ ${{ github.workspace }}/artifact/acme-sh/ + sudo rm ${{ github.workspace }}/artifact/data/*.rpm + # sudo cp -rp acme-sh/ ${{ github.workspace }}/artifact/acme-sh/ + docker exec acme-srv cat /etc/nginx/nginx.conf.orig > ${{ github.workspace }}/artifact/data/nginx.conf.orig + docker exec acme-srv cat /etc/nginx/nginx.conf > ${{ github.workspace }}/artifact/data/nginx.conf docker exec acme-srv cat /var/log/messages > ${{ github.workspace }}/artifact/acme-srv.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz data acme-srv.log acme-sh + sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz data acme-srv.log # acme-sh - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: ${{ failure() }} with: - name: alpn-rpm.tar.gz - path: ${{ github.workspace }}/artifact/upload/ \ No newline at end of file + name: alpn-rpm-rh${{ matrix.rhversion }}.tar.gz + path: ${{ github.workspace }}/artifact/upload/ diff --git a/.github/workflows/ari-test.yml b/.github/workflows/ari-test.yml index 5fc709b2..35f4a3fb 100644 --- a/.github/workflows/ari-test.yml +++ b/.github/workflows/ari-test.yml @@ -10,53 +10,63 @@ on: jobs: - ari_apache2_wsgi: - name: "ari_apache2_wsgi" + ari_container_tests: + name: "ari_container_tests" runs-on: ubuntu-latest + strategy: + fail-fast: false + max-parallel: 2 + matrix: + websrv: ['apache2', 'nginx'] + dbhandler: ['wsgi', 'django'] steps: - name: "checkout GIT" - uses: actions/checkout@v3 + uses: actions/checkout@v4 - - name: "[ PREPARE ] Build docker-compose (apache2_wsgi)" - working-directory: examples/Docker/ - run: | - sudo mkdir -p data - docker network create acme - docker-compose up -d - docker-compose logs + - name: "Build container" + uses: ./.github/actions/container_prep + with: + DB_HANDLER: ${{ matrix.dbhandler }} + WEB_SRV: ${{ matrix.websrv }} - - name: "Test http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory + - name: "Prepare acme_srv.cfg with certifier_ca_handler" + uses: ./.github/actions/wf_specific/certifier_ca_handler/certifier_setup_no_profile + with: + WCCE_SSH_ACCESS_KEY: ${{ secrets.WCCE_SSH_ACCESS_KEY }} + WCCE_SSH_KNOWN_HOSTS: ${{ secrets.WCCE_SSH_KNOWN_HOSTS }} + WCCE_SSH_USER: ${{ secrets.WCCE_SSH_USER }} + WCCE_SSH_HOST: ${{ secrets.WCCE_SSH_HOST }} + WCCE_SSH_PORT: ${{ secrets.WCCE_SSH_PORT }} + NCM_API_HOST: ${{ secrets.NCM_API_HOST }} + NCM_API_USER: ${{ secrets.NCM_API_USER }} + NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} + NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} + DATA_PATH: examples/Docker/data - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" + - name: "Restart a2c" run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg sudo echo -e "\n\n[Renewalinfo]" >> examples/Docker/data/acme_srv.cfg sudo echo "renewal_force: True" >> examples/Docker/data/acme_srv.cfg cd examples/Docker/ docker-compose restart docker-compose logs - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - name: "create lego folder" + - name: "Sleep for 10s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 10s + + - name: "Create lego folder" run: | mkdir lego - - name: "[ ENROLL ] HTTP-01 single domain lego" + - name: "Test http://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory + + - name: "Test if https://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory + + - name: "Enroll lego" run: | docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --http run sudo chmod 777 lego/certificates/lego.acme.issuer.crt @@ -64,13 +74,19 @@ jobs: sudo awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < lego.acme.issuer.crt sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt - - name: "[ RENEW ] HTTP-01 single domain lego" + - name: "Renew lego" run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --http renew --ari-enable --no-random-sleep 2> ari.txt + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --http renew --no-random-sleep 2> ari.txt grep "renewalInfo endpoint indicates that renewal is needed" ari.txt cat ari.txt sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + - name: "Check container configuration" + uses: ./.github/actions/container_check + with: + DB_HANDLER: ${{ matrix.dbhandler }} + WEB_SRV: ${{ matrix.websrv }} + - name: "[ * ] collecting test logs" if: ${{ failure() }} run: | @@ -82,66 +98,59 @@ jobs: sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data lego - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: ${{ failure() }} with: - name: ari_apache2_wsgi.tar.gz + name: ari_container-${{ matrix.websrv }}-${{ matrix.dbhandler }}.tar.gz path: ${{ github.workspace }}/artifact/upload/ - ari_apache2_django: - name: "ari_apache2_django" + ari_wsgi_rpm: + name: "ari_wsgi_rpm" runs-on: ubuntu-latest + strategy: + fail-fast: false + max-parallel: 1 + matrix: + rhversion: [8, 9] steps: - name: "checkout GIT" - uses: actions/checkout@v3 + uses: actions/checkout@v4 - - name: "[ PREPARE ] Build docker-compose (apache2_django)" - working-directory: examples/Docker/ - run: | - sed -i "s/wsgi/django/g" .env - sudo mkdir -p data - docker network create acme - docker-compose up -d - docker-compose logs - - - name: "[ WAIT ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 + - name: "Prepare Alma environment" + uses: ./.github/actions/rpm_prep with: - time: 10s + GH_SBOM_USER: ${{ secrets.GH_SBOM_USER }} + GH_SBOM_TOKEN: ${{ secrets.GH_SBOM_TOKEN }} + RH_VERSION: ${{ matrix.rhversion }} - - name: "Test http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - sudo echo -e "\n\n[Renewalinfo]" >> examples/Docker/data/acme_srv.cfg - sudo echo "renewal_force: True" >> examples/Docker/data/acme_srv.cfg - sudo cp .github/django_settings.py examples/Docker/data/settings.py - cd examples/Docker/ - docker-compose restart - docker-compose logs - env: + - name: "Prepare acme_srv.cfg with certifier_ca_handler" + uses: ./.github/actions/wf_specific/certifier_ca_handler/certifier_setup_no_profile + with: + WCCE_SSH_ACCESS_KEY: ${{ secrets.WCCE_SSH_ACCESS_KEY }} + WCCE_SSH_KNOWN_HOSTS: ${{ secrets.WCCE_SSH_KNOWN_HOSTS }} + WCCE_SSH_USER: ${{ secrets.WCCE_SSH_USER }} + WCCE_SSH_HOST: ${{ secrets.WCCE_SSH_HOST }} + WCCE_SSH_PORT: ${{ secrets.WCCE_SSH_PORT }} NCM_API_HOST: ${{ secrets.NCM_API_HOST }} NCM_API_USER: ${{ secrets.NCM_API_USER }} NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} + DATA_PATH: data + + - name: "Restart a2c" + run: | + sudo echo -e "\n\n[Renewalinfo]" >> data/acme_srv.cfg + sudo echo "renewal_force: True" >> data/acme_srv.cfg + + - name: "Execute install scipt" + run: | + docker exec acme-srv sh /tmp/acme2certifier/rpm_tester.sh - - name: "create lego folder" + - name: "Create lego folder" run: | mkdir lego - - name: "[ ENROLL ] HTTP-01 single domain lego" + - name: "Enroll HTTP-01 single domain lego" run: | docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --http run sudo chmod 777 lego/certificates/lego.acme.issuer.crt @@ -149,9 +158,9 @@ jobs: sudo awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < lego.acme.issuer.crt sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt - - name: "[ RENEW ] HTTP-01 single domain lego" + - name: "Renew HTTP-01 single domain lego" run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --http renew --ari-enable --no-random-sleep 2> ari.txt + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --http renew --no-random-sleep 2> ari.txt grep "renewalInfo endpoint indicates that renewal is needed" ari.txt cat ari.txt sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt @@ -160,158 +169,76 @@ jobs: if: ${{ failure() }} run: | mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ + docker exec acme-srv tar cvfz /tmp/acme2certifier/a2c.tgz /opt/acme2certifier + sudo cp -rp data/ ${{ github.workspace }}/artifact/data/ sudo cp -rp lego/ ${{ github.workspace }}/artifact/lego/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data lego + sudo rm ${{ github.workspace }}/artifact/data/*.rpm + docker exec acme-srv cat /etc/nginx/nginx.conf.orig > ${{ github.workspace }}/artifact/data/nginx.conf.orig + docker exec acme-srv cat /etc/nginx/nginx.conf > ${{ github.workspace }}/artifact/data/nginx.conf + docker exec acme-srv cat /var/log/messages > ${{ github.workspace }}/artifact/acme-srv.log + sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz data acme-srv.log lego - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: ${{ failure() }} with: - name: ari_apache2_django.tar.gz + name: ari_wsgi_rpm-rh${{ matrix.rhversion }}.tar.gz path: ${{ github.workspace }}/artifact/upload/ - ari_nginx_wsgi: - name: "ari_nginx_wsgi" + + ari_django_rpm: + name: "ari_django_rpm" runs-on: ubuntu-latest + strategy: + fail-fast: false + max-parallel: 1 + matrix: + rhversion: [8, 9] steps: - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "[ PREPARE ] Build docker-compose (nginx_django)" - working-directory: examples/Docker/ - run: | - sed -i "s/apache2/nginx/g" .env - sudo mkdir -p data - docker network create acme - docker-compose up -d - docker-compose logs + uses: actions/checkout@v4 - - name: "[ WAIT ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 + - name: "Prepare Alma environment" + uses: ./.github/actions/rpm_prep with: - time: 10s - - - name: "Test http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory + GH_SBOM_USER: ${{ secrets.GH_SBOM_USER }} + GH_SBOM_TOKEN: ${{ secrets.GH_SBOM_TOKEN }} + RH_VERSION: ${{ matrix.rhversion }} - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" + - name: "Create lego folder" run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - sudo echo -e "\n\n[Renewalinfo]" >> examples/Docker/data/acme_srv.cfg - sudo echo "renewal_force: True" >> examples/Docker/data/acme_srv.cfg - cd examples/Docker/ - docker-compose restart - docker-compose logs - env: + mkdir lego + + - name: "Prepare acme_srv.cfg with certifier_ca_handler" + uses: ./.github/actions/wf_specific/certifier_ca_handler/certifier_setup_no_profile + with: + WCCE_SSH_ACCESS_KEY: ${{ secrets.WCCE_SSH_ACCESS_KEY }} + WCCE_SSH_KNOWN_HOSTS: ${{ secrets.WCCE_SSH_KNOWN_HOSTS }} + WCCE_SSH_USER: ${{ secrets.WCCE_SSH_USER }} + WCCE_SSH_HOST: ${{ secrets.WCCE_SSH_HOST }} + WCCE_SSH_PORT: ${{ secrets.WCCE_SSH_PORT }} NCM_API_HOST: ${{ secrets.NCM_API_HOST }} NCM_API_USER: ${{ secrets.NCM_API_USER }} NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "create lego folder" - run: | - mkdir lego - - - name: "[ ENROLL ] HTTP-01 single domain lego" - run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --http run - sudo chmod 777 lego/certificates/lego.acme.issuer.crt - sudo cp lego/certificates/lego.acme.issuer.crt lego.acme.issuer.crt - sudo awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < lego.acme.issuer.crt - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + DATA_PATH: data/volume - - name: "[ RENEW ] HTTP-01 single domain lego" + - name: "Restart a2c" run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --http renew --ari-enable --no-random-sleep 2> ari.txt - grep "renewalInfo endpoint indicates that renewal is needed" ari.txt - cat ari.txt - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo echo -e "\n\n[Renewalinfo]" >> data/volume/acme_srv.cfg + sudo echo "renewal_force: True" >> data/volume/acme_srv.cfg - - name: "[ * ] collecting test logs" - if: ${{ failure() }} + - name: "Execute install scipt" run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp lego/ ${{ github.workspace }}/artifact/lego/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data lego + docker exec acme-srv sh /tmp/acme2certifier/django_tester.sh - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: ari_nginx_wsgi.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - - ari_nginx_django: - name: "lego_nginx_django" - runs-on: ubuntu-latest - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "[ PREPARE ] Build docker-compose (nginx_django)" - working-directory: examples/Docker/ - run: | - sed -i "s/wsgi/django/g" .env - sed -i "s/apache2/nginx/g" .env - sudo mkdir -p data - docker network create acme - docker-compose up -d - docker-compose logs - - - name: "[ WAIT ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "Test http://acme-srv/directory is accessable" + - name: "Test http://acme-srv/directory is accessible" run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - sudo echo -e "\n\n[Renewalinfo]" >> examples/Docker/data/acme_srv.cfg - sudo echo "renewal_force: True" >> examples/Docker/data/acme_srv.cfg - sudo cp .github/django_settings.py examples/Docker/data/settings.py - cd examples/Docker/ - docker-compose restart - docker-compose logs - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} + - name: "Test if https://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory - - name: "create lego folder" - run: | - mkdir lego - - - name: "[ ENROLL ] HTTP-01 single domain lego" + - name: "Enroll HTTP-01 single domain lego" run: | docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --http run sudo chmod 777 lego/certificates/lego.acme.issuer.crt @@ -319,9 +246,9 @@ jobs: sudo awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < lego.acme.issuer.crt sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt - - name: "[ RENEW ] HTTP-01 single domain lego" + - name: "Renew HTTP-01 single domain lego" run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --http renew --ari-enable --no-random-sleep 2> ari.txt + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --http renew --no-random-sleep 2> ari.txt grep "renewalInfo endpoint indicates that renewal is needed" ari.txt cat ari.txt sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt @@ -330,15 +257,20 @@ jobs: if: ${{ failure() }} run: | mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ + docker exec acme-srv tar cvfz /tmp/acme2certifier/a2c.tgz /opt/acme2certifier + docker exec acme-srv tar cvfz /tmp/acme2certifier/nginx.tgz /etc/nginx + sudo cp -rp data/ ${{ github.workspace }}/artifact/data/ sudo cp -rp lego/ ${{ github.workspace }}/artifact/lego/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data lego + sudo rm ${{ github.workspace }}/artifact/data/*.rpm + docker exec acme-srv cat /etc/nginx/nginx.conf.orig > ${{ github.workspace }}/artifact/data/nginx.conf.orig + docker exec acme-srv cat /etc/nginx/nginx.conf > ${{ github.workspace }}/artifact/data/nginx.conf + docker exec acme-srv rpm -qa > ${{ github.workspace }}/artifact/data/packages.txt + docker exec acme-srv cat /var/log/messages > ${{ github.workspace }}/artifact/acme-srv.log + sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz data acme-srv.log lego - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: ${{ failure() }} with: - name: ari_nginx_django.tar.gz - path: ${{ github.workspace }}/artifact/upload/ + name: ari_django_rpm-rh${{ matrix.rhversion }}.tar.gz + path: ${{ github.workspace }}/artifact/upload/ \ No newline at end of file diff --git a/.github/workflows/ca_handler_tests_asa.yml b/.github/workflows/ca_handler_tests_asa.yml new file mode 100644 index 00000000..89594e49 --- /dev/null +++ b/.github/workflows/ca_handler_tests_asa.yml @@ -0,0 +1,604 @@ +name: CA handler Tests - Insta ASA + +on: + push: + pull_request: + branches: [ devel ] + schedule: + # * is a special character in YAML so you have to quote this string + - cron: '0 2 * * 6' + +jobs: + asa_handler_headerinfo_tests: + name: "asa_handler_headerinfo_tests" + runs-on: ubuntu-latest + steps: + - name: "checkout GIT" + uses: actions/checkout@v4 + + - name: "Build container" + uses: ./.github/actions/container_prep + with: + DB_HANDLER: "wsgi" + WEB_SRV: "apache2" + + - name: "Create lego folder" + run: | + mkdir lego + + - name: "Test http://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory + + - name: "a2c configuration with standard profile" + run: | + sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem + sudo touch examples/Docker/data/acme_srv.cfg + sudo chmod 777 examples/Docker/data/acme_srv.cfg + sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg + sudo echo "handler_file: examples/ca_handler/asa_ca_handler.py" >> examples/Docker/data/acme_srv.cfg + sudo echo "api_host: $ASA_API_HOST" >> examples/Docker/data/acme_srv.cfg + sudo echo "api_user: $ASA_API_USER" >> examples/Docker/data/acme_srv.cfg + sudo echo "api_password: $ASA_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg + sudo echo "api_key: $ASA_API_KEY" >> examples/Docker/data/acme_srv.cfg + sudo echo "ca_name: $ASA_CA_NAME" >> examples/Docker/data/acme_srv.cfg + sudo echo "ca_bundle: $ASA_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg + sudo echo "profile_name: $ASA_POFILE1" >> examples/Docker/data/acme_srv.cfg + sudo sed -i "s/revocation_reason_check_disable: False/revocation_reason_check_disable: False\nenrollment_timeout:15/g" examples/Docker/data/acme_srv.cfg + sudo sed -i "s/tnauthlist_support: False/tnauthlist_support: False\nheader_info_list: [\"HTTP_USER_AGENT\"]/g" examples/Docker/data/acme_srv.cfg + cd examples/Docker/ + docker-compose restart + env: + ASA_API_HOST: ${{ secrets.ASA_API_HOST }} + ASA_API_USER: ${{ secrets.ASA_API_USER }} + ASA_API_PASSWORD: ${{ secrets.ASA_API_PASSWORD }} + ASA_API_KEY: ${{ secrets.ASA_API_KEY }} + ASA_CA_NAME: ${{ secrets.ASA_CA_NAME }} + ASA_CA_BUNDLE: ${{ secrets.ASA_CA_BUNDLE }} + ASA_PROFILE1: ${{ secrets.ASA_POFILE1 }} + + - name: "Test http://acme-srv/directory is accessible again" + run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory + + - name: "Enroll lego with profileID ACME - could potenially fail" + continue-on-error: True + run: | + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --user-agent profile_name=ACME -d lego.acme --key-type rsa2048 --http run + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl x509 -in lego/certificates/lego.acme.crt -ext keyUsage -noout | grep "Digital Signature" + + - name: "Enroll acme.sh with profileID ACME" + run: | + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv --accountemail 'acme-sh@example.com' -d acme-sh.acme --standalone --useragent profile_name=ACME --keylength 2048 --debug 3 --output-insecure + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme/ca.cer + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme/acme-sh.acme.cer + openssl x509 -in acme-sh/acme-sh.acme/acme-sh.acme.cer -ext keyUsage -noout | grep "Digital Signature" + + - name: "Enroll lego with profileID ACME" + run: | + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --user-agent profile_name=ACME -d lego.acme --key-type rsa2048 --http run + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl x509 -in lego/certificates/lego.acme.crt -ext keyUsage -noout | grep "Digital Signature" + + - name: "Enroll acme.sh with profileID ACME_2" + run: | + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --renew --server http://acme-srv --force -d acme-sh.acme --standalone --useragent profile_name=ACME_2 --keylength 2048 --debug 3 --output-insecure + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme/acme-sh.acme.cer + openssl x509 -in acme-sh/acme-sh.acme/acme-sh.acme.cer -ext keyUsage -noout | grep "Key Encipherment, Data Encipherment" + + - name: "Enroll lego with profileID ACME_2" + run: | + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --user-agent profile_name=ACME_2 -d lego.acme --key-type rsa2048 --http run + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo openssl x509 -in lego/certificates/lego.acme.crt -ext keyUsage -noout | grep "Key Encipherment, Data Encipherment" + + - name: "[ * ] collecting test logs" + if: ${{ failure() }} + run: | + mkdir -p ${{ github.workspace }}/artifact/upload + sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ + sudo cp -rp lego/ ${{ github.workspace }}/artifact/lego/ + cd examples/Docker + docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log + sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data lego + + - name: "[ * ] uploading artificates" + uses: actions/upload-artifact@v4 + if: ${{ failure() }} + with: + name: asa_handler_headerinfo_tests.tar.gz + path: ${{ github.workspace }}/artifact/upload/ + + asa_handler_tests: + name: "asa_handler_tests" + runs-on: ubuntu-latest + needs: asa_handler_headerinfo_tests + strategy: + max-parallel: 2 + fail-fast: false + matrix: + websrv: ['apache2', 'nginx'] + dbhandler: ['wsgi', 'django'] + steps: + - name: "checkout GIT" + uses: actions/checkout@v4 + + - name: "create folders" + run: | + mkdir lego + mkdir acme-sh + mkdir certbot + + - name: "Build container" + uses: ./.github/actions/container_prep + with: + DB_HANDLER: ${{ matrix.dbhandler }} + WEB_SRV: ${{ matrix.websrv }} + + - name: "Profile ${{ secrets.ASA_PROFILE1 }} - Setup a2c with asa_ca_handler with profile ${{ secrets.ASA_PROFILE1 }}" + run: | + sudo cp .github/openssl_ca_handler.py_acme_srv_default_handler.cfg examples/Docker/data/acme_srv.cfg + sudo chmod 777 examples/Docker/data/acme_srv.cfg + sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem + sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg + sudo echo "handler_file: examples/ca_handler/asa_ca_handler.py" >> examples/Docker/data/acme_srv.cfg + sudo echo "api_host: $ASA_API_HOST" >> examples/Docker/data/acme_srv.cfg + sudo echo "api_user: $ASA_API_USER" >> examples/Docker/data/acme_srv.cfg + sudo echo "api_password: $ASA_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg + sudo echo "api_key: $ASA_API_KEY" >> examples/Docker/data/acme_srv.cfg + sudo echo "ca_name: $ASA_CA_NAME" >> examples/Docker/data/acme_srv.cfg + sudo echo "ca_bundle: $ASA_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg + sudo echo "profile_name: $ASA_PROFILE1" >> examples/Docker/data/acme_srv.cfg + sudo sed -i "s/revocation_reason_check_disable: False/revocation_reason_check_disable: False\nenrollment_timeout:15/g" examples/Docker/data/acme_srv.cfg + cd examples/Docker/ + docker-compose restart + env: + ASA_API_HOST: ${{ secrets.ASA_API_HOST }} + ASA_API_USER: ${{ secrets.ASA_API_USER }} + ASA_API_PASSWORD: ${{ secrets.ASA_API_PASSWORD }} + ASA_API_KEY: ${{ secrets.ASA_API_KEY }} + ASA_CA_NAME: ${{ secrets.ASA_CA_NAME }} + ASA_CA_BUNDLE: ${{ secrets.ASA_CA_BUNDLE }} + ASA_PROFILE1: ${{ secrets.ASA_PROFILE1 }} + + - name: "${{ secrets.ASA_PROFILE1 }} - enrollment" + uses: ./.github/actions/wf_specific/asa_ca_handler/enroll_profile_1 + with: + PROFILE: ${{ secrets.ASA_PROFILE1 }} + + - name: "Profile ${{ secrets.ASA_PROFILE2 }} - Reconfiguration of a2c with a new profile" + run: | + sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem + sudo touch examples/Docker/data/acme_srv.cfg + sudo chmod 777 examples/Docker/data/acme_srv.cfg + sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg + sudo echo "handler_file: examples/ca_handler/asa_ca_handler.py" >> examples/Docker/data/acme_srv.cfg + sudo echo "api_host: $ASA_API_HOST" >> examples/Docker/data/acme_srv.cfg + sudo echo "api_user: $ASA_API_USER" >> examples/Docker/data/acme_srv.cfg + sudo echo "api_password: $ASA_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg + sudo echo "api_key: $ASA_API_KEY" >> examples/Docker/data/acme_srv.cfg + sudo echo "ca_name: $ASA_CA_NAME" >> examples/Docker/data/acme_srv.cfg + sudo echo "ca_bundle: $ASA_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg + sudo echo "profile_name: $ASA_PROFILE2" >> examples/Docker/data/acme_srv.cfg + sudo sed -i "s/revocation_reason_check_disable: False/revocation_reason_check_disable: False\nenrollment_timeout:15/g" examples/Docker/data/acme_srv.cfg + cd examples/Docker/ + docker-compose restart + env: + ASA_API_HOST: ${{ secrets.ASA_API_HOST }} + ASA_API_USER: ${{ secrets.ASA_API_USER }} + ASA_API_PASSWORD: ${{ secrets.ASA_API_PASSWORD }} + ASA_API_KEY: ${{ secrets.ASA_API_KEY }} + ASA_CA_NAME: ${{ secrets.ASA_CA_NAME }} + ASA_CA_BUNDLE: ${{ secrets.ASA_CA_BUNDLE }} + ASA_PROFILE2: ${{ secrets.ASA_PROFILE2 }} + + - name: "${{ secrets.ASA_PROFILE2 }} - enrollment" + uses: ./.github/actions/wf_specific/asa_ca_handler/enroll_profile_2 + with: + PROFILE: ${{ secrets.ASA_PROFILE1 }} + + - name: "Header-info - Setup asa_ca_handler with headerinfo" + run: | + sudo cp .github/openssl_ca_handler.py_acme_srv_default_handler.cfg examples/Docker/data/acme_srv.cfg + sudo chmod 777 examples/Docker/data/acme_srv.cfg + sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem + sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg + sudo echo "handler_file: examples/ca_handler/asa_ca_handler.py" >> examples/Docker/data/acme_srv.cfg + sudo echo "api_host: $ASA_API_HOST" >> examples/Docker/data/acme_srv.cfg + sudo echo "api_user: $ASA_API_USER" >> examples/Docker/data/acme_srv.cfg + sudo echo "api_password: $ASA_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg + sudo echo "api_key: $ASA_API_KEY" >> examples/Docker/data/acme_srv.cfg + sudo echo "ca_name: $ASA_CA_NAME" >> examples/Docker/data/acme_srv.cfg + sudo echo "ca_bundle: $ASA_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg + sudo echo "profile_name: $ASA_PROFILE1" >> examples/Docker/data/acme_srv.cfg + sudo sed -i "s/revocation_reason_check_disable: False/revocation_reason_check_disable: False\nenrollment_timeout:15/g" examples/Docker/data/acme_srv.cfg + sudo sed -i "s/tnauthlist_support: False/tnauthlist_support: False\nheader_info_list: [\"HTTP_USER_AGENT\"]/g" examples/Docker/data/acme_srv.cfg + cd examples/Docker/ + docker-compose restart + env: + ASA_API_HOST: ${{ secrets.ASA_API_HOST }} + ASA_API_USER: ${{ secrets.ASA_API_USER }} + ASA_API_PASSWORD: ${{ secrets.ASA_API_PASSWORD }} + ASA_API_KEY: ${{ secrets.ASA_API_KEY }} + ASA_CA_NAME: ${{ secrets.ASA_CA_NAME }} + ASA_CA_BUNDLE: ${{ secrets.ASA_CA_BUNDLE }} + ASA_PROFILE1: ${{ secrets.ASA_PROFILE1 }} + + - name: "Hederinfo - enrollment" + uses: ./.github/actions/wf_specific/asa_ca_handler/enroll_headerinfo + with: + ASA_PROFILE1: ${{ secrets.ASA_PROFILE1 }} + ASA_PROFILE2: ${{ secrets.ASA_PROFILE2 }} + + - name: "EAB without headerinfo - Setup asa_ca_handler" + run: | + sudo cp .github/openssl_ca_handler.py_acme_srv_default_handler.cfg examples/Docker/data/acme_srv.cfg + sudo chmod 777 examples/Docker/data/acme_srv.cfg + sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem + sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg + sudo echo "handler_file: examples/ca_handler/asa_ca_handler.py" >> examples/Docker/data/acme_srv.cfg + sudo echo "api_host: $ASA_API_HOST" >> examples/Docker/data/acme_srv.cfg + sudo echo "api_user: $ASA_API_USER" >> examples/Docker/data/acme_srv.cfg + sudo echo "api_password: $ASA_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg + sudo echo "api_key: $ASA_API_KEY" >> examples/Docker/data/acme_srv.cfg + sudo echo "ca_name: $ASA_CA_NAME" >> examples/Docker/data/acme_srv.cfg + sudo echo "ca_bundle: $ASA_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg + sudo echo "profile_name: $ASA_PROFILE1" >> examples/Docker/data/acme_srv.cfg + sudo echo "eab_profiling: True" >> examples/Docker/data/acme_srv.cfg + sudo sed -i "s/revocation_reason_check_disable: False/revocation_reason_check_disable: False\nenrollment_timeout:15/g" examples/Docker/data/acme_srv.cfg + sudo echo -e "\n[EABhandler]" >> examples/Docker/data/acme_srv.cfg + sudo echo "eab_handler_file: /var/www/acme2certifier/examples/eab_handler/kid_profile_handler.py" >> examples/Docker/data/acme_srv.cfg + sudo echo "key_file: volume/kid_profiles.json" >> examples/Docker/data/acme_srv.cfg + + sudo cp examples/eab_handler/kid_profiles.json examples/Docker/data/kid_profiles.json + sudo chmod 777 examples/eab_handler/kid_profiles.json + sudo sed -i "s/\"profile_id\"\: \[\"profile_1\", \"profile_2\", \"profile_3\"\]/\"profile_name\"\: \[\"$ASA_PROFILE2\", \"$ASA_PROFILE1\"\]/g" examples/Docker/data/kid_profiles.json + sudo sed -i "s/\"profile_id\"\: \"profile_2\"/\"profile_name\"\: \"$ASA_PROFILE3\"/g" examples/Docker/data/kid_profiles.json + sudo sed -i "s/\"ca_name\": \"example_ca_2\",/\"ca_name\": \"$ASA_CA_NAME2\"/" examples/Docker/data/kid_profiles.json + sudo sed -i "s/\"ca_name\": \"example_ca\",/\"unknown_key\": \"unknown_value\"/g" examples/Docker/data/kid_profiles.json + sudo sed -i "s/example.net/acme/g" examples/Docker/data/kid_profiles.json + sudo sed -i '18,19d' examples/Docker/data/kid_profiles.json + sudo sed -i '8,9d' examples/Docker/data/kid_profiles.json + + cd examples/Docker/ + docker-compose restart + env: + ASA_API_HOST: ${{ secrets.ASA_API_HOST }} + ASA_API_USER: ${{ secrets.ASA_API_USER }} + ASA_API_PASSWORD: ${{ secrets.ASA_API_PASSWORD }} + ASA_API_KEY: ${{ secrets.ASA_API_KEY }} + ASA_CA_NAME: ${{ secrets.ASA_CA_NAME }} + ASA_CA_NAME2: ${{ secrets.ASA_CA_NAME2 }} + ASA_CA_BUNDLE: ${{ secrets.ASA_CA_BUNDLE }} + ASA_PROFILE1: ${{ secrets.ASA_PROFILE1 }} + ASA_PROFILE2: ${{ secrets.ASA_PROFILE2 }} + ASA_PROFILE3: ${{ secrets.ASA_PROFILE3 }} + + - name: "EAB without headerinfo - enrollment" + uses: ./.github/actions/wf_specific/asa_ca_handler/enroll_eab_wo_headerinfo + with: + ASA_CA_NAME1: ${{ secrets.ASA_CA_NAME }} + ASA_CA_NAME2: ${{ secrets.ASA_CA_NAME2 }} + + - name: "EAB with headerinfo - Setup asa_ca_handler" + run: | + sudo cp .github/openssl_ca_handler.py_acme_srv_default_handler.cfg examples/Docker/data/acme_srv.cfg + sudo chmod 777 examples/Docker/data/acme_srv.cfg + sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem + sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg + sudo echo "handler_file: examples/ca_handler/asa_ca_handler.py" >> examples/Docker/data/acme_srv.cfg + sudo echo "api_host: $ASA_API_HOST" >> examples/Docker/data/acme_srv.cfg + sudo echo "api_user: $ASA_API_USER" >> examples/Docker/data/acme_srv.cfg + sudo echo "api_password: $ASA_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg + sudo echo "api_key: $ASA_API_KEY" >> examples/Docker/data/acme_srv.cfg + sudo echo "ca_name: $ASA_CA_NAME" >> examples/Docker/data/acme_srv.cfg + sudo echo "ca_bundle: $ASA_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg + sudo echo "profile_name: $ASA_PROFILE1" >> examples/Docker/data/acme_srv.cfg + sudo echo "eab_profiling: True" >> examples/Docker/data/acme_srv.cfg + sudo sed -i "s/revocation_reason_check_disable: False/revocation_reason_check_disable: False\nenrollment_timeout:15/g" examples/Docker/data/acme_srv.cfg + sudo sed -i "s/tnauthlist_support: False/tnauthlist_support: False\nheader_info_list: [\"HTTP_USER_AGENT\"]/g" examples/Docker/data/acme_srv.cfg + sudo echo -e "\n[EABhandler]" >> examples/Docker/data/acme_srv.cfg + sudo echo "eab_handler_file: /var/www/acme2certifier/examples/eab_handler/kid_profile_handler.py" >> examples/Docker/data/acme_srv.cfg + sudo echo "key_file: volume/kid_profiles.json" >> examples/Docker/data/acme_srv.cfg + + sudo cp examples/eab_handler/kid_profiles.json examples/Docker/data/kid_profiles.json + sudo chmod 777 examples/eab_handler/kid_profiles.json + sudo sed -i "s/\"profile_id\"\: \[\"profile_1\", \"profile_2\", \"profile_3\"\]/\"profile_name\"\: \[\"$ASA_PROFILE2\", \"$ASA_PROFILE1\"\]/g" examples/Docker/data/kid_profiles.json + sudo sed -i "s/\"profile_id\"\: \"profile_2\"/\"profile_name\"\: \"$ASA_PROFILE3\"/g" examples/Docker/data/kid_profiles.json + sudo sed -i "s/\"ca_name\": \"example_ca_2\",/\"ca_name\": \"$ASA_CA_NAME2\"/" examples/Docker/data/kid_profiles.json + sudo sed -i "s/\"ca_name\": \"example_ca\",/\"unknown_key\": \"unknown_value\"/g" examples/Docker/data/kid_profiles.json + sudo sed -i "s/example.net/acme/g" examples/Docker/data/kid_profiles.json + sudo sed -i '18,19d' examples/Docker/data/kid_profiles.json + sudo sed -i '8,9d' examples/Docker/data/kid_profiles.json + + cd examples/Docker/ + docker-compose restart + env: + ASA_API_HOST: ${{ secrets.ASA_API_HOST }} + ASA_API_USER: ${{ secrets.ASA_API_USER }} + ASA_API_PASSWORD: ${{ secrets.ASA_API_PASSWORD }} + ASA_API_KEY: ${{ secrets.ASA_API_KEY }} + ASA_CA_NAME: ${{ secrets.ASA_CA_NAME }} + ASA_CA_NAME2: ${{ secrets.ASA_CA_NAME2 }} + ASA_CA_BUNDLE: ${{ secrets.ASA_CA_BUNDLE }} + ASA_PROFILE1: ${{ secrets.ASA_PROFILE1 }} + ASA_PROFILE2: ${{ secrets.ASA_PROFILE2 }} + ASA_PROFILE3: ${{ secrets.ASA_PROFILE3 }} + + - name: "EAB with headerinfo - enrollment" + uses: ./.github/actions/wf_specific/asa_ca_handler/enroll_eab_w_headerinfo + with: + ASA_CA_NAME1: ${{ secrets.ASA_CA_NAME }} + ASA_CA_NAME2: ${{ secrets.ASA_CA_NAME2 }} + + - name: "Check container configuration" + uses: ./.github/actions/container_check + with: + DB_HANDLER: ${{ matrix.dbhandler }} + WEB_SRV: ${{ matrix.websrv }} + + - name: "[ * ] collecting test logs" + if: ${{ failure() }} + run: | + mkdir -p ${{ github.workspace }}/artifact/upload + sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ + sudo cp -rp acme-sh/ ${{ github.workspace }}/artifact/acme-sh/ + sudo cp -rp certbot/ ${{ github.workspace }}/artifact/certbot/ + sudo cp -rp lego/ ${{ github.workspace }}/artifact/lego/ + cd examples/Docker + docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log + sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data acme-sh certbot lego + + - name: "[ * ] uploading artificates" + uses: actions/upload-artifact@v4 + if: ${{ failure() }} + with: + name: asa-${{ matrix.websrv }}-${{ matrix.dbhandler }}.tar.gz + path: ${{ github.workspace }}/artifact/upload/ + + asa_handler_tests_rpm: + name: "asa_handler_tests_rpm" + runs-on: ubuntu-latest + needs: asa_handler_headerinfo_tests + strategy: + fail-fast: false + max-parallel: 1 + matrix: + rhversion: [8, 9] + steps: + - name: "checkout GIT" + uses: actions/checkout@v4 + + - name: "Prepare Alma environment" + uses: ./.github/actions/rpm_prep + with: + GH_SBOM_USER: ${{ secrets.GH_SBOM_USER }} + GH_SBOM_TOKEN: ${{ secrets.GH_SBOM_TOKEN }} + RH_VERSION: ${{ matrix.rhversion }} + + - name: "Create letsencrypt and lego folder" + run: | + mkdir certbot + mkdir lego + mkdir acme-sh + + - name: "Profile ${{ secrets.ASA_PROFILE1 }} - Setup a2c with asa_ca_handler with profile ${{ secrets.ASA_PROFILE1 }}" + run: | + mkdir -p data/acme_ca + sudo cp test/ca/certsrv_ca_certs.pem data/acme_ca/ca_certs.pem + sudo touch data/acme_srv.cfg + sudo chmod 777 data/acme_srv.cfg + sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > data/acme_srv.cfg + sudo echo "handler_file: examples/ca_handler/asa_ca_handler.py" >> data/acme_srv.cfg + sudo echo "api_host: $ASA_API_HOST" >> data/acme_srv.cfg + sudo echo "api_user: $ASA_API_USER" >> data/acme_srv.cfg + sudo echo "api_password: $ASA_API_PASSWORD" >> data/acme_srv.cfg + sudo echo "api_key: $ASA_API_KEY" >> data/acme_srv.cfg + sudo echo "ca_name: $ASA_CA_NAME" >> data/acme_srv.cfg + sudo echo "ca_bundle: $ASA_CA_BUNDLE" >> data/acme_srv.cfg + sudo echo "profile_name: $ASA_PROFILE1" >> data/acme_srv.cfg + sudo sed -i "s/revocation_reason_check_disable: False/revocation_reason_check_disable: False\nenrollment_timeout:15/g" data/acme_srv.cfg + env: + ASA_API_HOST: ${{ secrets.ASA_API_HOST }} + ASA_API_USER: ${{ secrets.ASA_API_USER }} + ASA_API_PASSWORD: ${{ secrets.ASA_API_PASSWORD }} + ASA_API_KEY: ${{ secrets.ASA_API_KEY }} + ASA_CA_NAME: ${{ secrets.ASA_CA_NAME }} + ASA_CA_BUNDLE: ${{ secrets.ASA_CA_BUNDLE }} + ASA_PROFILE1: ${{ secrets.ASA_PROFILE1 }} + + - name: "Profile ${{ secrets.ASA_PROFILE1 }} - Execute install scipt" + run: | + docker exec acme-srv sh /tmp/acme2certifier/rpm_tester.sh + + - name: "${{ secrets.ASA_PROFILE1 }} - enrollment" + uses: ./.github/actions/wf_specific/asa_ca_handler/enroll_profile_1 + with: + PROFILE: ${{ secrets.ASA_PROFILE1 }} + + - name: "Profile ${{ secrets.ASA_PROFILE2 }} - Setup a2c with asa_ca_handler with profile ${{ secrets.ASA_PROFILE1 }}" + run: | + sudo touch data/acme_srv.cfg + sudo chmod 777 data/acme_srv.cfg + sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > data/acme_srv.cfg + sudo echo "handler_file: examples/ca_handler/asa_ca_handler.py" >> data/acme_srv.cfg + sudo echo "api_host: $ASA_API_HOST" >> data/acme_srv.cfg + sudo echo "api_user: $ASA_API_USER" >> data/acme_srv.cfg + sudo echo "api_password: $ASA_API_PASSWORD" >> data/acme_srv.cfg + sudo echo "api_key: $ASA_API_KEY" >> data/acme_srv.cfg + sudo echo "ca_name: $ASA_CA_NAME" >> data/acme_srv.cfg + sudo echo "ca_bundle: $ASA_CA_BUNDLE" >> data/acme_srv.cfg + sudo echo "profile_name: $ASA_PROFILE2" >> data/acme_srv.cfg + sudo sed -i "s/revocation_reason_check_disable: False/revocation_reason_check_disable: False\nenrollment_timeout:15/g" data/acme_srv.cfg + env: + ASA_API_HOST: ${{ secrets.ASA_API_HOST }} + ASA_API_USER: ${{ secrets.ASA_API_USER }} + ASA_API_PASSWORD: ${{ secrets.ASA_API_PASSWORD }} + ASA_API_KEY: ${{ secrets.ASA_API_KEY }} + ASA_CA_NAME: ${{ secrets.ASA_CA_NAME }} + ASA_CA_BUNDLE: ${{ secrets.ASA_CA_BUNDLE }} + ASA_PROFILE2: ${{ secrets.ASA_PROFILE2 }} + + - name: "Profile ${{ secrets.ASA_PROFILE2 }} - reconfigure a2c " + run: | + docker exec acme-srv sh /tmp/acme2certifier/rpm_tester.sh restart + + - name: "${{ secrets.ASA_PROFILE2 }} - enrollment" + uses: ./.github/actions/wf_specific/asa_ca_handler/enroll_profile_2 + with: + PROFILE: ${{ secrets.ASA_PROFILE1 }} + + - name: "Header-info - Setup asa_ca_handler with headerinfo" + run: | + sudo touch data/acme_srv.cfg + sudo chmod 777 data/acme_srv.cfg + sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > data/acme_srv.cfg + sudo echo "handler_file: examples/ca_handler/asa_ca_handler.py" >> data/acme_srv.cfg + sudo echo "api_host: $ASA_API_HOST" >> data/acme_srv.cfg + sudo echo "api_user: $ASA_API_USER" >> data/acme_srv.cfg + sudo echo "api_password: $ASA_API_PASSWORD" >> data/acme_srv.cfg + sudo echo "api_key: $ASA_API_KEY" >> data/acme_srv.cfg + sudo echo "ca_name: $ASA_CA_NAME" >> data/acme_srv.cfg + sudo echo "ca_bundle: $ASA_CA_BUNDLE" >> data/acme_srv.cfg + sudo echo "profile_name: $ASA_PROFILE1" >> data/acme_srv.cfg + sudo sed -i "s/revocation_reason_check_disable: False/revocation_reason_check_disable: False\nenrollment_timeout:15/g" data/acme_srv.cfg + sudo sed -i "s/tnauthlist_support: False/tnauthlist_support: False\nheader_info_list: [\"HTTP_USER_AGENT\"]/g" data/acme_srv.cfg + env: + ASA_API_HOST: ${{ secrets.ASA_API_HOST }} + ASA_API_USER: ${{ secrets.ASA_API_USER }} + ASA_API_PASSWORD: ${{ secrets.ASA_API_PASSWORD }} + ASA_API_KEY: ${{ secrets.ASA_API_KEY }} + ASA_CA_NAME: ${{ secrets.ASA_CA_NAME }} + ASA_CA_BUNDLE: ${{ secrets.ASA_CA_BUNDLE }} + ASA_PROFILE1: ${{ secrets.ASA_PROFILE1 }} + + - name: "Profile ${{ secrets.ASA_PROFILE2 }} - reconfigure a2c " + run: | + docker exec acme-srv sh /tmp/acme2certifier/rpm_tester.sh restart + + - name: "Hederinfo - enrollment" + uses: ./.github/actions/wf_specific/asa_ca_handler/enroll_headerinfo + with: + ASA_PROFILE1: ${{ secrets.ASA_PROFILE1 }} + ASA_PROFILE2: ${{ secrets.ASA_PROFILE2 }} + + - name: "EAB without headerinfo - Setup asa_ca_handler" + run: | + sudo touch data/acme_srv.cfg + sudo chmod 777 data/acme_srv.cfg + sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > data/acme_srv.cfg + sudo echo "handler_file: examples/ca_handler/asa_ca_handler.py" >> data/acme_srv.cfg + sudo echo "api_host: $ASA_API_HOST" >> data/acme_srv.cfg + sudo echo "api_user: $ASA_API_USER" >> data/acme_srv.cfg + sudo echo "api_password: $ASA_API_PASSWORD" >> data/acme_srv.cfg + sudo echo "api_key: $ASA_API_KEY" >> data/acme_srv.cfg + sudo echo "ca_name: $ASA_CA_NAME" >> data/acme_srv.cfg + sudo echo "ca_bundle: $ASA_CA_BUNDLE" >> data/acme_srv.cfg + sudo echo "profile_name: $ASA_PROFILE1" >> data/acme_srv.cfg + sudo echo "eab_profiling: True" >> data/acme_srv.cfg + sudo sed -i "s/revocation_reason_check_disable: False/revocation_reason_check_disable: False\nenrollment_timeout:15/g" data/acme_srv.cfg + sudo echo -e "\n\n[EABhandler]" >> data/acme_srv.cfg + sudo echo "eab_handler_file: /opt/acme2certifier/examples/eab_handler/kid_profile_handler.py" >> data/acme_srv.cfg + sudo echo "key_file: /opt/acme2certifier/volume/acme_ca/kid_profiles.json" >> data/acme_srv.cfg + + sudo cp examples/eab_handler/kid_profiles.json data/acme_ca/kid_profiles.json + sudo chmod 777 data/acme_ca/kid_profiles.json + sudo sed -i "s/\"profile_id\"\: \[\"profile_1\", \"profile_2\", \"profile_3\"\]/\"profile_name\"\: \[\"$ASA_PROFILE2\", \"$ASA_PROFILE1\"\]/g" data/acme_ca/kid_profiles.json + sudo sed -i "s/\"profile_id\"\: \"profile_2\"/\"profile_name\"\: \"$ASA_PROFILE3\"/g" data/acme_ca/kid_profiles.json + sudo sed -i "s/\"ca_name\": \"example_ca_2\",/\"ca_name\": \"$ASA_CA_NAME2\"/" data/acme_ca/kid_profiles.json + sudo sed -i "s/\"ca_name\": \"example_ca\",/\"unknown_key\": \"unknown_value\"/g" data/acme_ca/kid_profiles.json + sudo sed -i "s/example.net/acme/g" data/acme_ca/kid_profiles.json + sudo sed -i '18,19d' data/acme_ca/kid_profiles.json + sudo sed -i '8,9d' data/acme_ca/kid_profiles.json + env: + ASA_API_HOST: ${{ secrets.ASA_API_HOST }} + ASA_API_USER: ${{ secrets.ASA_API_USER }} + ASA_API_PASSWORD: ${{ secrets.ASA_API_PASSWORD }} + ASA_API_KEY: ${{ secrets.ASA_API_KEY }} + ASA_CA_NAME: ${{ secrets.ASA_CA_NAME }} + ASA_CA_NAME2: ${{ secrets.ASA_CA_NAME2 }} + ASA_CA_BUNDLE: ${{ secrets.ASA_CA_BUNDLE }} + ASA_PROFILE1: ${{ secrets.ASA_PROFILE1 }} + ASA_PROFILE2: ${{ secrets.ASA_PROFILE2 }} + ASA_PROFILE3: ${{ secrets.ASA_PROFILE3 }} + + - name: "EAB without headerinfo - Reconfigure a2c " + run: | + docker exec acme-srv sh /tmp/acme2certifier/rpm_tester.sh restart + + - name: "EAB without headerinfo - enrollment" + uses: ./.github/actions/wf_specific/asa_ca_handler/enroll_eab_wo_headerinfo + with: + ASA_CA_NAME1: ${{ secrets.ASA_CA_NAME }} + ASA_CA_NAME2: ${{ secrets.ASA_CA_NAME2 }} + + - name: "EAB with headerinfo - Setup asa_ca_handler" + run: | + sudo touch data/acme_srv.cfg + sudo chmod 777 data/acme_srv.cfg + sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > data/acme_srv.cfg + sudo echo "handler_file: examples/ca_handler/asa_ca_handler.py" >> data/acme_srv.cfg + sudo echo "api_host: $ASA_API_HOST" >> data/acme_srv.cfg + sudo echo "api_user: $ASA_API_USER" >> data/acme_srv.cfg + sudo echo "api_password: $ASA_API_PASSWORD" >> data/acme_srv.cfg + sudo echo "api_key: $ASA_API_KEY" >> data/acme_srv.cfg + sudo echo "ca_name: $ASA_CA_NAME" >> data/acme_srv.cfg + sudo echo "ca_bundle: $ASA_CA_BUNDLE" >> data/acme_srv.cfg + sudo echo "profile_name: $ASA_PROFILE1" >> data/acme_srv.cfg + sudo echo "eab_profiling: True" >> data/acme_srv.cfg + sudo sed -i "s/revocation_reason_check_disable: False/revocation_reason_check_disable: False\nenrollment_timeout:15/g" data/acme_srv.cfg + sudo sed -i "s/tnauthlist_support: False/tnauthlist_support: False\nheader_info_list: [\"HTTP_USER_AGENT\"]/g" data/acme_srv.cfg + sudo echo -e "\n\n[EABhandler]" >> data/acme_srv.cfg + sudo echo "eab_handler_file: /opt/acme2certifier/examples/eab_handler/kid_profile_handler.py" >> data/acme_srv.cfg + sudo echo "key_file: /opt/acme2certifier/volume/acme_ca/kid_profiles.json" >> data/acme_srv.cfg + + sudo cp examples/eab_handler/kid_profiles.json data/acme_ca/kid_profiles.json + sudo chmod 777 data/acme_ca/kid_profiles.json + sudo sed -i "s/\"profile_id\"\: \[\"profile_1\", \"profile_2\", \"profile_3\"\]/\"profile_name\"\: \[\"$ASA_PROFILE2\", \"$ASA_PROFILE1\"\]/g" data/acme_ca/kid_profiles.json + sudo sed -i "s/\"profile_id\"\: \"profile_2\"/\"profile_name\"\: \"$ASA_PROFILE3\"/g" data/acme_ca/kid_profiles.json + sudo sed -i "s/\"ca_name\": \"example_ca_2\",/\"ca_name\": \"$ASA_CA_NAME2\"/" data/acme_ca/kid_profiles.json + sudo sed -i "s/\"ca_name\": \"example_ca\",/\"unknown_key\": \"unknown_value\"/g" data/acme_ca/kid_profiles.json + sudo sed -i "s/example.net/acme/g" data/acme_ca/kid_profiles.json + sudo sed -i '18,19d' data/acme_ca/kid_profiles.json + sudo sed -i '8,9d' data/acme_ca/kid_profiles.json + env: + ASA_API_HOST: ${{ secrets.ASA_API_HOST }} + ASA_API_USER: ${{ secrets.ASA_API_USER }} + ASA_API_PASSWORD: ${{ secrets.ASA_API_PASSWORD }} + ASA_API_KEY: ${{ secrets.ASA_API_KEY }} + ASA_CA_NAME: ${{ secrets.ASA_CA_NAME }} + ASA_CA_NAME2: ${{ secrets.ASA_CA_NAME2 }} + ASA_CA_BUNDLE: ${{ secrets.ASA_CA_BUNDLE }} + ASA_PROFILE1: ${{ secrets.ASA_PROFILE1 }} + ASA_PROFILE2: ${{ secrets.ASA_PROFILE2 }} + ASA_PROFILE3: ${{ secrets.ASA_PROFILE3 }} + + - name: "EAB with headerinfo - Reconfigure a2c " + run: | + docker exec acme-srv sh /tmp/acme2certifier/rpm_tester.sh restart + + - name: "EAB with headerinfo - enrollment" + uses: ./.github/actions/wf_specific/asa_ca_handler/enroll_eab_w_headerinfo + with: + ASA_CA_NAME1: ${{ secrets.ASA_CA_NAME }} + ASA_CA_NAME2: ${{ secrets.ASA_CA_NAME2 }} + + - name: "[ * ] collecting test logs" + if: ${{ failure() }} + run: | + mkdir -p ${{ github.workspace }}/artifact/upload + docker exec acme-srv tar cvfz /tmp/acme2certifier/a2c.tgz /opt/acme2certifier + sudo cp -rp data/ ${{ github.workspace }}/artifact/data/ + sudo rm ${{ github.workspace }}/artifact/data/*.rpm + sudo cp -rp acme-sh/ ${{ github.workspace }}/artifact/acme-sh/ + docker exec acme-srv cat /etc/nginx/nginx.conf.orig > ${{ github.workspace }}/artifact/data/nginx.conf.orig + docker exec acme-srv cat /etc/nginx/nginx.conf > ${{ github.workspace }}/artifact/data/nginx.conf + docker exec acme-srv cat /var/log/messages > ${{ github.workspace }}/artifact/acme-srv.log + sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz data acme-srv.log acme-sh + + - name: "[ * ] uploading artificates" + uses: actions/upload-artifact@v4 + if: ${{ failure() }} + with: + name: asa_handler_tests_rpm-rh${{ matrix.rhversion }}.tar.gz + path: ${{ github.workspace }}/artifact/upload/ + diff --git a/.github/workflows/ca_handler_tests_certifier.yml b/.github/workflows/ca_handler_tests_certifier.yml index 528bd812..2079bf06 100644 --- a/.github/workflows/ca_handler_tests_certifier.yml +++ b/.github/workflows/ca_handler_tests_certifier.yml @@ -12,41 +12,50 @@ jobs: certifier_handler_tests: name: "certifier_handler_tests" runs-on: ubuntu-latest + strategy: + max-parallel: 2 + fail-fast: false + matrix: + websrv: ['apache2', 'nginx'] + dbhandler: ['wsgi', 'django'] steps: - name: "checkout GIT" - uses: actions/checkout@v3 + uses: actions/checkout@v4 - - name: "[ PREPARE ] Build docker-compose (apache2_wsgi)" - working-directory: examples/Docker/ - run: | - sudo mkdir -p data - docker network create acme - docker-compose up -d - docker-compose logs - - - name: "[ PREPARE ] create letsencrypt and lego folder" - run: | - mkdir certbot - mkdir lego + - name: "Build container" + uses: ./.github/actions/container_prep + with: + DB_HANDLER: ${{ matrix.dbhandler }} + WEB_SRV: ${{ matrix.websrv }} - - name: "Test http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory + - name: "Setup tunnel" + uses: ./.github/actions/wf_specific/certifier_ca_handler/tunnel_setup + with: + WCCE_SSH_USER: ${{ secrets.WCCE_SSH_USER }} + WCCE_SSH_HOST: ${{ secrets.WCCE_SSH_HOST }} + WCCE_SSH_PORT: ${{ secrets.WCCE_SSH_PORT }} + NCM_API_HOST: ${{ secrets.NCM_API_HOST }} + WCCE_SSH_KNOWN_HOSTS: ${{ secrets.WCCE_SSH_KNOWN_HOSTS }} + WCCE_SSH_ACCESS_KEY: ${{ secrets.WCCE_SSH_ACCESS_KEY }} + NCM_API_USER: ${{ secrets.NCM_API_USER }} + NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" + - name: "No profile - Setup a2c with certifier_ca_handler" run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg + sudo cp .github/openssl_ca_handler.py_acme_srv_default_handler.cfg examples/Docker/data/acme_srv.cfg sudo chmod 777 examples/Docker/data/acme_srv.cfg + sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg + # sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg + sudo echo "api_host: https://forwarder.acme:8084" >> examples/Docker/data/acme_srv.cfg + sudo echo "ca_bundle: False" >> examples/Docker/data/acme_srv.cfg sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg + # sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg cd examples/Docker/ docker-compose restart - docker-compose logs env: NCM_API_HOST: ${{ secrets.NCM_API_HOST }} NCM_API_USER: ${{ secrets.NCM_API_USER }} @@ -54,211 +63,152 @@ jobs: NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - name: "Test http://acme-srv/directory is accessable again" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - sudo mkdir acme-sh - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ ENROLL ] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --alpn --standalone --debug 3 --output-insecure --force - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - - name: "revoke via acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --revoke -d acme-sh.acme --standalone --debug 3 --output-insecure + - name: "No profile - Enrollmnet" + uses: ./.github/actions/wf_specific/certifier_ca_handler/enroll_no_profile - - name: "[ REGISTER ] certbot" + - name: "Profile 101 - Setup a2c with certifier_ca_handler with profile 101" run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email - - - name: "[ ENROLL ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem - - - name: "revoke HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot revoke --delete-after-revoke --server http://acme-srv -d certbot.acme --cert-name certbot - - - name: "[ ENROLL ] lego" - run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --http run - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt - - - name: "revoke HTTP-01 single domain lego" - run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme revoke - - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp acme-sh/ ${{ github.workspace }}/artifact/acme-sh/ - sudo cp -rp certbot/ ${{ github.workspace }}/artifact/certbot/ - sudo cp -rp lego/ ${{ github.workspace }}/artifact/lego/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data acme-sh certbot lego - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: ncm.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - - certifier_p101_handler_tests: - name: "certifier_p101_handler_tests" - runs-on: ubuntu-latest - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "[ PREPARE ] Build docker-compose (apache2_wsgi)" - working-directory: examples/Docker/ - run: | - sudo mkdir -p data - docker network create acme - docker-compose up -d - docker-compose logs - - - name: "[ PREPARE ] create letsencrypt and lego folder" - run: | - mkdir certbot - mkdir lego - - - name: "Test http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg + # sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg + sudo echo "api_host: https://forwarder.acme:8084" >> examples/Docker/data/acme_srv.cfg + sudo echo "ca_bundle: False" >> examples/Docker/data/acme_srv.cfg sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg + # sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg sudo echo "profile_id: 101" >> examples/Docker/data/acme_srv.cfg cd examples/Docker/ docker-compose restart - docker-compose logs env: NCM_API_HOST: ${{ secrets.NCM_API_HOST }} NCM_API_USER: ${{ secrets.NCM_API_USER }} NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} + PROFILE: ${{ secrets.PROFILE }} - - name: "Test http://acme-srv/directory is accessable again" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - sudo mkdir acme-sh - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ ENROLL ] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --alpn --standalone --debug 3 --output-insecure --force - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - - name: "revoke via acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --revoke -d acme-sh.acme --standalone --debug 3 --output-insecure - - - name: "[ REGISTER ] certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email + - name: "Profile 101 - Enrollmnet" + uses: ./.github/actions/wf_specific/certifier_ca_handler/enroll_101_profile - - name: "[ ENROLL ] HTTP-01 single domain certbot" + - name: "Profile 102 - Setup a2c with certifier_ca_handler with Profile 102" run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem - sudo openssl x509 -in certbot/live/certbot/cert.pem -ext extendedKeyUsage -noout | grep -i "TLS Web Client" - - - name: "revoke HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot revoke --delete-after-revoke --server http://acme-srv -d certbot.acme --cert-name certbot - - - name: "[ ENROLL ] lego" - run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --http run - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt - sudo openssl x509 -in lego/certificates/lego.acme.crt -ext extendedKeyUsage -noout | grep -i "TLS Web Client" + sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg + sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg + # sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg + sudo echo "api_host: https://forwarder.acme:8084" >> examples/Docker/data/acme_srv.cfg + sudo echo "ca_bundle: False" >> examples/Docker/data/acme_srv.cfg + sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg + sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg + sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg + # sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg + sudo echo "profile_id: 102" >> examples/Docker/data/acme_srv.cfg + cd examples/Docker/ + docker-compose restart + env: + NCM_API_HOST: ${{ secrets.NCM_API_HOST }} + NCM_API_USER: ${{ secrets.NCM_API_USER }} + NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} + NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} + NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - name: "revoke HTTP-01 single domain lego" - run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme revoke + - name: "Profile 102 - Enrollmnet" + uses: ./.github/actions/wf_specific/certifier_ca_handler/enroll_102_profile - - name: "[ * ] collecting test logs" - if: ${{ failure() }} + - name: "Header-info - Setup a2c with certifier_ca_handler with header-info" run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp acme-sh/ ${{ github.workspace }}/artifact/acme-sh/ - sudo cp -rp certbot/ ${{ github.workspace }}/artifact/certbot/ - sudo cp -rp lego/ ${{ github.workspace }}/artifact/lego/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data acme-sh certbot lego - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: certifier_p101_handler_tests.tar.gz - path: ${{ github.workspace }}/artifact/upload/ + sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg + sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg + # sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg + sudo echo "api_host: https://forwarder.acme:8084" >> examples/Docker/data/acme_srv.cfg + sudo echo "ca_bundle: False" >> examples/Docker/data/acme_srv.cfg + sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg + sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg + sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg + # sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg + sudo sed -i "s/tnauthlist_support: False/tnauthlist_support: False\nheader_info_list: [\"HTTP_USER_AGENT\"]/g" examples/Docker/data/acme_srv.cfg + cd examples/Docker/ + docker-compose restart + env: + NCM_API_HOST: ${{ secrets.NCM_API_HOST }} + NCM_API_USER: ${{ secrets.NCM_API_USER }} + NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} + NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} + NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - certifier_p102_handler_tests: - name: "certifier_p102_handler_tests" - runs-on: ubuntu-latest - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 + - name: "Header-info - Enrollmnet" + uses: ./.github/actions/wf_specific/certifier_ca_handler/enroll_headerinfo - - name: "[ PREPARE ] Build docker-compose (apache2_wsgi)" - working-directory: examples/Docker/ + - name: "EAB without headerinfo - Setup a2c with certifier_ca_handler" run: | - sudo mkdir -p data - docker network create acme - docker-compose up -d - docker-compose logs + sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg + sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg + # sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg + sudo echo "api_host: https://forwarder.acme:8084" >> examples/Docker/data/acme_srv.cfg + sudo echo "ca_bundle: False" >> examples/Docker/data/acme_srv.cfg + sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg + sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg + sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg + # sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg + sudo echo "profile_id: 100" >> examples/Docker/data/acme_srv.cfg + sudo echo "eab_profiling: True" >> examples/Docker/data/acme_srv.cfg + sudo echo -e "\n[EABhandler]" >> examples/Docker/data/acme_srv.cfg + sudo echo "eab_handler_file: /var/www/acme2certifier/examples/eab_handler/kid_profile_handler.py" >> examples/Docker/data/acme_srv.cfg + sudo echo "key_file: volume/kid_profiles.json" >> examples/Docker/data/acme_srv.cfg + + sudo cp examples/eab_handler/kid_profiles.json examples/Docker/data/kid_profiles.json + sudo chmod 777 examples/eab_handler/kid_profiles.json + sudo sed -i "s/\"profile_id\"\: \[\"profile_1\", \"profile_2\", \"profile_3\"\]/\"profile_id\"\: \[\"102\", \"101\"\, \"100\"]/g" examples/Docker/data/kid_profiles.json + sudo sed -i "s/\"profile_id\"\: \"profile_2\"/\"profile_id\"\: \"102\"/g" examples/Docker/data/kid_profiles.json + sudo sed -i "s/\"ca_name\": \"example_ca_2\",/\"ca_name\": \"SubCA2\"/" examples/Docker/data/kid_profiles.json + sudo sed -i "s/\"ca_name\": \"example_ca\",/\"unknown_key\": \"unknown_value\"/g" examples/Docker/data/kid_profiles.json + sudo sed -i "s/example.net/acme/g" examples/Docker/data/kid_profiles.json + sudo sed -i '18,19d' examples/Docker/data/kid_profiles.json + sudo sed -i '8,9d' examples/Docker/data/kid_profiles.json - - name: "[ PREPARE ] create letsencrypt and lego folder" - run: | - mkdir certbot - mkdir lego + cd examples/Docker/ + docker-compose restart + env: + NCM_API_HOST: ${{ secrets.NCM_API_HOST }} + NCM_API_USER: ${{ secrets.NCM_API_USER }} + NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} + NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} + NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - name: "Test http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory + - name: "EAB without headerinfo - Enrollment" + uses: ./.github/actions/wf_specific/certifier_ca_handler/enroll_eab_wo_headerinfo - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" + - name: "EAB with headerinfo - Setup a2c with certifier_ca_handler" run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem sudo touch examples/Docker/data/acme_srv.cfg sudo chmod 777 examples/Docker/data/acme_srv.cfg sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg + # sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg + sudo echo "api_host: https://forwarder.acme:8084" >> examples/Docker/data/acme_srv.cfg + sudo echo "ca_bundle: False" >> examples/Docker/data/acme_srv.cfg sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - sudo echo "profile_id: 102" >> examples/Docker/data/acme_srv.cfg + # sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg + sudo echo "profile_id: 100" >> examples/Docker/data/acme_srv.cfg + sudo echo "eab_profiling: True" >> examples/Docker/data/acme_srv.cfg + sudo sed -i "s/tnauthlist_support: False/tnauthlist_support: False\nheader_info_list: [\"HTTP_USER_AGENT\"]/g" examples/Docker/data/acme_srv.cfg + sudo echo -e "\n[EABhandler]" >> examples/Docker/data/acme_srv.cfg + sudo echo "eab_handler_file: /var/www/acme2certifier/examples/eab_handler/kid_profile_handler.py" >> examples/Docker/data/acme_srv.cfg + sudo echo "key_file: volume/kid_profiles.json" >> examples/Docker/data/acme_srv.cfg + + sudo cp examples/eab_handler/kid_profiles.json examples/Docker/data/kid_profiles.json + sudo chmod 777 examples/eab_handler/kid_profiles.json + sudo sed -i "s/\"profile_id\"\: \[\"profile_1\", \"profile_2\", \"profile_3\"\]/\"profile_id\"\: \[\"102\", \"101\"\, \"100\"]/g" examples/Docker/data/kid_profiles.json + sudo sed -i "s/\"profile_id\"\: \"profile_2\"/\"profile_id\"\: \"102\"/g" examples/Docker/data/kid_profiles.json + sudo sed -i "s/\"ca_name\": \"example_ca_2\",/\"ca_name\": \"SubCA2\"/" examples/Docker/data/kid_profiles.json + sudo sed -i "s/\"ca_name\": \"example_ca\",/\"unknown_key\": \"unknown_value\"/g" examples/Docker/data/kid_profiles.json + sudo sed -i "s/example.net/acme/g" examples/Docker/data/kid_profiles.json + sudo sed -i '18,19d' examples/Docker/data/kid_profiles.json + sudo sed -i '8,9d' examples/Docker/data/kid_profiles.json cd examples/Docker/ docker-compose restart - docker-compose logs env: NCM_API_HOST: ${{ secrets.NCM_API_HOST }} NCM_API_USER: ${{ secrets.NCM_API_USER }} @@ -266,47 +216,40 @@ jobs: NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - name: "Test http://acme-srv/directory is accessable again" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - sudo mkdir acme-sh - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ ENROLL ] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --alpn --standalone --debug 3 --output-insecure --force - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - - name: "revoke via acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --revoke -d acme-sh.acme --standalone --debug 3 --output-insecure + - name: "EAB with headerinfo - Enrollment" + uses: ./.github/actions/wf_specific/certifier_ca_handler/enroll_eab_w_headerinfo - - name: "[ REGISTER ] certbot" + - name: "EAB with headerinfo - Reconfigure key_file without restarting" run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email + sudo sed -i "s/\"allowed_domainlist\": \[\"www.example.com\", \"www.example.org\"\]/\"allowed_domainlist\": \[\"www.example.com\", \"www.example.org\", \"*.acme\"\]/g" examples/Docker/data/kid_profiles.json + sudo sed -i '26,27d' examples/Docker/data/kid_profiles.json + sudo sed -i "s/ \"hmac\": \"YW5kX2ZpbmFsbHlfdGhlX2xhc3RfaG1hY19rZXlfd2hpY2hfaXNfbG9uZ2VyX3RoYW5fMjU2X2JpdHNfYW5kX3Nob3VsZF93b3Jr\"/ \"hmac\": \"YW5kX2ZpbmFsbHlfdGhlX2xhc3RfaG1hY19rZXlfd2hpY2hfaXNfbG9uZ2VyX3RoYW5fMjU2X2JpdHNfYW5kX3Nob3VsZF93b3Jr\"\n },\n \"keyid_04\": {\n \"hmac\": \"YW5kX2hlcmVfaXNfYW5vdGhlcl92ZXJ5X2xvbmdfbWFja19obWFjX2tleV90b19jaGVja19pZl9jaGFuZ2VzX2FmZmVjdF9pbW1lZGF0ZWx5\",\n \"cahandler\": {}\n }\n}/g" examples/Docker/data/kid_profiles.json - - name: "[ ENROLL ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem - sudo openssl x509 -in certbot/live/certbot/cert.pem -ext extendedKeyUsage -noout | grep -i "TLS Web Server" + - name: "EAB with headerinfo - Enrollment after reconfiguration" + uses: ./.github/actions/wf_specific/certifier_ca_handler/enroll_eab_w_headerinfo + with: + RECONFIGURE: true - - name: "revoke HTTP-01 single domain certbot" + - name: "kid-file in yaml format - Reconfiguration" run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot revoke --delete-after-revoke --server http://acme-srv -d certbot.acme --cert-name certbot + sudo sed -i "s/kid_profiles.json/kid_profiles.yml/g" examples/Docker/data/acme_srv.cfg + sudo pip3 install yq + sudo pip3 install jq + sudo sh -c "cat examples/Docker/data/kid_profiles.json | yq -y '.' > examples/Docker/data/kid_profiles.yml" + sudo rm examples/Docker/data/kid_profiles.json + sudo sed -i '33,34d' examples/Docker/data/kid_profiles.yml + # sudo cat examples/Docker/data/kid_profiles.yml - - name: "[ ENROLL ] lego" - run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --http run - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt - sudo openssl x509 -in lego/certificates/lego.acme.crt -ext extendedKeyUsage -noout | grep -i "TLS Web Server" + - name: "kid-file in yaml format - Enrollment after reconfiguration" + uses: ./.github/actions/wf_specific/certifier_ca_handler/enroll_eab_w_headerinfo + with: + RECONFIGURE: true - - name: "revoke HTTP-01 single domain lego" - run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme revoke + - name: "Check container configuration" + uses: ./.github/actions/container_check + with: + DB_HANDLER: ${{ matrix.dbhandler }} + WEB_SRV: ${{ matrix.websrv }} - name: "[ * ] collecting test logs" if: ${{ failure() }} @@ -321,52 +264,45 @@ jobs: sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data acme-sh certbot lego - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: ${{ failure() }} with: - name: certifier_p102_handler_tests.tar.gz + name: ncm-${{ matrix.websrv }}-${{ matrix.dbhandler }}.tar.gz path: ${{ github.workspace }}/artifact/upload/ certifier_handler_tests_rpm: name: "certifier_handler_tests_rpm" runs-on: ubuntu-latest + # needs: certifier_handler_tests + strategy: + fail-fast: false + max-parallel: 1 + matrix: + rhversion: [8, 9] steps: - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: Retrieve Version from version.py - run: | - echo TAG_NAME=$(cat acme_srv/version.py | grep -i __version__ | head -n 1 | sed 's/__version__ = //g' | sed s/\'//g) >> $GITHUB_ENV - - run: echo "Latest tag is ${{ env.TAG_NAME }}" + uses: actions/checkout@v4 - - name: update version number in spec file - run: | - # sudo sed -i "s/Source0:.*/Source0: %{name}-%{version}.tar.gz/g" examples/install_scripts/rpm/acme2certifier.spec - sudo sed -i "s/__version__/${{ env.TAG_NAME }}/g" examples/install_scripts/rpm/acme2certifier.spec - cat examples/install_scripts/rpm/acme2certifier.spec - - - name: build RPM package - id: rpm - uses: grindsa/rpmbuild@alma9 + - name: "Prepare Alma environment" + uses: ./.github/actions/rpm_prep with: - spec_file: "examples/install_scripts/rpm/acme2certifier.spec" - - - run: echo "path is ${{ steps.rpm.outputs.rpm_dir_path }}" - - - name: "[ PREPARE ] setup environment for alma installation" - run: | - docker network create acme - sudo mkdir -p data - sudo chmod -R 777 data - sudo cp ${{ steps.rpm.outputs.rpm_dir_path }}noarch/acme2certifier-${{ env.TAG_NAME }}-1.0.noarch.rpm data - sudo cp examples/Docker/almalinux-systemd/rpm_tester.sh data + GH_SBOM_USER: ${{ secrets.GH_SBOM_USER }} + GH_SBOM_TOKEN: ${{ secrets.GH_SBOM_TOKEN }} + RH_VERSION: ${{ matrix.rhversion }} - - name: "[ PREPARE ] create letsencrypt and lego folder" - run: | - mkdir certbot - mkdir lego + - name: "Setup tunnel" + uses: ./.github/actions/wf_specific/certifier_ca_handler/tunnel_setup + with: + WCCE_SSH_USER: ${{ secrets.WCCE_SSH_USER }} + WCCE_SSH_HOST: ${{ secrets.WCCE_SSH_HOST }} + WCCE_SSH_PORT: ${{ secrets.WCCE_SSH_PORT }} + NCM_API_HOST: ${{ secrets.NCM_API_HOST }} + WCCE_SSH_KNOWN_HOSTS: ${{ secrets.WCCE_SSH_KNOWN_HOSTS }} + WCCE_SSH_ACCESS_KEY: ${{ secrets.WCCE_SSH_ACCESS_KEY }} + NCM_API_USER: ${{ secrets.NCM_API_USER }} + NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - - name: "[ PREPARE ] prepare acme_srv.cfg with certifier_ca_handler" + - name: "No profile - Setup a2c with certifier_ca_handler" run: | mkdir -p data/acme_ca sudo cp test/ca/certsrv_ca_certs.pem data/acme_ca/ca_certs.pem @@ -374,11 +310,13 @@ jobs: sudo chmod 777 data/acme_srv.cfg sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > data/acme_srv.cfg sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> data/acme_srv.cfg + # sudo echo "api_host: $NCM_API_HOST" >> data/acme_srv.cfg + sudo echo "api_host: https://forwarder.acme:8084" >> data/acme_srv.cfg + sudo echo "ca_bundle: False" >> data/acme_srv.cfg sudo echo "api_user: $NCM_API_USER" >> data/acme_srv.cfg sudo echo "api_password: $NCM_API_PASSWORD" >> data/acme_srv.cfg sudo echo "ca_name: $NCM_CA_NAME" >> data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> data/acme_srv.cfg + # sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> data/acme_srv.cfg env: NCM_API_HOST: ${{ secrets.NCM_API_HOST }} NCM_API_USER: ${{ secrets.NCM_API_USER }} @@ -386,172 +324,227 @@ jobs: NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - name: "[ PREPARE ] Almalinux instance" - run: | - cat examples/Docker/almalinux-systemd/Dockerfile | docker build -t almalinux-systemd -f - . --no-cache - docker run -d -id --privileged --network acme --name=acme-srv -v "$(pwd)/data":/tmp/acme2certifier almalinux-systemd - - - name: "[ RUN ] Execute install scipt" + - name: "Execute install scipt" run: | docker exec acme-srv sh /tmp/acme2certifier/rpm_tester.sh - - name: "Test http://acme-srv/directory is accessible" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - sudo mkdir acme-sh - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ REGISTER] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --debug 3 + - name: "No profile - Enrollmnet" + uses: ./.github/actions/wf_specific/certifier_ca_handler/enroll_no_profile - - name: "[ ENROLL] acme.sh" + - name: "Profile 101 - Setup a2c with certifier_ca_handler with profile 101" run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --issue -d acme-sh.acme --standalone --debug 3 --output-insecure - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer + sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > data/acme_srv.cfg + sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> data/acme_srv.cfg + # sudo echo "api_host: $NCM_API_HOST" >> data/acme_srv.cfg + sudo echo "api_host: https://forwarder.acme:8084" >> data/acme_srv.cfg + sudo echo "ca_bundle: False" >> data/acme_srv.cfg + sudo echo "api_user: $NCM_API_USER" >> data/acme_srv.cfg + sudo echo "api_password: $NCM_API_PASSWORD" >> data/acme_srv.cfg + sudo echo "ca_name: $NCM_CA_NAME" >> data/acme_srv.cfg + # sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> data/acme_srv.cfg + sudo echo "profile_id: 101" >> data/acme_srv.cfg + env: + NCM_API_HOST: ${{ secrets.NCM_API_HOST }} + NCM_API_USER: ${{ secrets.NCM_API_USER }} + NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} + NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} + NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} + PROFILE: ${{ secrets.PROFILE }} - - name: "revoke via acme.sh" + - name: "Profile 101 - Reconfigure a2c " run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --revoke -d acme-sh.acme --standalone --debug 3 --output-insecure + docker exec acme-srv sh /tmp/acme2certifier/rpm_tester.sh restart - - name: "[ REGISTER ] certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email + - name: "Profile 101 - Enrollmnet" + uses: ./.github/actions/wf_specific/certifier_ca_handler/enroll_101_profile - - name: "[ ENROLL ] HTTP-01 single domain certbot" + - name: "Profile 102 - Setup a2c with certifier_ca_handler with profile 101" run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem + sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > data/acme_srv.cfg + sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> data/acme_srv.cfg + # sudo echo "api_host: $NCM_API_HOST" >> data/acme_srv.cfg + sudo echo "api_host: https://forwarder.acme:8084" >> data/acme_srv.cfg + sudo echo "ca_bundle: False" >> data/acme_srv.cfg + sudo echo "api_user: $NCM_API_USER" >> data/acme_srv.cfg + sudo echo "api_password: $NCM_API_PASSWORD" >> data/acme_srv.cfg + sudo echo "ca_name: $NCM_CA_NAME" >> data/acme_srv.cfg + # sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> data/acme_srv.cfg + sudo echo "profile_id: 102" >> data/acme_srv.cfg + env: + NCM_API_HOST: ${{ secrets.NCM_API_HOST }} + NCM_API_USER: ${{ secrets.NCM_API_USER }} + NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} + NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} + NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} + PROFILE: ${{ secrets.PROFILE }} - - name: "revoke HTTP-01 single domain certbot" + - name: "Profile 102 - Reconfigure a2c " run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot revoke --delete-after-revoke --server http://acme-srv -d certbot.acme --cert-name certbot + docker exec acme-srv sh /tmp/acme2certifier/rpm_tester.sh restart - - name: "[ ENROLL ] lego" - run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --http run - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + - name: "Profile 102 - Enrollmnet" + uses: ./.github/actions/wf_specific/certifier_ca_handler/enroll_102_profile - - name: "revoke HTTP-01 single domain lego" + - name: "Header-info - Setup a2c with certifier_ca_handler" run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme revoke + sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > data/acme_srv.cfg + sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> data/acme_srv.cfg + # sudo echo "api_host: $NCM_API_HOST" >> data/acme_srv.cfg + sudo echo "api_host: https://forwarder.acme:8084" >> data/acme_srv.cfg + sudo echo "ca_bundle: False" >> data/acme_srv.cfg + sudo echo "api_user: $NCM_API_USER" >> data/acme_srv.cfg + sudo echo "api_password: $NCM_API_PASSWORD" >> data/acme_srv.cfg + sudo echo "ca_name: $NCM_CA_NAME" >> data/acme_srv.cfg + # sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> data/acme_srv.cfg + sudo sed -i "s/tnauthlist_support: False/tnauthlist_support: False\nheader_info_list: [\"HTTP_USER_AGENT\"]/g" data/acme_srv.cfg + env: + NCM_API_HOST: ${{ secrets.NCM_API_HOST }} + NCM_API_USER: ${{ secrets.NCM_API_USER }} + NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} + NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} + NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} + PROFILE: ${{ secrets.PROFILE }} - - name: "[ * ] collecting test logs" - if: ${{ failure() }} + - name: "Header-info - Reconfigure a2c " run: | - mkdir -p ${{ github.workspace }}/artifact/upload - docker exec acme-srv tar cvfz /tmp/acme2certifier/a2c.tgz /opt/acme2certifier - sudo cp -rp data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp acme-sh/ ${{ github.workspace }}/artifact/acme-sh/ - docker exec acme-srv cat /var/log/messages > ${{ github.workspace }}/artifact/acme-srv.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz data acme-srv.log acme-sh - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: certifier_ca_handler_rpm.tar.gz - path: ${{ github.workspace }}/artifact/upload/ + docker exec acme-srv sh /tmp/acme2certifier/rpm_tester.sh restart + - name: "Header-info - Enrollmnet" + uses: ./.github/actions/wf_specific/certifier_ca_handler/enroll_headerinfo - certifier_handler_headerinfo_tests: - name: "certifier_handler_headerinfo_tests" - runs-on: ubuntu-latest - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "[ PREPARE ] Build docker-compose (apache2_wsgi)" - working-directory: examples/Docker/ + - name: "EAB without headerinfo - Setup a2c with certifier_ca_handler" run: | - sudo mkdir -p data - docker network create acme - docker-compose up -d - docker-compose logs + sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > data/acme_srv.cfg + sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> data/acme_srv.cfg + # sudo echo "api_host: $NCM_API_HOST" >> data/acme_srv.cfg + sudo echo "api_host: https://forwarder.acme:8084" >> data/acme_srv.cfg + sudo echo "ca_bundle: False" >> data/acme_srv.cfg + sudo echo "api_user: $NCM_API_USER" >> data/acme_srv.cfg + sudo echo "api_password: $NCM_API_PASSWORD" >> data/acme_srv.cfg + sudo echo "ca_name: $NCM_CA_NAME" >> data/acme_srv.cfg + # sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> data/acme_srv.cfg + sudo echo "profile_id: 100" >> data/acme_srv.cfg + sudo echo "eab_profiling: True" >> data/acme_srv.cfg + sudo echo -e "\n\n[EABhandler]" >> data/acme_srv.cfg + sudo echo "eab_handler_file: /opt/acme2certifier/examples/eab_handler/kid_profile_handler.py" >> data/acme_srv.cfg + sudo echo "key_file: /opt/acme2certifier/volume/acme_ca/kid_profiles.json" >> data/acme_srv.cfg + + sudo cp examples/eab_handler/kid_profiles.json data/acme_ca/kid_profiles.json + sudo chmod 777 data/acme_ca/kid_profiles.json + sudo sed -i "s/\"profile_id\"\: \[\"profile_1\", \"profile_2\", \"profile_3\"\]/\"profile_id\"\: \[\"102\", \"101\"\, \"100\"]/g" data/acme_ca/kid_profiles.json + sudo sed -i "s/\"profile_id\"\: \"profile_2\"/\"profile_id\"\: \"102\"/g" data/acme_ca/kid_profiles.json + sudo sed -i "s/\"ca_name\": \"example_ca_2\",/\"ca_name\": \"SubCA2\"/" data/acme_ca/kid_profiles.json + sudo sed -i "s/\"ca_name\": \"example_ca\",/\"unknown_key\": \"unknown_value\"/g" data/acme_ca/kid_profiles.json + sudo sed -i "s/example.net/acme/g" data/acme_ca/kid_profiles.json + sudo sed -i '18,19d' data/acme_ca/kid_profiles.json + sudo sed -i '8,9d' data/acme_ca/kid_profiles.json + env: + NCM_API_HOST: ${{ secrets.NCM_API_HOST }} + NCM_API_USER: ${{ secrets.NCM_API_USER }} + NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} + NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} + NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} + PROFILE: ${{ secrets.PROFILE }} - - name: "[ PREPARE ] create lego folder" + - name: "EAB without headerinfo - Reconfigure a2c " run: | - mkdir lego + docker exec acme-srv sh /tmp/acme2certifier/rpm_tester.sh restart - - name: "Test http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory + - name: "EAB without headerinfo - Enrollment" + uses: ./.github/actions/wf_specific/certifier_ca_handler/enroll_eab_wo_headerinfo - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" + - name: "EAB with headerinfo - Setup a2c with certifier_ca_handler" run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - sudo sed -i "s/tnauthlist_support: False/tnauthlist_support: False\nheader_info_list: [\"HTTP_USER_AGENT\"]/g" examples/Docker/data/acme_srv.cfg - cd examples/Docker/ - docker-compose restart - docker-compose logs + sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > data/acme_srv.cfg + sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> data/acme_srv.cfg + # sudo echo "api_host: $NCM_API_HOST" >> data/acme_srv.cfg + sudo echo "api_host: https://forwarder.acme:8084" >> data/acme_srv.cfg + sudo echo "ca_bundle: False" >> data/acme_srv.cfg + sudo echo "api_user: $NCM_API_USER" >> data/acme_srv.cfg + sudo echo "api_password: $NCM_API_PASSWORD" >> data/acme_srv.cfg + sudo echo "ca_name: $NCM_CA_NAME" >> data/acme_srv.cfg + # sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> data/acme_srv.cfg + sudo echo "profile_id: 100" >> data/acme_srv.cfg + sudo echo "eab_profiling: True" >> data/acme_srv.cfg + sudo sed -i "s/tnauthlist_support: False/tnauthlist_support: False\nheader_info_list: [\"HTTP_USER_AGENT\"]/g" data/acme_srv.cfg + sudo echo -e "\n\n[EABhandler]" >> data/acme_srv.cfg + sudo echo "eab_handler_file: /opt/acme2certifier/examples/eab_handler/kid_profile_handler.py" >> data/acme_srv.cfg + sudo echo "key_file: /opt/acme2certifier/volume/acme_ca/kid_profiles.json" >> data/acme_srv.cfg + + sudo cp examples/eab_handler/kid_profiles.json data/acme_ca/kid_profiles.json + sudo chmod 777 data/acme_ca/kid_profiles.json + sudo sed -i "s/\"profile_id\"\: \[\"profile_1\", \"profile_2\", \"profile_3\"\]/\"profile_id\"\: \[\"102\", \"101\"\, \"100\"]/g" data/acme_ca/kid_profiles.json + sudo sed -i "s/\"profile_id\"\: \"profile_2\"/\"profile_id\"\: \"102\"/g" data/acme_ca/kid_profiles.json + sudo sed -i "s/\"ca_name\": \"example_ca_2\",/\"ca_name\": \"SubCA2\"/" data/acme_ca/kid_profiles.json + sudo sed -i "s/\"ca_name\": \"example_ca\",/\"unknown_key\": \"unknown_value\"/g" data/acme_ca/kid_profiles.json + sudo sed -i "s/example.net/acme/g" data/acme_ca/kid_profiles.json + sudo sed -i '18,19d' data/acme_ca/kid_profiles.json + sudo sed -i '8,9d' data/acme_ca/kid_profiles.json env: NCM_API_HOST: ${{ secrets.NCM_API_HOST }} NCM_API_USER: ${{ secrets.NCM_API_USER }} NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} + PROFILE: ${{ secrets.PROFILE }} - - name: "Test http://acme-srv/directory is accessable again" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "[ PREPARE ] prepare acme.sh container" + - name: "EAB with headerinfo - Reconfigure a2c " run: | - sudo mkdir acme-sh - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon + docker exec acme-srv sh /tmp/acme2certifier/rpm_tester.sh restart - - name: "[ REGISTER] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --debug 3 + - name: "EAB with headerinfo - Enrollment" + uses: ./.github/actions/wf_specific/certifier_ca_handler/enroll_eab_w_headerinfo - - name: "[ ENROLL] acme.sh with profileID 101" + - name: "EAB with headerinfo - Reconfigure key_file without restarting" run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --issue -d acme-sh.acme --standalone --useragent profileID=101 --debug 3 --output-insecure - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -ext extendedKeyUsage -noout | grep -i "TLS Web Client" + sudo sed -i "s/\"allowed_domainlist\": \[\"www.example.com\", \"www.example.org\"\]/\"allowed_domainlist\": \[\"www.example.com\", \"www.example.org\", \"*.acme\"\]/g" data/acme_ca/kid_profiles.json + sudo sed -i '26,27d' data/acme_ca/kid_profiles.json + sudo sed -i "s/ \"hmac\": \"YW5kX2ZpbmFsbHlfdGhlX2xhc3RfaG1hY19rZXlfd2hpY2hfaXNfbG9uZ2VyX3RoYW5fMjU2X2JpdHNfYW5kX3Nob3VsZF93b3Jr\"/ \"hmac\": \"YW5kX2ZpbmFsbHlfdGhlX2xhc3RfaG1hY19rZXlfd2hpY2hfaXNfbG9uZ2VyX3RoYW5fMjU2X2JpdHNfYW5kX3Nob3VsZF93b3Jr\"\n },\n \"keyid_04\": {\n \"hmac\": \"YW5kX2hlcmVfaXNfYW5vdGhlcl92ZXJ5X2xvbmdfbWFja19obWFjX2tleV90b19jaGVja19pZl9jaGFuZ2VzX2FmZmVjdF9pbW1lZGF0ZWx5\",\n \"cahandler\": {}\n }\n}/g" data/acme_ca/kid_profiles.json - - name: "[ ENROLL ] lego with profileID 101" + - name: "Update configuration" run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --user-agent profileID=101 -d lego.acme --http run - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt - sudo openssl x509 -in lego/certificates/lego.acme.crt -ext extendedKeyUsage -noout | grep -i "TLS Web Client" + docker exec acme-srv sh /tmp/acme2certifier/rpm_tester.sh update + + - name: "EAB with headerinfo - Enrollment after reconfiguration" + uses: ./.github/actions/wf_specific/certifier_ca_handler/enroll_eab_w_headerinfo + with: + RECONFIGURE: true - - name: "[ ENROLL] acme.sh with profileID 102" + - name: "kid-file in yaml format - Reconfiguration" run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --renew --force -d acme-sh.acme --standalone --useragent profileID=102 --debug 3 --output-insecure - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - openssl x509 -in acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer -ext extendedKeyUsage -noout | grep -i "TLS Web Server" + sudo sed -i "s/kid_profiles.json/kid_profiles.yml/g" data/acme_srv.cfg + sudo pip3 install yq + sudo pip3 install jq + sudo sh -c "cat data/acme_ca/kid_profiles.json | yq -y '.' > data/acme_ca/kid_profiles.yml" + sudo rm data/acme_ca/kid_profiles.json + sudo sed -i '33,34d' data/acme_ca/kid_profiles.yml - - name: "[ ENROLL ] lego with profileID 102" + - name: "kid-file in yaml format - update a2c " run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --user-agent profileID=102 -d lego.acme --http run - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt - sudo openssl x509 -in lego/certificates/lego.acme.crt -ext extendedKeyUsage -noout | grep -i "TLS Web Server" + docker exec acme-srv sh /tmp/acme2certifier/rpm_tester.sh restart + + - name: "kid-file in yaml format - Enrollment after reconfiguration" + uses: ./.github/actions/wf_specific/certifier_ca_handler/enroll_eab_w_headerinfo + with: + RECONFIGURE: true - name: "[ * ] collecting test logs" if: ${{ failure() }} run: | mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp lego/ ${{ github.workspace }}/artifact/lego/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data lego + docker exec acme-srv tar cvfz /tmp/acme2certifier/a2c.tgz /opt/acme2certifier + sudo cp -rp data/ ${{ github.workspace }}/artifact/data/ + sudo rm ${{ github.workspace }}/artifact/data/*.rpm + sudo cp -rp acme-sh/ ${{ github.workspace }}/artifact/acme-sh/ + docker exec acme-srv cat /etc/nginx/nginx.conf.orig > ${{ github.workspace }}/artifact/data/nginx.conf.orig + docker exec acme-srv cat /etc/nginx/nginx.conf > ${{ github.workspace }}/artifact/data/nginx.conf + docker exec acme-srv cat /var/log/messages > ${{ github.workspace }}/artifact/acme-srv.log + sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz data acme-srv.log acme-sh - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: ${{ failure() }} with: - name: certifier_handler_headerinfo_tests.tar.gz - path: ${{ github.workspace }}/artifact/upload/ \ No newline at end of file + name: certifier_ca_handler_rpm-rh${{ matrix.rhversion }}.tar.gz + path: ${{ github.workspace }}/artifact/upload/ + diff --git a/.github/workflows/ca_handler_tests_nclm.yml b/.github/workflows/ca_handler_tests_nclm.yml index 80a79e40..432be990 100644 --- a/.github/workflows/ca_handler_tests_nclm.yml +++ b/.github/workflows/ca_handler_tests_nclm.yml @@ -12,27 +12,29 @@ jobs: nclm_handler_tests: name: "nclm_handler_tests" runs-on: ubuntu-latest + strategy: + max-parallel: 1 + fail-fast: false + # max-parallel: 1 + matrix: + websrv: ['apache2', 'nginx'] + dbhandler: ['wsgi', 'django'] steps: - name: "checkout GIT" - uses: actions/checkout@v3 + uses: actions/checkout@v4 - - name: "[ PREPARE ] Build docker-compose (apache2_wsgi)" - working-directory: examples/Docker/ + - name: "Generate UUID" run: | - sudo mkdir -p data - docker network create acme - docker-compose up -d - docker-compose logs + echo UUID=$(uuidgen | cut -d "-" -f1) >> $GITHUB_ENV + - run: echo "UUID ${{ env.UUID }}" - - name: "[ PREPARE ] create letsencrypt and lego folder" - run: | - mkdir certbot - mkdir lego - - - name: "Test http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory + - name: "Build container" + uses: ./.github/actions/container_prep + with: + DB_HANDLER: ${{ matrix.dbhandler }} + WEB_SRV: ${{ matrix.websrv }} - - name: "[ PREPARE ] setup a2c with nclm_ca_handler" + - name: "Setup a2c with nclm_ca_handler" run: | sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem sudo touch examples/Docker/data/acme_srv.cfg @@ -48,7 +50,6 @@ jobs: sudo sed -i "s/revocation_reason_check_disable: False/revocation_reason_check_disable: False\nenrollment_timeout: 45/g" examples/Docker/data/acme_srv.cfg cd examples/Docker/ docker-compose restart - docker-compose logs env: NCLM_API_HOST: ${{ secrets.NCLM_API_HOST }} NCLM_API_USER: ${{ secrets.NCLM_API_USER }} @@ -57,68 +58,50 @@ jobs: NCLM_CA_NAME: ${{ secrets.NCLM_CA_NAME }} NCLM_CA_ID_LIST: ${{ secrets.NCLM_CA_ID_LIST }} - - name: "Test http://acme-srv/directory is accessable again" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - sudo mkdir acme-sh - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ ENROLL ] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --alpn --standalone --debug 3 --output-insecure --force - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - - name: "[ REGISTER] certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email - - - name: "[ ENROLL ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem + - name: "Test enrollment" + uses: ./.github/actions/acme_clients + with: + HOSTNAME_SUFFIX: -${{ env.UUID }} + VERIFY_CERT: false - - name: "[ ENROLL ] lego" + - name: "Generate UUID" run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --http run - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + echo UUID=$(uuidgen | cut -d "-" -f1) >> $GITHUB_ENV + - run: echo "UUID ${{ env.UUID }}" - - name: "[ PREPARE ] reconfigure nclm handler to test enrollment from MSCA" + - name: "Reconfigure nclm handler to test enrollment from MSCA" run: | sudo sed -i "s/ca_name: $NCLM_CA_NAME/ca_name: $NCLM_MSCA_NAME/g" examples/Docker/data/acme_srv.cfg sudo echo "template_name: $NCLM_MSCA_TEMPLATE_NAME" >> examples/Docker/data/acme_srv.cfg - sudo rm -rf lego/* + cd examples/Docker/ + docker-compose restart env: NCLM_MSCA_TEMPLATE_NAME: ${{ secrets.NCLM_MSCA_TEMPLATE_NAME }} NCLM_MSCA_NAME: ${{ secrets.NCLM_MSCA_NAME }} NCLM_CA_NAME: ${{ secrets.NCLM_CA_NAME }} - - name: "[ PREPARE ] restart a2c" - working-directory: examples/Docker/ - run: | - docker-compose restart - - - name: "[ ENROLL ] lego" - run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --http run - sudo openssl verify -CAfile lego/certificates/lego.acme.issuer.crt lego/certificates/lego.acme.crt + - name: "Test enrollment" + uses: ./.github/actions/acme_clients + with: + USE_RSA: true + HOSTNAME_SUFFIX: -${{ env.UUID }} - name: "[ * ] collecting test logs" if: ${{ failure() }} run: | mkdir -p ${{ github.workspace }}/artifact/upload + mkdir -p ${{ github.workspace }}/artifact/clients sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp acme-sh/ ${{ github.workspace }}/artifact/acme-sh/ - sudo cp -rp certbot/ ${{ github.workspace }}/artifact/certbot/ - sudo cp -rp lego/ ${{ github.workspace }}/artifact/lego/ + # sudo cp *.pem ${{ github.workspace }}/artifact/data/ + sudo cp -rp acme-sh/ ${{ github.workspace }}/artifact/clients/acme-sh/ + sudo cp -rp certbot/ ${{ github.workspace }}/artifact/clients/certbot/ + sudo cp -rp lego/ ${{ github.workspace }}/artifact/clients/lego/ cd examples/Docker docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data acme-sh certbot lego + sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data clients - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: ${{ failure() }} with: name: nclm.tar.gz @@ -128,43 +111,31 @@ jobs: nclm_handler_tests_rpm: name: "nclm_handler_tests_rpm" runs-on: ubuntu-latest + strategy: + fail-fast: false + max-parallel: 1 + matrix: + rhversion: [8, 9] + execscript: ['rpm_tester.sh', 'django_tester.sh'] + steps: - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: Retrieve Version from version.py - run: | - echo TAG_NAME=$(cat acme_srv/version.py | grep -i __version__ | head -n 1 | sed 's/__version__ = //g' | sed s/\'//g) >> $GITHUB_ENV - - run: echo "Latest tag is ${{ env.TAG_NAME }}" + uses: actions/checkout@v4 - - name: update version number in spec file + - name: "Generate UUID" run: | - # sudo sed -i "s/Source0:.*/Source0: %{name}-%{version}.tar.gz/g" examples/install_scripts/rpm/acme2certifier.spec - sudo sed -i "s/__version__/${{ env.TAG_NAME }}/g" examples/install_scripts/rpm/acme2certifier.spec - cat examples/install_scripts/rpm/acme2certifier.spec + echo UUID=$(uuidgen | cut -d "-" -f1) >> $GITHUB_ENV + - run: echo "UUID ${{ env.UUID }}" - - name: build RPM package - id: rpm - uses: grindsa/rpmbuild@alma9 + - name: "Prepare Alma environment" + uses: ./.github/actions/rpm_prep with: - spec_file: "examples/install_scripts/rpm/acme2certifier.spec" - - - run: echo "path is ${{ steps.rpm.outputs.rpm_dir_path }}" - - - name: "[ PREPARE ] setup environment for alma installation" - run: | - docker network create acme - sudo mkdir -p data - sudo chmod -R 777 data - sudo cp ${{ steps.rpm.outputs.rpm_dir_path }}noarch/acme2certifier-${{ env.TAG_NAME }}-1.0.noarch.rpm data - sudo cp examples/Docker/almalinux-systemd/rpm_tester.sh data + GH_SBOM_USER: ${{ secrets.GH_SBOM_USER }} + GH_SBOM_TOKEN: ${{ secrets.GH_SBOM_TOKEN }} + RH_VERSION: ${{ matrix.rhversion }} - - name: "[ PREPARE ] create letsencrypt and lego folder" - run: | - mkdir certbot - mkdir lego - - - name: "[ PREPARE ] prepare acme_srv.cfg with nclm_ca_handler" + - name: "Setup a2c with with nclm_ca_handler" + if: matrix.execscript == 'rpm_tester.sh' run: | mkdir -p data/acme_ca sudo cp test/ca/certsrv_ca_certs.pem data/acme_ca/ca_certs.pem @@ -178,8 +149,8 @@ jobs: sudo echo "tsg_name: $NCLM_TSG_NAME" >> data/acme_srv.cfg sudo echo "ca_name: $NCLM_CA_NAME" >> data/acme_srv.cfg sudo echo "ca_id_list: [$NCLM_CA_ID_LIST]" >> data/acme_srv.cfg - sudo sed -i "s/revocation_reason_check_disable: False/revocation_reason_check_disable: False\nenrollment_timeout: 30/g" data/acme_srv.cfg - + sudo echo "request_timeout: 40" >> data/acme_srv.cfg + sudo sed -i "s/revocation_reason_check_disable: False/revocation_reason_check_disable: False\nenrollment_timeout: 60/g" data/acme_srv.cfg env: NCLM_API_HOST: ${{ secrets.NCLM_API_HOST }} NCLM_API_USER: ${{ secrets.NCLM_API_USER }} @@ -188,60 +159,101 @@ jobs: NCLM_CA_NAME: ${{ secrets.NCLM_CA_NAME }} NCLM_CA_ID_LIST: ${{ secrets.NCLM_CA_ID_LIST }} - - name: "[ PREPARE ] Almalinux instance" + - name: "Setup a2c with with nclm_ca_handler for django" + if: matrix.execscript == 'django_tester.sh' run: | - cat examples/Docker/almalinux-systemd/Dockerfile | docker build -t almalinux-systemd -f - . --no-cache - docker run -d -id --privileged --network acme --name=acme-srv -v "$(pwd)/data":/tmp/acme2certifier almalinux-systemd + sudo mkdir -p data/volume/acme_ca/certs + sudo cp test/ca/certsrv_ca_certs.pem data/volume/acme_ca/ca_certs.pem + sudo touch data/volume/acme_srv.cfg + sudo chmod 777 data/volume/acme_srv.cfg + sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > data/volume/acme_srv.cfg + sudo echo "handler_file: examples/ca_handler/nclm_ca_handler.py" >> data/volume/acme_srv.cfg + sudo echo "api_host: $NCLM_API_HOST" >> data/volume/acme_srv.cfg + sudo echo "api_user: $NCLM_API_USER" >> data/volume/acme_srv.cfg + sudo echo "api_password: $NCLM_API_PASSWORD" >> data/volume/acme_srv.cfg + sudo echo "tsg_name: $NCLM_TSG_NAME" >> data/volume/acme_srv.cfg + sudo echo "ca_name: $NCLM_CA_NAME" >> data/volume/acme_srv.cfg + sudo echo "ca_id_list: [$NCLM_CA_ID_LIST]" >> data/volume/acme_srv.cfg + sudo echo "request_timeout: 40" >> data/volume/acme_srv.cfg + sudo sed -i "s/revocation_reason_check_disable: False/revocation_reason_check_disable: False\nenrollment_timeout: 60/g" data/volume/acme_srv.cfg + env: + NCLM_API_HOST: ${{ secrets.NCLM_API_HOST }} + NCLM_API_USER: ${{ secrets.NCLM_API_USER }} + NCLM_API_PASSWORD: ${{ secrets.NCLM_API_PASSWORD }} + NCLM_TSG_NAME: ${{ secrets.NCLM_TSG_NAME }} + NCLM_CA_NAME: ${{ secrets.NCLM_CA_NAME }} + NCLM_CA_ID_LIST: ${{ secrets.NCLM_CA_ID_LIST }} - - name: "[ RUN ] Execute install scipt" + - name: "Execute install scipt" run: | - docker exec acme-srv sh /tmp/acme2certifier/rpm_tester.sh - - - name: "Test http://acme-srv/directory is accessible" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory + docker exec acme-srv sh /tmp/acme2certifier/$EXEC_SCRIPT + env: + EXEC_SCRIPT: ${{ matrix.execscript }} - - name: "[ PREPARE ] prepare acme.sh container" - run: | - sudo mkdir acme-sh - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh -e MAX_RETRY_TIMES=4 neilpang/acme.sh:latest daemon + - name: "Test enrollment" + uses: ./.github/actions/acme_clients + with: + HOSTNAME_SUFFIX: -${{ env.UUID }} + VERIFY_CERT: false - - name: "[ REGISTER] acme.sh" + - name: "Generate UUID" run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --debug 3 + echo UUID=$(uuidgen | cut -d "-" -f1) >> $GITHUB_ENV + - run: echo "UUID ${{ env.UUID }}" - - name: "[ ENROLL] acme.sh" + - name: "Reconfigure nclm handler to test enrollment from MSCA" + if: matrix.execscript == 'rpm_tester.sh' run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --issue -d acme-sh.acme --standalone --debug 3 --output-insecure - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer + sudo sed -i "s/ca_name: $NCLM_CA_NAME/ca_name: $NCLM_MSCA_NAME/g" data/acme_srv.cfg + sudo echo "template_name: $NCLM_MSCA_TEMPLATE_NAME" >> data/acme_srv.cfg + env: + NCLM_MSCA_TEMPLATE_NAME: ${{ secrets.NCLM_MSCA_TEMPLATE_NAME }} + NCLM_MSCA_NAME: ${{ secrets.NCLM_MSCA_NAME }} + NCLM_CA_NAME: ${{ secrets.NCLM_CA_NAME }} - - name: "[ REGISTER ] certbot" + - name: "Reconfigure nclm handler to test enrollment from MSCA" + if: matrix.execscript == 'django_tester.sh' run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email + sudo sed -i "s/ca_name: $NCLM_CA_NAME/ca_name: $NCLM_MSCA_NAME/g" data/volume/acme_srv.cfg + sudo echo "template_name: $NCLM_MSCA_TEMPLATE_NAME" >> data/volume/acme_srv.cfg + env: + NCLM_MSCA_TEMPLATE_NAME: ${{ secrets.NCLM_MSCA_TEMPLATE_NAME }} + NCLM_MSCA_NAME: ${{ secrets.NCLM_MSCA_NAME }} + NCLM_CA_NAME: ${{ secrets.NCLM_CA_NAME }} - - name: "[ ENROLL ] HTTP-01 single domain certbot" + - name: "Execute install scipt" run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem + docker exec acme-srv sh /tmp/acme2certifier/$EXEC_SCRIPT restart + env: + EXEC_SCRIPT: ${{ matrix.execscript }} - - name: "[ ENROLL ] lego" - run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --http run - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + - name: "Test enrollment" + uses: ./.github/actions/acme_clients + with: + USE_RSA: true + HOSTNAME_SUFFIX: -${{ env.UUID }} - name: "[ * ] collecting test logs" if: ${{ failure() }} + continue-on-error: true run: | mkdir -p ${{ github.workspace }}/artifact/upload + mkdir -p ${{ github.workspace }}/artifact/clients docker exec acme-srv tar cvfz /tmp/acme2certifier/a2c.tgz /opt/acme2certifier sudo cp -rp data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp acme-sh/ ${{ github.workspace }}/artifact/acme-sh/ + # sudo cp *.pem ${{ github.workspace }}/artifact/data/ + sudo cp -rp acme-sh/ ${{ github.workspace }}/artifact/clients/acme-sh/ + sudo cp -rp certbot/ ${{ github.workspace }}/artifact/clients/certbot/ + sudo cp -rp lego/ ${{ github.workspace }}/artifact/clients/lego/ + sudo rm ${{ github.workspace }}/artifact/data/*.rpm + docker exec acme-srv cat /etc/nginx/nginx.conf.orig > ${{ github.workspace }}/artifact/data/nginx.conf.orig + docker exec acme-srv cat /etc/nginx/nginx.conf > ${{ github.workspace }}/artifact/data/nginx.conf docker exec acme-srv cat /var/log/messages > ${{ github.workspace }}/artifact/acme-srv.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz data acme-srv.log acme-sh + sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz data clients acme-srv.log - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: ${{ failure() }} with: - name: nclm_ca_handler_rpm.tar.gz + name: nclm_ca_handler_rpm-rh${{ matrix.rhversion }}-${{ matrix.execscript}}.tar.gz path: ${{ github.workspace }}/artifact/upload/ \ No newline at end of file diff --git a/.github/workflows/caddy-application-test.yml b/.github/workflows/caddy-application-test.yml deleted file mode 100644 index 4cc23b6b..00000000 --- a/.github/workflows/caddy-application-test.yml +++ /dev/null @@ -1,387 +0,0 @@ -name: Application Tests - Caddy - -on: - push: - pull_request: - branches: [ devel ] - schedule: - # * is a special character in YAML so you have to quote this string - - cron: '0 2 * * 6' - -jobs: - caddy_apache2_wsgi: - name: "caddy_apache2_wsgi" - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - ports: ['-p 80:80 -p 443:443', '-p 443:443'] - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "Build docker-compose (apache2_wsgi)" - working-directory: examples/Docker/ - run: | - sudo mkdir -p data - docker network create acme - docker-compose up -d - docker-compose logs - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - sudo cp .github/acme2certifier.pem examples/Docker/data/acme2certifier.pem - cd examples/Docker/ - docker-compose restart - docker-compose logs - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "Test http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "Test if https://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory - - - - name: "Create caddy folder and copy configuratation files" - run: | - mkdir caddy - cp .github/Caddyfile caddy/ - cp .github/acme2certifier_cabundle.pem caddy - - - name: "Enroll certificate with Caddy" - run: | - docker run -d --rm ${{ matrix.ports }} --network acme -v $PWD/caddy/Caddyfile:/etc/caddy/Caddyfile -v$PWD/caddy/acme2certifier_cabundle.pem:/tmp/acme2certifier_cabundle.pem -v $(pwd)/caddy/config:/config -v $(pwd)/caddy/data:/data --name=caddy caddy:2 - - - name: "Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "Check for logs indicating successful enrollment" - run: | - docker logs caddy 2>&1 | grep "successfully downloaded available certificate chains" - docker logs caddy 2>&1 | grep "certificate obtained successfully" - - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp caddy/ ${{ github.workspace }}/artifact/caddy/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/a2c.log - docker logs caddy 2> ${{ github.workspace }}/artifact/caddy.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log caddy.log data caddy - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: caddy_apache2_wsgi-${{ github.run_id }}.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - - - caddy_apache2_django: - name: "caddy_apache2_django" - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - ports: ['-p 80:80 -p 443:443', '-p 443:443'] - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "Build docker-compose (apache2_django)" - working-directory: examples/Docker/ - run: | - sed -i "s/wsgi/django/g" .env - sudo mkdir -p data - docker network create acme - docker-compose up -d - docker-compose logs - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - sudo cp .github/acme2certifier.pem examples/Docker/data/acme2certifier.pem - sudo cp .github/django_settings.py examples/Docker/data/settings.py - cd examples/Docker/ - docker-compose restart - docker-compose logs - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "Test http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "Test if https://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory - - - - name: "Create caddy folder and copy configuratation files" - run: | - mkdir caddy - cp .github/Caddyfile caddy/ - cp .github/acme2certifier_cabundle.pem caddy - - - name: "Enroll certificate with Caddy" - run: | - docker run -d --rm ${{ matrix.ports }} --network acme -v $PWD/caddy/Caddyfile:/etc/caddy/Caddyfile -v$PWD/caddy/acme2certifier_cabundle.pem:/tmp/acme2certifier_cabundle.pem -v $(pwd)/caddy/config:/config -v $(pwd)/caddy/data:/data --name=caddy caddy:2 - - - name: "Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "Check for logs indicating successful enrollment" - run: | - docker logs caddy 2>&1 | grep "successfully downloaded available certificate chains" - docker logs caddy 2>&1 | grep "certificate obtained successfully" - - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp caddy/ ${{ github.workspace }}/artifact/caddy/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/a2c.log - docker logs caddy 2> ${{ github.workspace }}/artifact/caddy.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log caddy.log data caddy - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: caddy_apache2_django-${{ github.run_id }}.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - - - caddy_nginx_wsgi: - name: "caddy_nginx_wsgi" - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - ports: ['-p 80:80 -p 443:443', '-p 443:443'] - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "Build docker-compose (nginx_wsgi)" - working-directory: examples/Docker/ - run: | - sed -i "s/apache2/nginx/g" .env - sudo mkdir -p data - docker network create acme - docker-compose up -d - docker-compose logs - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - sudo cp .github/acme2certifier_cert.pem examples/Docker/data/acme2certifier_cert.pem - sudo cp .github/acme2certifier_key.pem examples/Docker/data/acme2certifier_key.pem - cd examples/Docker/ - docker-compose restart - docker-compose logs - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "Test http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "Test if https://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory - - - - name: "Create caddy folder and copy configuratation files" - run: | - mkdir caddy - cp .github/Caddyfile caddy/ - cp .github/acme2certifier_cabundle.pem caddy - - - name: " enroll certificate with Caddy" - run: | - docker run -d --rm ${{ matrix.ports }} --network acme -v $PWD/caddy/Caddyfile:/etc/caddy/Caddyfile -v$PWD/caddy/acme2certifier_cabundle.pem:/tmp/acme2certifier_cabundle.pem -v $(pwd)/caddy/config:/config -v $(pwd)/caddy/data:/data --name=caddy caddy:2 - - - name: "Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "Check for logs indicating successful enrollment" - run: | - docker logs caddy 2>&1 | grep "successfully downloaded available certificate chains" - docker logs caddy 2>&1 | grep "certificate obtained successfully" - - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp caddy/ ${{ github.workspace }}/artifact/caddy/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/a2c.log - docker logs caddy 2> ${{ github.workspace }}/artifact/caddy.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log caddy.log data caddy - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: caddy_nginx_wsgi-${{ github.run_id }}.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - - caddy_nginx_django: - name: "caddy_nginx_django" - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - ports: ['-p 80:80 -p 443:443', '-p 443:443'] - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "Build docker-compose (nginx_django)" - working-directory: examples/Docker/ - run: | - sed -i "s/wsgi/django/g" .env - sed -i "s/apache2/nginx/g" .env - sudo mkdir -p data - docker network create acme - docker-compose up -d - docker-compose logs - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - sudo cp .github/acme2certifier_cert.pem examples/Docker/data/acme2certifier_cert.pem - sudo cp .github/acme2certifier_key.pem examples/Docker/data/acme2certifier_key.pem - sudo cp .github/django_settings.py examples/Docker/data/settings.py - cd examples/Docker/ - docker-compose restart - docker-compose logs - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "Test http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "Test if https://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory - - - name: "Create caddy folder and copy configuratation files" - run: | - mkdir caddy - cp .github/Caddyfile caddy/ - cp .github/acme2certifier_cabundle.pem caddy - - - name: "Enroll certificate with Caddy" - run: | - docker run -d --rm ${{ matrix.ports }} --network acme -v $PWD/caddy/Caddyfile:/etc/caddy/Caddyfile -v$PWD/caddy/acme2certifier_cabundle.pem:/tmp/acme2certifier_cabundle.pem -v $(pwd)/caddy/config:/config -v $(pwd)/caddy/data:/data --name=caddy caddy:2 - - - name: "Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "Check for logs indicating successful enrollment" - run: | - docker logs caddy 2>&1 | grep "successfully downloaded available certificate chains" - docker logs caddy 2>&1 | grep "certificate obtained successfully" - - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp caddy/ ${{ github.workspace }}/artifact/caddy/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/a2c.log - docker logs caddy 2> ${{ github.workspace }}/artifact/caddy.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log caddy.log data caddy - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: caddy_nginx_django-${{ github.run_id }}.tar.gz - path: ${{ github.workspace }}/artifact/upload/ diff --git a/.github/workflows/certbot-application-test.yml b/.github/workflows/certbot-application-test.yml deleted file mode 100644 index eb1e9835..00000000 --- a/.github/workflows/certbot-application-test.yml +++ /dev/null @@ -1,437 +0,0 @@ -name: Application Tests - Certbot - -on: - push: - pull_request: - branches: [ devel ] - schedule: - # * is a special character in YAML so you have to quote this string - - cron: '0 2 * * 6' - -jobs: - - certbot_apache2_wsgi: - name: "certbot_apache2_wsgi" - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - keylength: [2048, 4096] - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "[ PREPARE ] Build docker-compose (apache2_wsgi)" - working-directory: examples/Docker/ - run: | - sudo mkdir -p data - docker network create acme - docker-compose up -d - docker-compose logs - - - name: "[ PREPARE ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "Test http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - cd examples/Docker/ - docker-compose restart - docker-compose logs - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "[ PREPARE ] create letsencrypt folder" - run: | - mkdir certbot - - - name: "[ REGISTER] certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email - - - name: "[ ENROLL ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --rsa-key-size ${{ matrix.keylength }} --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot - sudo chmod 777 certbot/archive/certbot/chain1.pem - sudo cp certbot/archive/certbot/chain1.pem chain1.pem - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < chain1.pem - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem - - - name: "[ RENEW ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --force-renew --rsa-key-size ${{ matrix.keylength }} --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem - - - name: "[ REVOKE ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot revoke --delete-after-revoke --server http://acme-srv -d certbot.acme --cert-name certbot - - - name: "[ ENROLL ] HTTP-01 2x domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --rsa-key-size ${{ matrix.keylength }} --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme -d certbot. --cert-name certbot - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem - - - name: "[ RENEW ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --force-renew --rsa-key-size ${{ matrix.keylength }} --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme -d certbot. --cert-name certbot - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem - - - name: "[ REVOKE ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot revoke --delete-after-revoke --server http://acme-srv -d certbot.acme -d certbot. --cert-name certbot - - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp certbot/ ${{ github.workspace }}/artifact/certbot/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data certbot - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: certbot_apache2_wsgi-${{ matrix.keylength }}.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - - certbot_apache2_django: - name: "certbot_apache2_django" - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - keylength: [2048, 4096] - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "[ PREPARE ] Build docker-compose (apache2_django)" - working-directory: examples/Docker/ - run: | - sed -i "s/wsgi/django/g" .env - sudo mkdir -p data - docker network create acme - docker-compose up -d - docker-compose logs - - - name: "[ PREPARE ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "Test http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - sudo cp .github/django_settings.py examples/Docker/data/settings.py - cd examples/Docker/ - docker-compose restart - docker-compose logs - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "[ PREPARE ] create letsencrypt folder" - run: | - mkdir certbot - - - name: "[ REGISTER] certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email - - - name: "[ ENROLL ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --rsa-key-size ${{ matrix.keylength }} --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot - sudo chmod 777 certbot/archive/certbot/chain1.pem - sudo cp certbot/archive/certbot/chain1.pem chain1.pem - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < chain1.pem - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem - - - name: "[ RENEW ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --force-renew --rsa-key-size ${{ matrix.keylength }} --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem - - - name: "[ REVOKE ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot revoke --delete-after-revoke --server http://acme-srv -d certbot.acme --cert-name certbot - - - name: "[ ENROLL ] HTTP-01 2x domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --rsa-key-size ${{ matrix.keylength }} --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme -d certbot. --cert-name certbot - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem - - - name: "[ RENEW ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --force-renew --rsa-key-size ${{ matrix.keylength }} --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme -d certbot. --cert-name certbot - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem - - - name: "[ REVOKE ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot revoke --delete-after-revoke --server http://acme-srv -d certbot.acme -d certbot. --cert-name certbot - - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp certbot/ ${{ github.workspace }}/artifact/certbot/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data certbot - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: certbot_apache2_django-${{ matrix.keylength }}.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - - certbot_nginx_wsgi: - name: "certbot_nginx_wsgi" - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - keylength: [2048, 4096] - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "[ PREPARE ] Build docker-compose (nginx_django)" - working-directory: examples/Docker/ - run: | - sed -i "s/apache2/nginx/g" .env - sudo mkdir -p data - docker network create acme - docker-compose up -d - docker-compose logs - - - name: "[ PREPARE ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "Test http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - cd examples/Docker/ - docker-compose restart - docker-compose logs - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "[ PREPARE ] create letsencrypt folder" - run: | - mkdir certbot - - - name: "[ REGISTER] certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email - - - name: "[ ENROLL ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --rsa-key-size ${{ matrix.keylength }} --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot - sudo chmod 777 certbot/archive/certbot/chain1.pem - sudo cp certbot/archive/certbot/chain1.pem chain1.pem - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < chain1.pem - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem - - - name: "[ RENEW ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --force-renew --rsa-key-size ${{ matrix.keylength }} --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem - - - name: "[ REVOKE ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot revoke --delete-after-revoke --server http://acme-srv -d certbot.acme --cert-name certbot - - - name: "[ ENROLL ] HTTP-01 2x domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --rsa-key-size ${{ matrix.keylength }} --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme -d certbot. --cert-name certbot - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem - - - name: "[ RENEW ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --force-renew --rsa-key-size ${{ matrix.keylength }} --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme -d certbot. --cert-name certbot - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem - - - name: "[ REVOKE ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot revoke --delete-after-revoke --server http://acme-srv -d certbot.acme -d certbot. --cert-name certbot - - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp certbot/ ${{ github.workspace }}/artifact/certbot/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data certbot - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: certbot_nginx_wsgi-${{ matrix.keylength }}.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - - certbot_nginx_django: - name: "certbot_nginx_django" - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - keylength: [2048, 4096] - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "[ PREPARE ] Build docker-compose (nginx_django)" - working-directory: examples/Docker/ - run: | - sed -i "s/wsgi/django/g" .env - sed -i "s/apache2/nginx/g" .env - sudo mkdir -p data - docker network create acme - docker-compose up -d - docker-compose logs - - - name: "[ PREPARE ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "Test http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - sudo cp .github/django_settings.py examples/Docker/data/settings.py - cd examples/Docker/ - docker-compose restart - docker-compose logs - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "[ PREPARE ] create letsencrypt folder" - run: | - mkdir certbot - - - name: "[ REGISTER] certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email - - - name: "[ ENROLL ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --rsa-key-size ${{ matrix.keylength }} --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot - sudo chmod 777 certbot/archive/certbot/chain1.pem - sudo cp certbot/archive/certbot/chain1.pem chain1.pem - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < chain1.pem - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem - - - name: "[ RENEW ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --force-renew --rsa-key-size ${{ matrix.keylength }} --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem - - - name: "[ REVOKE ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot revoke --delete-after-revoke --server http://acme-srv -d certbot.acme --cert-name certbot - - - name: "[ ENROLL ] HTTP-01 2x domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --rsa-key-size ${{ matrix.keylength }} --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme -d certbot. --cert-name certbot - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem - - - name: "[ RENEW ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --force-renew --rsa-key-size ${{ matrix.keylength }} --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme -d certbot. --cert-name certbot - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem - - - name: "[ REVOKE ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot revoke --delete-after-revoke --server http://acme-srv -d certbot.acme -d certbot. --cert-name certbot - - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp certbot/ ${{ github.workspace }}/artifact/certbot/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data certbot - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: certbot_nginx_django-${{ matrix.keylength }}.tar.gz - path: ${{ github.workspace }}/artifact/upload/ diff --git a/.github/workflows/certmanager-application-test.yml b/.github/workflows/certmanager-application-test.yml deleted file mode 100644 index e69815fd..00000000 --- a/.github/workflows/certmanager-application-test.yml +++ /dev/null @@ -1,905 +0,0 @@ -name: Application Tests - cert-manager - -on: - push: - pull_request: - branches: [ devel ] - schedule: - # * is a special character in YAML so you have to quote this string - - cron: '0 2 * * 6' - -jobs: - certmgr_http01_apwsgi: - name: "apache2 wsgi - certmgr http01 challenge tests" - runs-on: ubuntu-latest - steps: - - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "[ PREPARE ] get runner ip" - run: | - echo RUNNER_IP=$(ip addr show eth0 | grep -i "inet " | cut -d ' ' -f 6 | cut -d '/' -f 1) >> $GITHUB_ENV - echo RUNNER_PATH=$(pwd | sed 's_/_\\/_g') >> $GITHUB_ENV - - run: echo "runner IP is ${{ env.RUNNER_IP }}" - - - name: "[ PREPARE ] install microk8s" - run: | - sudo snap install microk8s --classic - sudo microk8s status --wait-ready - sudo microk8s enable helm3 - sudo microk8s enable ingress - - name: "[ PREPARE ] install dnsmasq" - run: | - sudo mkdir -p data - sudo cp .github/dnsmasq.conf data - sudo cp .github/dnsmasq.yml data - sudo chmod -R 777 data/dnsmasq.conf - sudo chmod -R 777 data/dnsmasq.yml - sudo sed -i "s/RUNNER_IP/${{ env.RUNNER_IP }}/g" data/dnsmasq.conf - sudo sed -i "s/RUNNER_PATH/${{ env.RUNNER_PATH }}/g" data/dnsmasq.yml - cat data/dnsmasq.conf - cat data/dnsmasq.yml - docker pull gigantuar/dnsmasq:latest-amd64 - docker save gigantuar/dnsmasq -o dnsmasq.tar - sudo microk8s ctr image import dnsmasq.tar - sudo microk8s ctr images ls | grep -i gigantuar - - name: "[ PREPARE ] deploy dnsmasq pod" - run: | - sudo microk8s.kubectl apply -f data/dnsmasq.yml - - name: "[ WAIT ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "[ CHECK ] check status dnsmasq pod and grab ip" - run: | - sudo microk8s.kubectl get pods -n dnsmasq - sudo microk8s.kubectl -n dnsmasq describe pod dnsmasq - sudo microk8s.kubectl get pods -n dnsmasq | grep -i Running - sudo microk8s.kubectl -n dnsmasq describe pod dnsmasq | grep " IP:" | cut -d ' ' -f 5 - echo DNSMASQ_IP=$(sudo microk8s.kubectl -n dnsmasq describe pod dnsmasq | grep " IP:" | cut -d ' ' -f 5) >> $GITHUB_ENV - - run: echo "dnsmasq pod IP is ${{ env.DNSMASQ_IP }}" - - - name: "[ PREPARE ] change and test dns" - run: | - sudo cp .github/k8s-acme-srv.yml data/ - sudo chmod 777 data/k8s-acme-srv.yml - sudo sed -i "s/DNSMASQ_IP/${{ env.DNSMASQ_IP }}/g" data/k8s-acme-srv.yml - cat data/k8s-acme-srv.yml - host www.bar.local ${{ env.DNSMASQ_IP }} - - - name: "[ PREPARE ] install cert-manager charts" - run: | - sudo microk8s.kubectl create namespace cert-manager - sudo microk8s.helm3 repo add jetstack https://charts.jetstack.io - sudo microk8s.helm3 repo update - sudo microk8s.helm3 install cert-manager jetstack/cert-manager --namespace cert-manager --set installCRDs=true --set podDnsPolicy="None",podDnsConfig.nameservers={${{ env.DNSMASQ_IP }}} - echo CERTMGR_VERSION=$(sudo microk8s.helm3 show chart jetstack/cert-manager | grep version) >> $GITHUB_ENV - - run: echo "cert-manager ${{ env.CERTMGR_VERSION }}" - - - name: "[ PREPARE ] Build docker-compose (apache2_wsgi)" - run: | - cat examples/Docker/apache2/wsgi/Dockerfile | docker build -t grindsa/acme2certifier:devel -f - . --no-cache - # docker pull grindsa/acme2certifier:devel - docker save grindsa/acme2certifier > a2c.tar - sudo microk8s ctr image import a2c.tar - sudo microk8s ctr images ls | grep -i grindsa - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo chmod 777 data - mkdir -p data/acme_ca - sudo cp examples/ca_handler/certifier_ca_handler.py data/ca_handler.py - sudo cp test/ca/certsrv_ca_certs.pem data/acme_ca/ca_certs.pem - sudo touch data/acme_srv.cfg - sudo chmod 777 data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > data/acme_srv.cfg - sudo echo "handler_file: /opt/acme2certifier/examples/ca_handler/certifier_ca_handler.py" >> data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> data/acme_srv.cfg - sudo echo "profile_id: 101" >> data/acme_srv.cfg - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "[ DEPLOY ] deploy a2c pod" - run: | - sudo microk8s.kubectl apply -f data/k8s-acme-srv.yml - sudo microk8s.kubectl get pods -n cert-manager-acme - - name: "[ WAIT ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "[ CHECK ] check status a2c pod and grab ip of a2c pod" - run: | - sudo microk8s.kubectl get pods -n cert-manager-acme - sudo microk8s.kubectl -n cert-manager-acme describe pod acme2certifier - sudo microk8s.kubectl get pods -n cert-manager-acme | grep -i Running - sudo microk8s.kubectl -n cert-manager-acme describe pod acme2certifier | grep " IP:" | cut -d ' ' -f 5 - echo ACME_IP=$(sudo microk8s.kubectl -n cert-manager-acme describe pod acme2certifier | grep " IP:" | cut -d ' ' -f 5) >> $GITHUB_ENV - - run: echo "a2c pod IP is ${{ env.ACME_IP }}" - - - name: "[ DEPLOY ] deploy cert-manager and trigger enrollment" - run: | - sudo cp .github/k8s-cert-mgr-http-01.yml data - sudo chmod -R 777 data/k8s-cert-mgr-http-01.yml - sudo sed -i "s/ACME_SRV/${{ env.ACME_IP }}/g" data/k8s-cert-mgr-http-01.yml - sudo microk8s.kubectl apply -f data/k8s-cert-mgr-http-01.yml - - - name: "[ WAIT ] Sleep for 20s" - uses: juliangruber/sleep-action@v1 - with: - time: 20s - - - name: "[ CHECK ] check issuer and challenge" - run: | - sudo microk8s.kubectl describe ClusterIssuer acme2certifier - sudo microk8s.kubectl describe challenge - - name: "[ WAIT ] Sleep for 20s" - uses: juliangruber/sleep-action@v1 - with: - time: 20s - - - name: "[ CHECK ] check issuer and challenge" - run: | - sudo microk8s.kubectl describe ClusterIssuer acme2certifier - sudo microk8s.kubectl describe challenge - - name: "[ WAIT ] Sleep for 20s" - uses: juliangruber/sleep-action@v1 - with: - time: 20s - - - name: "[ CHECK ] check issuer and challenge" - run: | - sudo microk8s.kubectl describe ClusterIssuer acme2certifier - sudo microk8s.kubectl describe challenge - sudo microk8s.kubectl describe certificate - sudo microk8s.kubectl describe certificates | grep -i "The certificate has been successfully issued" - - name: "[ * ] collecting test logs" - - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp data/ ${{ github.workspace }}/artifact/data/ - sudo microk8s.kubectl logs acme2certifier -n cert-manager-acme > ${{ github.workspace }}/artifact/acme2certifier.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz acme2certifier.log data - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: cert-manager-http-apwsgi.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - - - certmgr_http01_apdjango: - name: "apache2 django - certmgr http01 challenge tests" - runs-on: ubuntu-latest - steps: - - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "[ PREPARE ] get runner ip" - run: | - echo RUNNER_IP=$(ip addr show eth0 | grep -i "inet " | cut -d ' ' -f 6 | cut -d '/' -f 1) >> $GITHUB_ENV - echo RUNNER_PATH=$(pwd | sed 's_/_\\/_g') >> $GITHUB_ENV - - run: echo "runner IP is ${{ env.RUNNER_IP }}" - - - name: "[ PREPARE ] install microk8s" - run: | - sudo snap install microk8s --classic - sudo microk8s status --wait-ready - sudo microk8s enable helm3 - sudo microk8s enable ingress - - - name: "[ PREPARE ] install dnsmasq" - run: | - sudo mkdir -p data - sudo cp .github/dnsmasq.conf data - sudo cp .github/dnsmasq.yml data - sudo chmod -R 777 data/dnsmasq.conf - sudo chmod -R 777 data/dnsmasq.yml - sudo sed -i "s/RUNNER_IP/${{ env.RUNNER_IP }}/g" data/dnsmasq.conf - sudo sed -i "s/RUNNER_PATH/${{ env.RUNNER_PATH }}/g" data/dnsmasq.yml - cat data/dnsmasq.conf - cat data/dnsmasq.yml - docker pull gigantuar/dnsmasq:latest-amd64 - docker save gigantuar/dnsmasq -o dnsmasq.tar - sudo microk8s ctr image import dnsmasq.tar - sudo microk8s ctr images ls | grep -i gigantuar - - name: "[ PREPARE ] deploy dnsmasq pod" - run: | - sudo microk8s.kubectl apply -f data/dnsmasq.yml - - name: "[ WAIT ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "[ CHECK ] check status dnsmasq pod and grab ip" - run: | - sudo microk8s.kubectl get pods -n dnsmasq - sudo microk8s.kubectl -n dnsmasq describe pod dnsmasq - sudo microk8s.kubectl get pods -n dnsmasq | grep -i Running - sudo microk8s.kubectl -n dnsmasq describe pod dnsmasq | grep " IP:" | cut -d ' ' -f 5 - echo DNSMASQ_IP=$(sudo microk8s.kubectl -n dnsmasq describe pod dnsmasq | grep " IP:" | cut -d ' ' -f 5) >> $GITHUB_ENV - - run: echo "dnsmasq pod IP is ${{ env.DNSMASQ_IP }}" - - - name: "[ PREPARE ] change and test dns" - run: | - sudo cp .github/k8s-acme-srv.yml data/ - sudo chmod 777 data/k8s-acme-srv.yml - sudo sed -i "s/DNSMASQ_IP/${{ env.DNSMASQ_IP }}/g" data/k8s-acme-srv.yml - cat data/k8s-acme-srv.yml - host www.bar.local ${{ env.DNSMASQ_IP }} - - - name: "[ PREPARE ] install cert-manager charts" - run: | - sudo microk8s.kubectl create namespace cert-manager - sudo microk8s.helm3 repo add jetstack https://charts.jetstack.io - sudo microk8s.helm3 repo update - sudo microk8s.helm3 install cert-manager jetstack/cert-manager --namespace cert-manager --set installCRDs=true --set podDnsPolicy="None",podDnsConfig.nameservers={${{ env.DNSMASQ_IP }}} - echo CERTMGR_VERSION=$(sudo microk8s.helm3 show chart jetstack/cert-manager | grep version) >> $GITHUB_ENV - - run: echo "cert-manager ${{ env.CERTMGR_VERSION }}" - - - name: "[ PREPARE ] Build docker-compose (apache2_django)" - run: | - cat examples/Docker/apache2/django/Dockerfile | docker build -t grindsa/acme2certifier:devel -f - . --no-cache - docker save grindsa/acme2certifier > a2c.tar - sudo microk8s ctr image import a2c.tar - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo chmod 777 data - mkdir -p data/acme_ca - sudo cp examples/ca_handler/certifier_ca_handler.py data/ca_handler.py - sudo cp test/ca/certsrv_ca_certs.pem data/acme_ca/ca_certs.pem - sudo touch data/acme_srv.cfg - sudo chmod 777 data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > data/acme_srv.cfg - sudo echo "handler_file: /opt/acme2certifier/examples/ca_handler/certifier_ca_handler.py" >> data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> data/acme_srv.cfg - sudo echo "profile_id: 101" >> data/acme_srv.cfg - sudo cp .github/django_settings.py data/settings.py - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "[ DEPLOY ] deploy a2c pod" - run: | - sudo microk8s.kubectl apply -f data/k8s-acme-srv.yml - sudo microk8s.kubectl get pods -n cert-manager-acme - - - name: "[ WAIT ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "[ CHECK ] check status a2c pod and grab ip of a2c pod" - run: | - sudo microk8s.kubectl get pods -n cert-manager-acme - sudo microk8s.kubectl -n cert-manager-acme describe pod acme2certifier - sudo microk8s.kubectl get pods -n cert-manager-acme | grep -i Running - sudo microk8s.kubectl -n cert-manager-acme describe pod acme2certifier | grep " IP:" | cut -d ' ' -f 5 - echo ACME_IP=$(sudo microk8s.kubectl -n cert-manager-acme describe pod acme2certifier | grep " IP:" | cut -d ' ' -f 5) >> $GITHUB_ENV - - run: echo "a2c pod IP is ${{ env.ACME_IP }}" - - - name: "[ DEPLOY ] deploy cert-manager and trigger enrollment" - run: | - sudo cp .github/k8s-cert-mgr-http-01.yml data - sudo chmod -R 777 data/k8s-cert-mgr-http-01.yml - sudo sed -i "s/ACME_SRV/${{ env.ACME_IP }}/g" data/k8s-cert-mgr-http-01.yml - sudo microk8s.kubectl apply -f data/k8s-cert-mgr-http-01.yml - - - name: "[ WAIT ] Sleep for 20s" - uses: juliangruber/sleep-action@v1 - with: - time: 20s - - - name: "[ CHECK ] check issuer and challenge" - run: | - sudo microk8s.kubectl describe ClusterIssuer acme2certifier - sudo microk8s.kubectl describe challenge - - name: "[ WAIT ] Sleep for 20s" - uses: juliangruber/sleep-action@v1 - with: - time: 20s - - - name: "[ CHECK ] check issuer and challenge" - run: | - sudo microk8s.kubectl describe ClusterIssuer acme2certifier - sudo microk8s.kubectl describe challenge - - name: "[ WAIT ] Sleep for 20s" - uses: juliangruber/sleep-action@v1 - with: - time: 20s - - - name: "[ CHECK ] check issuer and challenge" - run: | - sudo microk8s.kubectl describe ClusterIssuer acme2certifier - sudo microk8s.kubectl describe challenge - sudo microk8s.kubectl describe certificate - sudo microk8s.kubectl describe certificates | grep -i "The certificate has been successfully issued" - - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp data/ ${{ github.workspace }}/artifact/data/ - sudo microk8s.kubectl logs acme2certifier -n cert-manager-acme > ${{ github.workspace }}/artifact/acme2certifier.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz acme2certifier.log data - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: cert-manager-http-apdjango.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - - certmgr_http01_nginxwsgi: - name: "nginx wsgi - certmgr http01 challenge tests" - runs-on: ubuntu-latest - steps: - - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "[ PREPARE ] get runner ip" - run: | - echo RUNNER_IP=$(ip addr show eth0 | grep -i "inet " | cut -d ' ' -f 6 | cut -d '/' -f 1) >> $GITHUB_ENV - echo RUNNER_PATH=$(pwd | sed 's_/_\\/_g') >> $GITHUB_ENV - - run: echo "runner IP is ${{ env.RUNNER_IP }}" - - - name: "[ PREPARE ] install microk8s" - run: | - sudo snap install microk8s --classic - sudo microk8s status --wait-ready - sudo microk8s enable helm3 - sudo microk8s enable ingress - - name: "[ PREPARE ] install dnsmasq" - run: | - sudo mkdir -p data - sudo cp .github/dnsmasq.conf data - sudo cp .github/dnsmasq.yml data - sudo chmod -R 777 data/dnsmasq.conf - sudo chmod -R 777 data/dnsmasq.yml - sudo sed -i "s/RUNNER_IP/${{ env.RUNNER_IP }}/g" data/dnsmasq.conf - sudo sed -i "s/RUNNER_PATH/${{ env.RUNNER_PATH }}/g" data/dnsmasq.yml - cat data/dnsmasq.conf - cat data/dnsmasq.yml - docker pull gigantuar/dnsmasq:latest-amd64 - docker save gigantuar/dnsmasq -o dnsmasq.tar - sudo microk8s ctr image import dnsmasq.tar - sudo microk8s ctr images ls | grep -i gigantuar - - name: "[ PREPARE ] deploy dnsmasq pod" - run: | - sudo microk8s.kubectl apply -f data/dnsmasq.yml - - - name: "[ WAIT ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "[ CHECK ] check status dnsmasq pod and grab ip" - run: | - sudo microk8s.kubectl get pods -n dnsmasq - sudo microk8s.kubectl -n dnsmasq describe pod dnsmasq - sudo microk8s.kubectl get pods -n dnsmasq | grep -i Running - sudo microk8s.kubectl -n dnsmasq describe pod dnsmasq | grep " IP:" | cut -d ' ' -f 5 - echo DNSMASQ_IP=$(sudo microk8s.kubectl -n dnsmasq describe pod dnsmasq | grep " IP:" | cut -d ' ' -f 5) >> $GITHUB_ENV - - run: echo "dnsmasq pod IP is ${{ env.DNSMASQ_IP }}" - - - name: "[ PREPARE ] change and test dns" - run: | - sudo cp .github/k8s-acme-srv.yml data/ - sudo chmod 777 data/k8s-acme-srv.yml - sudo sed -i "s/DNSMASQ_IP/${{ env.DNSMASQ_IP }}/g" data/k8s-acme-srv.yml - cat data/k8s-acme-srv.yml - host www.bar.local ${{ env.DNSMASQ_IP }} - - - name: "[ PREPARE ] install cert-manager charts" - run: | - sudo microk8s.kubectl create namespace cert-manager - sudo microk8s.helm3 repo add jetstack https://charts.jetstack.io - sudo microk8s.helm3 repo update - sudo microk8s.helm3 install cert-manager jetstack/cert-manager --namespace cert-manager --set installCRDs=true --set podDnsPolicy="None",podDnsConfig.nameservers={${{ env.DNSMASQ_IP }}} - echo CERTMGR_VERSION=$(sudo microk8s.helm3 show chart jetstack/cert-manager | grep version) >> $GITHUB_ENV - - run: echo "cert-manager ${{ env.CERTMGR_VERSION }}" - - - name: "[ PREPARE ] Build docker-compose (nginx_wsgi)" - run: | - cat examples/Docker/nginx/wsgi/Dockerfile | docker build -t grindsa/acme2certifier:devel -f - . --no-cache - # docker pull grindsa/acme2certifier:devel - docker save grindsa/acme2certifier > a2c.tar - sudo microk8s ctr image import a2c.tar - sudo microk8s ctr images ls | grep -i grindsa - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo chmod 777 data - mkdir -p data/acme_ca - sudo cp examples/ca_handler/certifier_ca_handler.py data/ca_handler.py - sudo cp test/ca/certsrv_ca_certs.pem data/acme_ca/ca_certs.pem - sudo touch data/acme_srv.cfg - sudo chmod 777 data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > data/acme_srv.cfg - sudo echo "handler_file: /opt/acme2certifier/examples/ca_handler/certifier_ca_handler.py" >> data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> data/acme_srv.cfg - sudo echo "profile_id: 101" >> data/acme_srv.cfg - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "[ DEPLOY ] deploy a2c pod" - run: | - sudo microk8s.kubectl apply -f data/k8s-acme-srv.yml - sudo microk8s.kubectl get pods -n cert-manager-acme - - name: "[ WAIT ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "[ CHECK ] check status a2c pod and grab ip of a2c pod" - run: | - sudo microk8s.kubectl get pods -n cert-manager-acme - sudo microk8s.kubectl -n cert-manager-acme describe pod acme2certifier - sudo microk8s.kubectl get pods -n cert-manager-acme | grep -i Running - sudo microk8s.kubectl -n cert-manager-acme describe pod acme2certifier | grep " IP:" | cut -d ' ' -f 5 - echo ACME_IP=$(sudo microk8s.kubectl -n cert-manager-acme describe pod acme2certifier | grep " IP:" | cut -d ' ' -f 5) >> $GITHUB_ENV - - - run: echo "a2c pod IP is ${{ env.ACME_IP }}" - - - name: "[ DEPLOY ] deploy cert-manager and trigger enrollment" - run: | - sudo cp .github/k8s-cert-mgr-http-01.yml data - sudo chmod -R 777 data/k8s-cert-mgr-http-01.yml - sudo sed -i "s/ACME_SRV/${{ env.ACME_IP }}/g" data/k8s-cert-mgr-http-01.yml - sudo microk8s.kubectl apply -f data/k8s-cert-mgr-http-01.yml - - name: "[ WAIT ] Sleep for 20s" - uses: juliangruber/sleep-action@v1 - with: - time: 20s - - - name: "[ CHECK ] check issuer and challenge" - run: | - sudo microk8s.kubectl describe ClusterIssuer acme2certifier - sudo microk8s.kubectl describe challenge - - name: "[ WAIT ] Sleep for 20s" - uses: juliangruber/sleep-action@v1 - with: - time: 20s - - - name: "[ CHECK ] check issuer and challenge" - run: | - sudo microk8s.kubectl describe ClusterIssuer acme2certifier - sudo microk8s.kubectl describe challenge - - name: "[ WAIT ] Sleep for 20s" - uses: juliangruber/sleep-action@v1 - with: - time: 20s - - - name: "[ CHECK ] check issuer and challenge" - run: | - sudo microk8s.kubectl describe ClusterIssuer acme2certifier - sudo microk8s.kubectl describe challenge - sudo microk8s.kubectl describe certificate - sudo microk8s.kubectl describe certificates | grep -i "The certificate has been successfully issued" - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp data/ ${{ github.workspace }}/artifact/data/ - sudo microk8s.kubectl logs acme2certifier -n cert-manager-acme > ${{ github.workspace }}/artifact/acme2certifier.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz acme2certifier.log data - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: cert-manager-http-nginxwsgi.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - - certmgr_http01_nginxdjango: - name: "nginx wsgi - certmgr http01 challenge tests" - runs-on: ubuntu-latest - steps: - - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "[ PREPARE ] get runner ip" - run: | - echo RUNNER_IP=$(ip addr show eth0 | grep -i "inet " | cut -d ' ' -f 6 | cut -d '/' -f 1) >> $GITHUB_ENV - echo RUNNER_PATH=$(pwd | sed 's_/_\\/_g') >> $GITHUB_ENV - - run: echo "runner IP is ${{ env.RUNNER_IP }}" - - - name: "[ PREPARE ] install microk8s" - run: | - sudo snap install microk8s --classic - sudo microk8s status --wait-ready - sudo microk8s enable helm3 - sudo microk8s enable ingress - - - name: "[ PREPARE ] install dnsmasq" - run: | - sudo mkdir -p data - sudo cp .github/dnsmasq.conf data - sudo cp .github/dnsmasq.yml data - sudo chmod -R 777 data/dnsmasq.conf - sudo chmod -R 777 data/dnsmasq.yml - sudo sed -i "s/RUNNER_IP/${{ env.RUNNER_IP }}/g" data/dnsmasq.conf - sudo sed -i "s/RUNNER_PATH/${{ env.RUNNER_PATH }}/g" data/dnsmasq.yml - cat data/dnsmasq.conf - cat data/dnsmasq.yml - docker pull gigantuar/dnsmasq:latest-amd64 - docker save gigantuar/dnsmasq -o dnsmasq.tar - sudo microk8s ctr image import dnsmasq.tar - sudo microk8s ctr images ls | grep -i gigantuar - - - name: "[ PREPARE ] deploy dnsmasq pod" - run: | - sudo microk8s.kubectl apply -f data/dnsmasq.yml - - - name: "[ WAIT ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "[ CHECK ] check status dnsmasq pod and grab ip" - run: | - sudo microk8s.kubectl get pods -n dnsmasq - sudo microk8s.kubectl -n dnsmasq describe pod dnsmasq - sudo microk8s.kubectl get pods -n dnsmasq | grep -i Running - sudo microk8s.kubectl -n dnsmasq describe pod dnsmasq | grep " IP:" | cut -d ' ' -f 5 - echo DNSMASQ_IP=$(sudo microk8s.kubectl -n dnsmasq describe pod dnsmasq | grep " IP:" | cut -d ' ' -f 5) >> $GITHUB_ENV - - run: echo "dnsmasq pod IP is ${{ env.DNSMASQ_IP }}" - - - name: "[ PREPARE ] change and test dns" - run: | - sudo cp .github/k8s-acme-srv.yml data/ - sudo chmod 777 data/k8s-acme-srv.yml - sudo sed -i "s/DNSMASQ_IP/${{ env.DNSMASQ_IP }}/g" data/k8s-acme-srv.yml - cat data/k8s-acme-srv.yml - host www.bar.local ${{ env.DNSMASQ_IP }} - - - name: "[ PREPARE ] install cert-manager charts" - run: | - sudo microk8s.kubectl create namespace cert-manager - sudo microk8s.helm3 repo add jetstack https://charts.jetstack.io - sudo microk8s.helm3 repo update - sudo microk8s.helm3 install cert-manager jetstack/cert-manager --namespace cert-manager --set installCRDs=true --set podDnsPolicy="None",podDnsConfig.nameservers={${{ env.DNSMASQ_IP }}} - echo CERTMGR_VERSION=$(sudo microk8s.helm3 show chart jetstack/cert-manager | grep version) >> $GITHUB_ENV - - run: echo "cert-manager ${{ env.CERTMGR_VERSION }}" - - - name: "[ PREPARE ] Build docker-compose (nginx_django)" - run: | - cat examples/Docker/nginx/django/Dockerfile | docker build -t grindsa/acme2certifier:devel -f - . --no-cache - # docker pull grindsa/acme2certifier:devel - docker save grindsa/acme2certifier > a2c.tar - sudo microk8s ctr image import a2c.tar - sudo microk8s ctr images ls | grep -i grindsa - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo chmod 777 data - mkdir -p data/acme_ca - sudo cp examples/ca_handler/certifier_ca_handler.py data/ca_handler.py - sudo cp test/ca/certsrv_ca_certs.pem data/acme_ca/ca_certs.pem - sudo touch data/acme_srv.cfg - sudo chmod 777 data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > data/acme_srv.cfg - sudo echo "handler_file: /opt/acme2certifier/examples/ca_handler/certifier_ca_handler.py" >> data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> data/acme_srv.cfg - sudo echo "profile_id: 101" >> data/acme_srv.cfg - sudo cp .github/django_settings.py data/settings.py - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "[ DEPLOY ] deploy a2c pod" - run: | - sudo microk8s.kubectl apply -f data/k8s-acme-srv.yml - sudo microk8s.kubectl get pods -n cert-manager-acme - - - name: "[ WAIT ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "[ CHECK ] check status a2c pod and grab ip of a2c pod" - run: | - sudo microk8s.kubectl get pods -n cert-manager-acme - sudo microk8s.kubectl -n cert-manager-acme describe pod acme2certifier - sudo microk8s.kubectl get pods -n cert-manager-acme | grep -i Running - sudo microk8s.kubectl -n cert-manager-acme describe pod acme2certifier | grep " IP:" | cut -d ' ' -f 5 - echo ACME_IP=$(sudo microk8s.kubectl -n cert-manager-acme describe pod acme2certifier | grep " IP:" | cut -d ' ' -f 5) >> $GITHUB_ENV - - run: echo "a2c pod IP is ${{ env.ACME_IP }}" - - - name: "[ DEPLOY ] deploy cert-manager and trigger enrollment" - run: | - sudo cp .github/k8s-cert-mgr-http-01.yml data - sudo chmod -R 777 data/k8s-cert-mgr-http-01.yml - sudo sed -i "s/ACME_SRV/${{ env.ACME_IP }}/g" data/k8s-cert-mgr-http-01.yml - sudo microk8s.kubectl apply -f data/k8s-cert-mgr-http-01.yml - - - name: "[ WAIT ] Sleep for 20s" - uses: juliangruber/sleep-action@v1 - with: - time: 20s - - - name: "[ CHECK ] check issuer and challenge" - run: | - sudo microk8s.kubectl describe ClusterIssuer acme2certifier - sudo microk8s.kubectl describe challenge - - - name: "[ WAIT ] Sleep for 20s" - uses: juliangruber/sleep-action@v1 - with: - time: 20s - - - name: "[ CHECK ] check issuer and challenge" - run: | - sudo microk8s.kubectl describe ClusterIssuer acme2certifier - sudo microk8s.kubectl describe challenge - - name: "[ WAIT ] Sleep for 20s" - uses: juliangruber/sleep-action@v1 - with: - time: 20s - - - name: "[ CHECK ] check issuer and challenge" - run: | - sudo microk8s.kubectl describe ClusterIssuer acme2certifier - sudo microk8s.kubectl describe challenge - sudo microk8s.kubectl describe certificate - sudo microk8s.kubectl describe certificates | grep -i "The certificate has been successfully issued" - - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp data/ ${{ github.workspace }}/artifact/data/ - sudo microk8s.kubectl logs acme2certifier -n cert-manager-acme > ${{ github.workspace }}/artifact/acme2certifier.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz acme2certifier.log data - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: cert-manager-http-nginxdjango.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - - certmgr_dns01_apwsgi: - name: "apache2 wsgi - certmgr dns01 challenge tests" - runs-on: ubuntu-latest - steps: - - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "[ PREPARE ] change dns" - run: | - sudo mkdir -p data - sudo systemctl disable systemd-resolved - sudo systemctl stop systemd-resolved - sudo chmod -R 777 /etc/resolv.conf - sudo echo "nameserver 8.8.8.8" > /etc/resolv.conf - sudo cat /etc/resolv.conf - sudo cp .github/k8s-acme-srv.yml data/ - sudo chmod 777 data/k8s-acme-srv.yml - sudo sed -i "s/DNSMASQ_IP/8.8.8.8/g" data/k8s-acme-srv.yml - cat data/k8s-acme-srv.yml - - - name: "[ PREPARE ] install microk8s" - run: | - sudo snap install microk8s --classic - sudo microk8s status --wait-ready - sudo microk8s enable helm3 - - - name: "[ PREPARE ] install cert-manager charts" - run: | - sudo microk8s.kubectl create namespace cert-manager - sudo microk8s.helm3 repo add jetstack https://charts.jetstack.io - sudo microk8s.helm3 repo update - sudo microk8s.helm3 install \ - cert-manager jetstack/cert-manager \ - --namespace cert-manager \ - --set installCRDs=true - echo CERTMGR_VERSION=$(sudo microk8s.helm3 show chart jetstack/cert-manager | grep version) >> $GITHUB_ENV - - run: echo "cert-manager ${{ env.CERTMGR_VERSION }}" - - - name: "[ PREPARE ] Build docker-compose (apache2_wsgi)" - run: | - cat examples/Docker/apache2/wsgi/Dockerfile | docker build -t grindsa/acme2certifier:devel -f - . --no-cache - # docker pull grindsa/acme2certifier:devel - docker save grindsa/acme2certifier > a2c.tar - sudo microk8s ctr image import a2c.tar - sudo microk8s ctr images ls | grep -i grindsa - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo chmod 777 data - mkdir -p data/acme_ca - sudo cp examples/ca_handler/certifier_ca_handler.py data/ca_handler.py - sudo cp test/ca/certsrv_ca_certs.pem data/acme_ca/ca_certs.pem - sudo touch data/acme_srv.cfg - sudo chmod 777 data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > data/acme_srv.cfg - sudo echo "handler_file: /opt/acme2certifier/examples/ca_handler/certifier_ca_handler.py" >> data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> data/acme_srv.cfg - sudo echo "profile_id: 101" >> data/acme_srv.cfg - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "[ DEPLOY ] deploy a2c pod" - run: | - sudo microk8s.kubectl apply -f data/k8s-acme-srv.yml - sudo microk8s.kubectl get pods -n cert-manager-acme - - - name: "[ WAIT ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "[ CHECK ] check status a2c pod and grab ip of a2c pod" - run: | - sudo microk8s.kubectl get pods -n cert-manager-acme - sudo microk8s.kubectl -n cert-manager-acme describe pod acme2certifier - sudo microk8s.kubectl get pods -n cert-manager-acme | grep -i Running - sudo microk8s.kubectl -n cert-manager-acme describe pod acme2certifier | grep " IP:" | cut -d ' ' -f 5 - echo ACME_IP=$(sudo microk8s.kubectl -n cert-manager-acme describe pod acme2certifier | grep " IP:" | cut -d ' ' -f 5) >> $GITHUB_ENV - - run: echo "a2c pod IP is ${{ env.ACME_IP }}" - - - name: "[ DEPLOY ] deploy cert-manager" - run: | - sudo cp .github/k8s-cert-mgr-dns-01.yml data - sudo chmod -R 777 data/k8s-cert-mgr-dns-01.yml - sudo sed -i "s/ACME_SRV/${{ env.ACME_IP }}/g" data/k8s-cert-mgr-dns-01.yml - sudo sed -i "s/CF_TOKEN/${{ secrets.CF_TOKEN }}/g" data/k8s-cert-mgr-dns-01.yml - sudo sed -i "s/MY_EMAIL/${{ secrets.EMAIL }}/g" data/k8s-cert-mgr-dns-01.yml - - - name: "[ DEPLOY ] deploy cert-manager and trigger enrollment" - run: | - sudo microk8s.kubectl apply -f data/k8s-cert-mgr-dns-01.yml - - - name: "[ WAIT ] Sleep for 20s" - uses: juliangruber/sleep-action@v1 - with: - time: 20s - - - name: "[ CHECK ] check issuer and challenge" - run: | - sudo microk8s.kubectl describe issuer acme2certifier -n cert-manager-acme - sudo microk8s.kubectl describe challenge -n cert-manager-acme - - - name: "[ WAIT ] Sleep for 30s" - uses: juliangruber/sleep-action@v1 - with: - time: 60s - - - name: "[ CHECK ] check issuer and challenge" - run: | - sudo microk8s.kubectl describe issuer acme2certifier -n cert-manager-acme - sudo microk8s.kubectl describe challenge -n cert-manager-acme - - - name: "[ WAIT ] Sleep for 60s" - uses: juliangruber/sleep-action@v1 - with: - time: 60s - - - name: "[ CHECK ] check issuer and challenge" - run: | - sudo microk8s.kubectl describe issuer acme2certifier -n cert-manager-acme - sudo microk8s.kubectl describe challenge -n cert-manager-acme - - - name: "[ WAIT ] Sleep for 60s" - uses: juliangruber/sleep-action@v1 - with: - time: 60s - - - name: "[ CHECK ] check challenge and certificate" - run: | - sudo microk8s.kubectl describe challenge -n cert-manager-acme - sudo microk8s.kubectl describe certificates acme-cert -n cert-manager-acme - sudo microk8s.kubectl describe certificates acme-cert -n cert-manager-acme | grep -i "The certificate has been successfully issued" - - - name: "[ PREPARE ] reconfigure YAML to wildcard domain" - run: | - sudo microk8s.kubectl delete -f data/k8s-cert-mgr-dns-01.yml - sudo sed -i "s/commonName: k8.acme.dynamop.de/commonName: '*.acme.dynamop.de'/g" data/k8s-cert-mgr-dns-01.yml - sudo sed -i "s/- k8.acme.dynamop.de/- '*.acme.dynamop.de'/g" data/k8s-cert-mgr-dns-01.yml - - - name: "[ DEPLOY ] deploy cert-manager and trigger enrollment" - run: | - sudo microk8s.kubectl apply -f data/k8s-cert-mgr-dns-01.yml - - - name: "[ WAIT ] Sleep for 20s" - uses: juliangruber/sleep-action@v1 - with: - time: 20s - - - name: "[ CHECK ] check issuer and challenge" - run: | - sudo microk8s.kubectl describe issuer acme2certifier -n cert-manager-acme - sudo microk8s.kubectl describe challenge -n cert-manager-acme - - name: "[ WAIT ] Sleep for 30s" - uses: juliangruber/sleep-action@v1 - with: - time: 60s - - - name: "[ CHECK ] check issuer and challenge" - run: | - sudo microk8s.kubectl describe issuer acme2certifier -n cert-manager-acme - sudo microk8s.kubectl describe challenge -n cert-manager-acme - - - name: "[ WAIT ] Sleep for 60s" - uses: juliangruber/sleep-action@v1 - with: - time: 60s - - - name: "[ CHECK ] check issuer and challenge" - run: | - sudo microk8s.kubectl describe issuer acme2certifier -n cert-manager-acme - sudo microk8s.kubectl describe challenge -n cert-manager-acme - - - name: "[ WAIT ] Sleep for 60s" - uses: juliangruber/sleep-action@v1 - with: - time: 60s - - - name: "[ CHECK ] check challenge and certificate" - run: | - sudo microk8s.kubectl describe challenge -n cert-manager-acme - sudo microk8s.kubectl describe certificates acme-cert -n cert-manager-acme - sudo microk8s.kubectl describe certificates acme-cert -n cert-manager-acme | grep -i "The certificate has been successfully issued" - - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp data/ ${{ github.workspace }}/artifact/data/ - sudo microk8s.kubectl logs acme2certifier -n cert-manager-acme > ${{ github.workspace }}/artifact/acme2certifier.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz acme2certifier.log data - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: cert-manager-dns-apwsgi.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - diff --git a/.github/workflows/codescanner.yml b/.github/workflows/codescanner.yml index d4fdd893..91e9748a 100644 --- a/.github/workflows/codescanner.yml +++ b/.github/workflows/codescanner.yml @@ -4,27 +4,67 @@ on: branches: - 'master' - 'devel' - - 'min' - 'min-devel' + - 'min' + - 'code-scanner_wf' + jobs: + + bandit: + permissions: + contents: read # for actions/checkout to fetch code + security-events: write # for github/codeql-action/upload-sarif to upload SARIF results + actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status + + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Bandit Scan + uses: shundor/python-bandit-scan@9cc5aa4a006482b8a7f91134412df6772dbda22c + with: # optional arguments + # exit with 0, even with results found + exit_zero: true # optional, default is DEFAULT + # Github token of the repository (automatically created by Github) + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information. + # File or directory to run bandit on + # path: # optional, default is . + # Report only issues of a given severity level or higher. Can be LOW, MEDIUM or HIGH. Default is UNDEFINED (everything) + # level: # optional, default is UNDEFINED + # Report only issues of a given confidence level or higher. Can be LOW, MEDIUM or HIGH. Default is UNDEFINED (everything) + # confidence: # optional, default is UNDEFINED + # comma-separated list of paths (glob patterns supported) to exclude from scan (note that these are in addition to the excluded paths provided in the config file) (default: .svn,CVS,.bzr,.hg,.git,__pycache__,.tox,.eggs,*.egg) + # excluded_paths: # optional, default is DEFAULT + # comma-separated list of test IDs to skip + # skips: # optional, default is DEFAULT + # path to a .bandit file that supplies command line arguments + # ini_path: # optional, default is DEFAULT + codecov: name: Codecov Analysis runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@master with: python-version: 3.9 + + - name: Install components + run: | + sudo DEBIAN_FRONTEND="noninteractive" apt-get install --no-install-recommends -y \ + libkrb5-dev \ + python3-gssapi \ + - name: Generate coverage report run: | python -m pip install --upgrade pip pip install lxml beautifulsoup4 html5lib pip install pytest - pip install pytest-cov + pip install pytest-cov impacket if [ -f requirements.txt ]; then pip install -r requirements.txt; fi pytest --cov=./ --cov-report=xml + - name: Upload coverage to Codecov uses: codecov/codecov-action@v3 with: @@ -36,7 +76,7 @@ jobs: name: SonarCloud Analysis runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis @@ -45,10 +85,16 @@ jobs: with: python-version: '3.x' + - name: Install components + run: | + sudo DEBIAN_FRONTEND="noninteractive" apt-get install --no-install-recommends -y \ + libkrb5-dev \ + python3-gssapi \ + - name: Install pytest coverage and any other packages run: | python -m pip install --upgrade pip - pip install pytest coverage + pip install pytest coverage impacket if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - name: run coverage @@ -68,7 +114,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: # We must fetch at least the immediate parents so that if this is # a pull request then we can checkout the head. @@ -77,7 +123,7 @@ jobs: # If this run was triggered by a pull request event, then checkout # the head of the pull request instead of the merge commit. - run: git checkout HEAD^2 - if: ${{ github.event_name == 'pull_request' }} + if: github.event_name == 'pull_request' # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL @@ -113,7 +159,7 @@ jobs: # steps: # # Checkout your code repository to scan # - name: Checkout repository - # uses: actions/checkout@v3 + # uses: actions/checkout@v4 # with: # We must fetch at least the immediate parents so that if this is # a pull request then we can checkout the head. diff --git a/.github/workflows/container-tests.yml b/.github/workflows/container-tests.yml deleted file mode 100644 index c39b3d56..00000000 --- a/.github/workflows/container-tests.yml +++ /dev/null @@ -1,350 +0,0 @@ -name: Container Deployment Tests - -on: - push: - pull_request: - branches: [ devel ] - schedule: - # * is a special character in YAML so you have to quote this string - - cron: '0 2 * * 6' - -jobs: - docker-compose_apache2_wsgi: - name: "Docker compose - apache2 wsgi" - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: "Build the stack" - working-directory: examples/Docker/ - run: | - sudo mkdir -p data - docker network create acme - docker-compose up -d - docker-compose logs - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - sudo cp .github/acme2certifier.pem examples/Docker/data/acme2certifier.pem - cd examples/Docker/ - docker-compose restart - docker-compose logs - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - - name: "Test if http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - name: "Test if https://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory - - name: "[ PREPARE ] prepare acme.sh container" - run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - name: "[ ENROLL ] register via http" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --debug 2 - - name: "[ ENROLL ] register via https" - run: | - docker exec -i acme-sh acme.sh --server https://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --insecure --debug 2 - - name: "[ PREPARE ] test ca_handler_migration" - run: | - sudo cp .github/openssl_ca_handler_v16.py examples/Docker/data/ca_handler.py - cd examples/Docker/ - docker-compose restart - head -n 13 data/ca_handler.py - docker-compose logs - - name: "[ PREPARE ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - name: "Test if http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - name: "[ ENROLL ] enroll certificate to verify handler migration" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --debug --output-insecure - - name: "[ * ] collecting test data" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data acme_sh - - name: "[ * ] uploading artifacts" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: docker-compose_apache2_wsgi.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - - docker-compose_nginx_wsgi: - name: "Docker compose - nginx wsgi" - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: "Build the stack" - working-directory: examples/Docker/ - run: | - sed -i "s/apache2/nginx/g" .env - sudo mkdir -p data - docker network create acme - docker-compose up -d - docker-compose logs - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - sudo cp .github/acme2certifier_cert.pem examples/Docker/data/acme2certifier_cert.pem - sudo cp .github/acme2certifier_key.pem examples/Docker/data/acme2certifier_key.pem - cd examples/Docker/ - docker-compose restart - docker-compose logs - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "[ PREPARE ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - name: "Test if http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - name: "Test if https://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory - - name: "[ PREPARE ] prepare acme.sh container" - run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - name: "[ ENROLL ] register via http" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --debug 2 - - name: "[ ENROLL ] register via https" - run: | - docker exec -i acme-sh acme.sh --server https://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --insecure --debug 2 - - name: "[ PREPARE ] test ca_handler_migration" - run: | - sudo cp .github/openssl_ca_handler_v16.py examples/Docker/data/ca_handler.py - cd examples/Docker/ - docker-compose restart - head -n 13 data/ca_handler.py - docker-compose logs - - name: "[ PREPARE ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - name: "Test if http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - name: "[ ENROLL ] enroll certificate to verify handler migration" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --debug --output-insecure - - name: "[ * ] collecting test data" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data acme_sh - - name: "[ * ] uploading artifacts" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: docker-compose_nginx_wsgi.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - - docker-compose_apache2_django: - name: "Docker compose - apache2 django" - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: "Build the stack" - working-directory: examples/Docker/ - run: | - sed -i "s/wsgi/django/g" .env - sudo mkdir -p data - docker network create acme - docker-compose up -d - docker-compose logs - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - sudo cp .github/acme2certifier.pem examples/Docker/data/acme2certifier.pem - sudo cp .github/django_settings.py examples/Docker/data/settings.py - cd examples/Docker/ - docker-compose restart - docker-compose logs - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "[ PREPARE ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - name: "Test if http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - name: "Test if https://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory - - name: "[ PREPARE ] prepare acme.sh container" - run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - name: "[ ENROLL ] register via http" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --debug 2 - - name: "[ ENROLL ] register via https" - run: | - docker exec -i acme-sh acme.sh --server https://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --insecure --debug 2 - - name: "[ PREPARE ] test ca_handler_migration" - run: | - sudo cp .github/openssl_ca_handler_v16.py examples/Docker/data/ca_handler.py - cd examples/Docker/ - docker-compose restart - head -n 13 data/ca_handler.py - docker-compose logs - - name: "[ PREPARE ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - name: "Test if http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - name: "[ ENROLL ] enroll certificate to verify handler migration" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --debug --output-insecure - - name: "[ * ] collecting test data" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data acme_sh - - name: "[ * ] uploading artifacts" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: docker-compose_apache2_django.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - docker-compose_nginx_django: - name: "Docker compose - nginx django" - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: "Build the stack" - working-directory: examples/Docker/ - run: | - sed -i "s/wsgi/django/g" .env - sed -i "s/apache2/nginx/g" .env - sudo mkdir -p data - docker network create acme - docker-compose up -d - docker-compose logs - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - sudo cp .github/django_settings.py examples/Docker/data/settings.py - sudo cp .github/acme2certifier_cert.pem examples/Docker/data/acme2certifier_cert.pem - sudo cp .github/acme2certifier_key.pem examples/Docker/data/acme2certifier_key.pem - cd examples/Docker/ - docker-compose restart - docker-compose logs - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "[ PREPARE ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - name: "Test if http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - name: "Test if https://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory - - name: "[ PREPARE ] prepare acme.sh container" - run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - name: "[ ENROLL ] register via http" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --debug 2 - - name: "[ ENROLL ] register via https" - run: | - docker exec -i acme-sh acme.sh --server https://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --insecure --debug 2 - - name: "[ PREPARE ] test ca_handler_migration" - run: | - sudo cp .github/openssl_ca_handler_v16.py examples/Docker/data/ca_handler.py - cd examples/Docker/ - docker-compose restart - head -n 13 data/ca_handler.py - docker-compose logs - - name: "[ PREPARE ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - name: "Test if http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - name: "[ ENROLL ] enroll certificate to verify handler migration" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --debug --output-insecure - - name: "[ * ] collecting test data" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data acme_sh - - name: "[ * ] uploading artifacts" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: docker-compose_nginx_django.tar.gz - path: ${{ github.workspace }}/artifact/upload/ diff --git a/.github/workflows/create_release.yml b/.github/workflows/create_release.yml deleted file mode 100644 index f5c944e2..00000000 --- a/.github/workflows/create_release.yml +++ /dev/null @@ -1,117 +0,0 @@ -on: - push: - branches: - - "tbd" - -name: Create Release - -jobs: - build: - name: Create Release - runs-on: ubuntu-latest - - steps: - - - name: "Get current version" - uses: oprypin/find-latest-tag@v1 - with: - repository: ${{ github.repository }} # The repository to scan. - releases-only: true # We know that all relevant tags have a GitHub release for them. - id: acme2certifier_ver # The step ID to refer to later. - - - name: Checkout code - uses: actions/checkout@v3 - - - name: Retrieve Version from version.py - run: | - echo APP_NAME=$(echo ${{ github.repository }} | awk -F / '{print $2}') >> $GITHUB_ENV - echo TAG_NAME=$(cat acme_srv/version.py | grep -i __version__ | head -n 1 | sed 's/__version__ = //g' | sed s/\'//g) >> $GITHUB_ENV - - - run: echo "Repo is at version ${{ steps.acme2certifier_ver.outputs.tag }}" - - run: echo "APP tag is ${{ env.APP_NAME }}" - - run: echo "Latest tag is ${{ env.TAG_NAME }}" - - - name: Create Release - id: create_release - if: steps.acme2certifier_ver.outputs.tag != env.TAG_NAME - uses: actions/create-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token - with: - tag_name: ${{ env.TAG_NAME }} - release_name: ${{ env.APP_NAME }} ${{ env.TAG_NAME }} - body: | - [Changelog](https://github.com/grindsa/acme2certifier/blob/master/CHANGES.md) - draft: false - prerelease: false - - - name: update version number in spec file - if: steps.acme2certifier_ver.outputs.tag != env.TAG_NAME - run: | - sudo sed -i "s/__version__/${{ env.TAG_NAME }}/g" examples/install_scripts/rpm/acme2certifier.spec - sudo sed -i "s/\/var\/www\/acme2certifier\/volume/\/etc\/nginx/g" examples/nginx/nginx_acme_srv_ssl.conf - git config --global user.email "grindelsack@gmail.com" - git config --global user.name "rpm update" - git add examples/nginx - git commit -a -m "rpm update" - - - name: build RPM package - id: rpm_build - if: steps.acme2certifier_ver.outputs.tag != env.TAG_NAME - uses: grindsa/rpmbuild@master - with: - spec_file: "examples/install_scripts/rpm/acme2certifier.spec" - - - name: Upload Release Source-RPM - id: upload-srpm - if: steps.acme2certifier_ver.outputs.tag != env.TAG_NAME - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ${{ steps.rpm_build.outputs.source_rpm_path }} - asset_name: ${{ steps.rpm_build.outputs.source_rpm_name }} - asset_content_type: ${{ steps.rpm_build.outputs.rpm_content_type }} - - - name: Upload Release RPM - id: upload-rpm - if: steps.acme2certifier_ver.outputs.tag != env.TAG_NAME - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ${{ steps.rpm_build.outputs.rpm_dir_path }}noarch/acme2certifier-${{ env.TAG_NAME }}-1.0.noarch.rpm - asset_name: acme2certifier-${{ env.TAG_NAME }}-1.0.noarch.rpm - asset_content_type: ${{ steps.rpm_build.outputs.rpm_content_type }} - - - name: Prepare deb packaging environment - if: steps.acme2certifier_ver.outputs.tag != env.TAG_NAME - run: | - sudo apt-get -y install build-essential fakeroot dpkg-dev devscripts debhelper - rm setup.py - cp -R examples/install_scripts/debian ./ - sudo sed -i "s/__version__/${{ env.TAG_NAME }}/g" debian/changelog - cd ../ - tar cvfz ../acme2certifier_${{ env.TAG_NAME }}.orig.tar.gz ./ - - - name: "[ BUILD ] build debian package" - if: steps.acme2certifier_ver.outputs.tag != env.TAG_NAME - run: | - dpkg-buildpackage -uc -us - # dpkg -c ../acme2certifier_${{ env.TAG_NAME }}-1_all.deb - cp ../acme2certifier_${{ env.TAG_NAME }}-1_all.deb "$(pwd)/acme2certifier_${{ env.TAG_NAME }}-1_all.deb" - ls -la - - - name: Upload Release deb - id: upload-deb - if: steps.acme2certifier_ver.outputs.tag != env.TAG_NAME - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: acme2certifier_${{ env.TAG_NAME }}-1_all.deb - asset_name: acme2certifier_${{ env.TAG_NAME }}-1_all.deb - asset_content_type: application/vnd.debian.binary-package \ No newline at end of file diff --git a/.github/workflows/django_tests..yml b/.github/workflows/django_tests..yml index e9972b7f..897bac3f 100644 --- a/.github/workflows/django_tests..yml +++ b/.github/workflows/django_tests..yml @@ -9,105 +9,60 @@ on: - cron: '0 2 * * 6' jobs: - apache_django_mariadb: - name: "apache_django_mariadb" + django_mariadb: + name: "django_mariadb" runs-on: ubuntu-latest + strategy: + fail-fast: false + max-parallel: 2 + matrix: + websrv: ['apache2', 'nginx'] + steps: - name: "checkout GIT" - uses: actions/checkout@v3 + uses: actions/checkout@v4 - - name: "[ PREPARE ] Build environment" - working-directory: examples/Docker/ - run: | - sed -i "s/wsgi/django/g" .env - sudo mkdir -p data/mysql - docker network create acme - docker-compose up -d - docker-compose logs - - - name: "[ PREPARE ] install mariadb" - working-directory: examples/Docker/ - run: | - # docker run --name mariadbsrv --network acme -v $PWD/data/mysql:/var/lib/mysql -e MARIADB_ROOT_PASSWORD=foobar -d mariadb - docker run --name mariadbsrv --network acme -e MARIADB_ROOT_PASSWORD=foobar -d mariadb - - - name: "[ PREPARE ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 + - name: "Build container" + uses: ./.github/actions/container_prep with: - time: 10s + DB_HANDLER: "django" + WEB_SRV: ${{ matrix.websrv }} + DJANGO_DB: "mariadb" - - name: "[ PREPARE ] configure mariadb" - working-directory: examples/Docker/ - run: | - docker exec mariadbsrv mariadb -u root --password=foobar -e"CREATE DATABASE acme2certifier CHARACTER SET UTF8;" - docker exec mariadbsrv mariadb -u root --password=foobar -e"GRANT ALL PRIVILEGES ON acme2certifier.* TO 'acme2certifier'@'%' IDENTIFIED BY '1mmSvDFl';" - docker exec mariadbsrv mariadb -u root --password=foobar -e"FLUSH PRIVILEGES;" - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - sudo cp .github/acme2certifier.pem examples/Docker/data/acme2certifier.pem - sudo cp .github/django_settings.py examples/Docker/data/settings.py - cd examples/Docker/ - sudo chmod 777 data/acme_srv.cfg - sudo echo "" >> data/acme_srv.cfg - sudo echo "[Directory]" >> data/acme_srv.cfg - sudo echo "url_prefix: /foo" >> data/acme_srv.cfg - docker-compose restart - docker-compose logs - env: + - name: "Prepare acme_srv.cfg with certifier_ca_handler" + uses: ./.github/actions/wf_specific/certifier_ca_handler/certifier_setup_no_profile + with: + WCCE_SSH_ACCESS_KEY: ${{ secrets.WCCE_SSH_ACCESS_KEY }} + WCCE_SSH_KNOWN_HOSTS: ${{ secrets.WCCE_SSH_KNOWN_HOSTS }} + WCCE_SSH_USER: ${{ secrets.WCCE_SSH_USER }} + WCCE_SSH_HOST: ${{ secrets.WCCE_SSH_HOST }} + WCCE_SSH_PORT: ${{ secrets.WCCE_SSH_PORT }} NCM_API_HOST: ${{ secrets.NCM_API_HOST }} NCM_API_USER: ${{ secrets.NCM_API_USER }} NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - - name: "Test if http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "Test if https://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon + DATA_PATH: examples/Docker/data - - name: "[ ENROLL ] register via http" + - name: "Restart a2c" run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --debug 2 - - - name: "[ ENROLL ] register via https" - run: | - docker exec -i acme-sh acme.sh --server https://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --insecure --debug 2 - - - name: "[ ENROLL] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --debug --output-insecure + cd examples/Docker/ + sudo echo "[Directory]" >> data/acme_srv.cfg + sudo echo "url_prefix: /foo" >> data/acme_srv.cfg + grep -i 'django.db.backends.mysql' data/settings.py + docker-compose restart - - name: "[ REGISTER] certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email + - name: "Test enrollment" + uses: ./.github/actions/acme_clients - - name: "[ ENROLL ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot - sudo chmod 777 certbot/archive/certbot/chain1.pem - sudo cp certbot/archive/certbot/chain1.pem chain1.pem - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < chain1.pem - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem + - name: "Check container configuration" + uses: ./.github/actions/container_check + with: + DB_HANDLER: "django" + WEB_SRV: ${{ matrix.websrv }} - name: "[ * ] collecting test logs" if: ${{ failure() }} + continue-on-error: true run: | docker exec mariadbsrv mariadb-dump -u root --password=foobar acme2certifier > /tmp/acme2certifer.sql mkdir -p ${{ github.workspace }}/artifact/upload @@ -116,849 +71,340 @@ jobs: cd examples/Docker docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data + - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: ${{ failure() }} with: - name: apache-django-mariadb.tar.gz + name: ${{ matrix.websrv }}-mariadb.tar.gz path: ${{ github.workspace }}/artifact/upload/ - apache_django_psql: - name: "apache_django_psql" + django_psql: + name: "django_psql" runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + websrv: ['apache2', 'nginx'] steps: - name: "checkout GIT" - uses: actions/checkout@v3 + uses: actions/checkout@v4 - - name: "[ PREPARE ] Build environment" - working-directory: examples/Docker/ - run: | - sed -i "s/wsgi/django/g" .env - sudo mkdir -p data/mysql - sudo mkdir -p data/pgsql - docker network create acme - docker-compose up -d - docker-compose logs - - - name: "[ PREPARE ] postgres environment" - run: | - sudo cp .github/a2c.psql examples/Docker/data/pgsql/a2c.psql - sudo cp .github/pgpass examples/Docker/data/pgsql/pgpass - sudo chmod 600 examples/Docker/data/pgsql/pgpass - - - name: "[ PREPARE ] install postgres" - working-directory: examples/Docker/ - run: | - docker run --name postgresdbsrv --network acme -e POSTGRES_PASSWORD=foobar -d postgres - - - name: "[ PREPARE ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 + - name: "Build container" + uses: ./.github/actions/container_prep with: - time: 10s + DB_HANDLER: "django" + WEB_SRV: ${{ matrix.websrv }} + DJANGO_DB: "psql" - - name: "[ PREPARE ] configure postgres" - working-directory: examples/Docker/ - run: | - docker run -v "$(pwd)/data/pgsql/a2c.psql":/tmp/a2c.psql -v "$(pwd)/data/pgsql/pgpass:/root/.pgpass" --rm --network acme postgres psql -U postgres -h postgresdbsrv -f /tmp/a2c.psql - - name: "[ PREPARE ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 + - name: "Prepare acme_srv.cfg with certifier_ca_handler" + uses: ./.github/actions/wf_specific/certifier_ca_handler/certifier_setup_no_profile with: - time: 10s - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - sudo cp .github/acme2certifier.pem examples/Docker/data/acme2certifier.pem - sudo cp .github/django_settings.py examples/Docker/data/settings.py - cd examples/Docker/ - sudo chmod 777 data/acme_srv.cfg - sudo echo "" >> data/acme_srv.cfg - sudo echo "[Directory]" >> data/acme_srv.cfg - sudo echo "url_prefix: /foo" >> data/acme_srv.cfg - sudo truncate -s 0 $(docker inspect --format='{{.LogPath}}' acme2certifier_acme-srv_1) - docker-compose restart - docker-compose logs - env: + WCCE_SSH_ACCESS_KEY: ${{ secrets.WCCE_SSH_ACCESS_KEY }} + WCCE_SSH_KNOWN_HOSTS: ${{ secrets.WCCE_SSH_KNOWN_HOSTS }} + WCCE_SSH_USER: ${{ secrets.WCCE_SSH_USER }} + WCCE_SSH_HOST: ${{ secrets.WCCE_SSH_HOST }} + WCCE_SSH_PORT: ${{ secrets.WCCE_SSH_PORT }} NCM_API_HOST: ${{ secrets.NCM_API_HOST }} NCM_API_USER: ${{ secrets.NCM_API_USER }} NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "Test if http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "Test if https://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ ENROLL ] register via http" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --debug 2 - - - name: "[ ENROLL ] register via https" - run: | - docker exec -i acme-sh acme.sh --server https://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --insecure --debug 2 - - - name: "[ ENROLL] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --debug --output-insecure - - - name: "[ REGISTER] certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email - - - name: "[ ENROLL ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot - sudo chmod 777 certbot/archive/certbot/chain1.pem - sudo cp certbot/archive/certbot/chain1.pem chain1.pem - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < chain1.pem - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem - - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - docker run -v "$(pwd)/examples/Docker/data/pgsql/pgpass":/root/.pgpass --rm --network acme postgres pg_dump -U postgres -h postgresdbsrv acme2certifier > /tmp/acme2certifier.psql - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - sudo cp /tmp/acme2certifier.psql ${{ github.workspace }}/artifact/data/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: apache-django-psql.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - - nginx_django_mariadb: - name: "nginx_django_mariadb" - runs-on: ubuntu-latest - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "[ PREPARE ] Build environment" - working-directory: examples/Docker/ - run: | - sed -i "s/wsgi/django/g" .env - sed -i "s/apache2/nginx/g" .env - sudo mkdir -p data/mysql - docker network create acme - docker-compose up -d - docker-compose logs - - - name: "[ PREPARE ] install mariadb" - working-directory: examples/Docker/ - run: | - # docker run --name mariadbsrv --network acme -v $PWD/data/mysql:/var/lib/mysql -e MARIADB_ROOT_PASSWORD=foobar -d mariadb - docker run --name mariadbsrv --network acme -e MARIADB_ROOT_PASSWORD=foobar -d mariadb - - - name: "[ PREPARE ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "[ PREPARE ] configure mariadb" - working-directory: examples/Docker/ - run: | - docker exec mariadbsrv mariadb -u root --password=foobar -e"CREATE DATABASE acme2certifier CHARACTER SET UTF8;" - docker exec mariadbsrv mariadb -u root --password=foobar -e"GRANT ALL PRIVILEGES ON acme2certifier.* TO 'acme2certifier'@'%' IDENTIFIED BY '1mmSvDFl';" - docker exec mariadbsrv mariadb -u root --password=foobar -e"FLUSH PRIVILEGES;" + DATA_PATH: examples/Docker/data - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" + - name: "Restart a2c" run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - sudo cp .github/acme2certifier_cert.pem examples/Docker/data/acme2certifier_cert.pem - sudo cp .github/acme2certifier_key.pem examples/Docker/data/acme2certifier_key.pem - sudo cp .github/django_settings_mariadb.py examples/Docker/data/settings.py cd examples/Docker/ - sudo chmod 777 data/acme_srv.cfg - sudo echo "" >> data/acme_srv.cfg sudo echo "[Directory]" >> data/acme_srv.cfg sudo echo "url_prefix: /foo" >> data/acme_srv.cfg + grep -i 'django.db.backends.postgresql_psycopg2' data/settings.py docker-compose restart - docker-compose logs - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "[ PREPARE ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "Test if http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "Test if https://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory - - name: "[ PREPARE ] prepare acme.sh container" - run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ ENROLL ] register via http" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --debug 2 - - - name: "[ ENROLL ] register via https" - run: | - docker exec -i acme-sh acme.sh --server https://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --insecure --debug 2 - - - name: "[ ENROLL] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --debug --output-insecure + - name: "Test enrollment" + uses: ./.github/actions/acme_clients - - name: "[ REGISTER] certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email - - - name: "[ ENROLL ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot - sudo chmod 777 certbot/archive/certbot/chain1.pem - sudo cp certbot/archive/certbot/chain1.pem chain1.pem - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < chain1.pem - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem + - name: "Check container configuration" + uses: ./.github/actions/container_check + with: + DB_HANDLER: "django" + WEB_SRV: ${{ matrix.websrv }} - name: "[ * ] collecting test logs" if: ${{ failure() }} + continue-on-error: true run: | - docker exec mariadbsrv mariadb-dump -u root --password=foobar acme2certifier > /tmp/acme2certifer.sql + docker run -v "$(pwd)/examples/Docker/data/pgsql/pgpass":/root/.pgpass --rm --network acme postgres pg_dump -U postgres -h postgresdbsrv acme2certifier > /tmp/acme2certifier.psql mkdir -p ${{ github.workspace }}/artifact/upload sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - sudo cp /tmp/acme2certifer.sql ${{ github.workspace }}/artifact/data/ + sudo cp /tmp/acme2certifier.psql ${{ github.workspace }}/artifact/data/ cd examples/Docker docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data + - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: ${{ failure() }} with: - name: nginx-django-mariadb.tar.gz + name: ${{ matrix.websrv }}-psql.tar.gz path: ${{ github.workspace }}/artifact/upload/ - nginx_django_psql: - name: "nginx_django_psql" + rpm_build_and_upload: + name: "rpm_build_and_upload" runs-on: ubuntu-latest steps: - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "[ PREPARE ] Build environment" - working-directory: examples/Docker/ - run: | - sed -i "s/wsgi/django/g" .env - sed -i "s/apache2/nginx/g" .env - sudo mkdir -p data/mysql - sudo mkdir -p data/pgsql - docker network create acme - docker-compose up -d - docker-compose logs - - - name: "[ PREPARE ] postgres environment" - run: | - sudo cp .github/a2c.psql examples/Docker/data/pgsql/a2c.psql - sudo cp .github/pgpass examples/Docker/data/pgsql/pgpass - sudo chmod 600 examples/Docker/data/pgsql/pgpass - - - name: "[ PREPARE ] install postgres" - working-directory: examples/Docker/ - run: | - docker run --name postgresdbsrv --network acme -e POSTGRES_PASSWORD=foobar -d postgres - - - name: "[ PREPARE ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "[ PREPARE ] configure postgres" - working-directory: examples/Docker/ - run: | - docker run -v "$(pwd)/data/pgsql/a2c.psql":/tmp/a2c.psql -v "$(pwd)/data/pgsql/pgpass:/root/.pgpass" --rm --network acme postgres psql -U postgres -h postgresdbsrv -f /tmp/a2c.psql - - name: "[ PREPARE ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - sudo cp .github/django_settings_psql.py examples/Docker/data/settings.py - sudo cp .github/acme2certifier_cert.pem examples/Docker/data/acme2certifier_cert.pem - sudo cp .github/acme2certifier_key.pem examples/Docker/data/acme2certifier_key.pem - cd examples/Docker/ - sudo chmod 777 data/acme_srv.cfg - sudo echo "" >> data/acme_srv.cfg - sudo echo "[Directory]" >> data/acme_srv.cfg - sudo echo "url_prefix: /foo" >> data/acme_srv.cfg - sudo truncate -s 0 $(docker inspect --format='{{.LogPath}}' acme2certifier_acme-srv_1) - docker-compose restart - docker-compose logs - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} + uses: actions/checkout@v4 - - name: "[ PREPARE ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "Test if http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory + - name: "Build rpm package" + id: rpm_build + uses: ./.github/actions/rpm_build_upload - - name: "Test if https://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ ENROLL ] register via http" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --debug 2 - - - name: "[ ENROLL ] register via https" - run: | - docker exec -i acme-sh acme.sh --server https://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --insecure --debug 2 - - - name: "[ ENROLL] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --debug --output-insecure - - - name: "[ REGISTER] certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email - - - name: "[ ENROLL ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot - sudo chmod 777 certbot/archive/certbot/chain1.pem - sudo cp certbot/archive/certbot/chain1.pem chain1.pem - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < chain1.pem - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem - - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - docker run -v "$(pwd)/examples/Docker/data/pgsql/pgpass":/root/.pgpass --rm --network acme postgres pg_dump -U postgres -h postgresdbsrv acme2certifier > /tmp/acme2certifier.psql - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - sudo cp /tmp/acme2certifier.psql ${{ github.workspace }}/artifact/data/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: nginx-django-psql.tar.gz - path: ${{ github.workspace }}/artifact/upload/ nginx_django_rpm_sqlite: name: "nginx_django_rpm_sqlite" runs-on: ubuntu-latest + needs: rpm_build_and_upload + strategy: + fail-fast: false + max-parallel: 1 + matrix: + rhversion: [8, 9] steps: - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: Retrieve Version from version.py - run: | - echo TAG_NAME=$(cat acme_srv/version.py | grep -i __version__ | head -n 1 | sed 's/__version__ = //g' | sed s/\'//g) >> $GITHUB_ENV - - run: echo "Latest tag is ${{ env.TAG_NAME }}" + uses: actions/checkout@v4 - - name: update version number in spec file and path in nginx ssl config - run: | - sudo sed -i "s/__version__/${{ env.TAG_NAME }}/g" examples/install_scripts/rpm/acme2certifier.spec - sudo sed -i "s/\/var\/www\/acme2certifier\/volume/\/etc\/nginx/g" examples/nginx/nginx_acme_srv_ssl.conf - git config --global user.email "grindelsack@gmail.com" - git config --global user.name "rpm update" - git add examples/nginx - git commit -a -m "rpm update" - - - name: build RPM package - id: rpm - uses: grindsa/rpmbuild@alma9 + - name: "Prepare Alma environment" + uses: ./.github/actions/rpm_prep with: - spec_file: "examples/install_scripts/rpm/acme2certifier.spec" - - - run: echo "path is ${{ steps.rpm.outputs.rpm_dir_path }}" - - - name: "[ PREPARE ] setup environment for alma installation" - run: | - docker network create acme - sudo mkdir -p data/volume - sudo mkdir -p data/acme2certifier - sudo mkdir -p data/nginx - sudo chmod -R 777 data - sudo cp ${{ steps.rpm.outputs.rpm_dir_path }}noarch/acme2certifier-${{ env.TAG_NAME }}-1.0.noarch.rpm data - sudo cp examples/Docker/almalinux-systemd/django_tester.sh data - sudo cp .github/acme2certifier_cert.pem data/nginx/acme2certifier_cert.pem - sudo cp .github/acme2certifier_key.pem data/nginx/acme2certifier_key.pem - sudo cp .github/django_settings.py data/acme2certifier/settings.py - sudo sed -i "s/\/var\/www\//\/opt\//g" data/acme2certifier/settings.py - sudo sed -i "s/USE_I18N = True/USE_I18N = False/g" data/acme2certifier/settings.py - - - name: "Retrieve rpms from SBOM repo" - run: | - git clone https://$GH_SBOM_USER:$GH_SBOM_TOKEN@github.com/$GH_SBOM_USER/sbom /tmp/sbom - cp /tmp/sbom/rpm-repo/RPMs/*.rpm data - env: GH_SBOM_USER: ${{ secrets.GH_SBOM_USER }} GH_SBOM_TOKEN: ${{ secrets.GH_SBOM_TOKEN }} + RH_VERSION: ${{ matrix.rhversion }} + RPM_BUILD: false - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo mkdir -p acme-sh - mkdir -p data/acme_ca - sudo cp test/ca/certsrv_ca_certs.pem data/acme_ca/ca_certs.pem - sudo touch data/volume/acme_srv.cfg - sudo chmod 777 data/volume/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > data/volume/acme_srv.cfg - sudo echo "handler_file: /opt/acme2certifier/examples/ca_handler/certifier_ca_handler.py" >> data/volume/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> data/volume/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> data/volume/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> data/volume/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> data/volume/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> data/volume/acme_srv.cfg - sudo echo "profile_id: 101" >> data/volume/acme_srv.cfg - env: + - name: Download rpm package + uses: actions/download-artifact@v4 + with: + name: acme2certifier-${{ github.run_id }}.noarch.rpm + path: data/ + + - name: "Prepare acme_srv.cfg with certifier_ca_handler" + uses: ./.github/actions/wf_specific/certifier_ca_handler/certifier_setup_no_profile + with: + WCCE_SSH_ACCESS_KEY: ${{ secrets.WCCE_SSH_ACCESS_KEY }} + WCCE_SSH_KNOWN_HOSTS: ${{ secrets.WCCE_SSH_KNOWN_HOSTS }} + WCCE_SSH_USER: ${{ secrets.WCCE_SSH_USER }} + WCCE_SSH_HOST: ${{ secrets.WCCE_SSH_HOST }} + WCCE_SSH_PORT: ${{ secrets.WCCE_SSH_PORT }} NCM_API_HOST: ${{ secrets.NCM_API_HOST }} NCM_API_USER: ${{ secrets.NCM_API_USER }} NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} + DATA_PATH: data/volume - - name: "[ PREPARE ] Almalinux instance" + - name: "Modify Django setup" run: | - cat examples/Docker/almalinux-systemd/Dockerfile | docker build -t almalinux-systemd -f - . --no-cache - docker run -d -id --privileged --network acme -p 22280:80 --name=acme-srv -v "$(pwd)/data":/tmp/acme2certifier almalinux-systemd + sudo mkdir -p data/volume/acme_ca/certs + grep -i 'django.db.backends.sqlite3' data/acme2certifier/settings.py - - name: "[ RUN ] Execute install scipt" + - name: "Execute install scipt" run: | docker exec acme-srv sh /tmp/acme2certifier/django_tester.sh - - name: "Test http://acme-srv/directory is accessible" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "Test if https://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory - - - name: "[ CURL ] install curl and socat and test connction" - run: | - sudo apt-get install -y curl socat - curl -f http://localhost:22280 - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ ENROLL ] register via http" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --debug 2 - - - name: "[ ENROLL ] register via https" - run: | - docker exec -i acme-sh acme.sh --server https://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --insecure --debug 2 - - - name: "[ ENROLL] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server https://acme-srv --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --alpn --standalone --debug 3 --insecure --output-insecure --force - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer - ls -la *.pem - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - - name: "[ REGISTER] certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email - - - name: "[ ENROLL ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot - sudo chmod 777 certbot/archive/certbot/chain1.pem - sudo cp certbot/archive/certbot/chain1.pem chain1.pem - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < chain1.pem - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem + - name: "Test enrollment" + uses: ./.github/actions/acme_clients - name: "[ * ] collecting test logs" if: ${{ failure() }} + continue-on-error: true run: | mkdir -p ${{ github.workspace }}/artifact/upload docker exec acme-srv tar cvfz /tmp/acme2certifier/a2c.tgz /opt/acme2certifier docker exec acme-srv tar cvfz /tmp/acme2certifier/nginx.tgz /etc/nginx sudo cp -rp data/ ${{ github.workspace }}/artifact/data/ sudo cp -rp acme-sh/ ${{ github.workspace }}/artifact/acme-sh/ + sudo rm ${{ github.workspace }}/artifact/data/*.rpm + docker exec acme-srv cat /etc/nginx/nginx.conf.orig > ${{ github.workspace }}/artifact/data/nginx.conf.orig + docker exec acme-srv cat /etc/nginx/nginx.conf > ${{ github.workspace }}/artifact/data/nginx.conf + docker exec acme-srv rpm -qa > ${{ github.workspace }}/artifact/data/packages.txt docker exec acme-srv cat /var/log/messages > ${{ github.workspace }}/artifact/acme-srv.log sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz data acme-srv.log acme-sh - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: ${{ failure() }} with: - name: nginx_django_rpm_sqlite.tar.gz + name: nginx_django_rpm_sqlite-rh${{ matrix.rhversion }}.tar.gz path: ${{ github.workspace }}/artifact/upload/ nginx_django_rpm_mariadb: name: "nginx_django_rpm_mariadb" runs-on: ubuntu-latest + needs: rpm_build_and_upload + strategy: + fail-fast: false + max-parallel: 1 + matrix: + rhversion: [9] steps: - name: "checkout GIT" - uses: actions/checkout@v3 + uses: actions/checkout@v4 + + - name: "Prepare Alma environment" + uses: ./.github/actions/rpm_prep + with: + GH_SBOM_USER: ${{ secrets.GH_SBOM_USER }} + GH_SBOM_TOKEN: ${{ secrets.GH_SBOM_TOKEN }} + RH_VERSION: ${{ matrix.rhversion }} + DJANGO_DB: mariadb + RPM_BUILD: false - - name: Retrieve Version from version.py + - name: "Retrieve Version from version.py" run: | echo TAG_NAME=$(cat acme_srv/version.py | grep -i __version__ | head -n 1 | sed 's/__version__ = //g' | sed s/\'//g) >> $GITHUB_ENV - run: echo "Latest tag is ${{ env.TAG_NAME }}" - - name: update version number in spec file and path in nginx ssl config - run: | - sudo sed -i "s/__version__/${{ env.TAG_NAME }}/g" examples/install_scripts/rpm/acme2certifier.spec - sudo sed -i "s/\/var\/www\/acme2certifier\/volume/\/etc\/nginx/g" examples/nginx/nginx_acme_srv_ssl.conf - git config --global user.email "grindelsack@gmail.com" - git config --global user.name "rpm update" - git add examples/nginx - git commit -a -m "rpm update" - - - name: build RPM package - id: rpm - uses: grindsa/rpmbuild@alma9 + - name: Download rpm package + uses: actions/download-artifact@v4 with: - spec_file: "examples/install_scripts/rpm/acme2certifier.spec" - - - run: echo "path is ${{ steps.rpm.outputs.rpm_dir_path }}" - - - name: "[ PREPARE ] setup environment for alma installation" - run: | - docker network create acme - sudo mkdir -p data/volume - sudo mkdir -p data/acme2certifier - sudo mkdir -p data/nginx - sudo chmod -R 777 data - sudo cp ${{ steps.rpm.outputs.rpm_dir_path }}noarch/acme2certifier-${{ env.TAG_NAME }}-1.0.noarch.rpm data - sudo cp examples/Docker/almalinux-systemd/django_tester.sh data - sudo cp .github/acme2certifier_cert.pem data/nginx/acme2certifier_cert.pem - sudo cp .github/acme2certifier_key.pem data/nginx/acme2certifier_key.pem - sudo cp .github/django_settings_mariadb.py data/acme2certifier/settings.py - # sudo sed -i "s/\/var\/www\//\/opt\//g" data/acme2certifier/settings.py - sudo sed -i "s/USE_I18N = True/USE_I18N = False/g" data/acme2certifier/settings.py - - - name: "[ PREPARE ] install mariadb" - run: | - sudo mkdir -p /tmp/mysql - docker run --name mariadbsrv --network acme -v /tmp/mysql:/var/lib/mysql -e MARIADB_ROOT_PASSWORD=foobar -d mariadb - # docker run --name mariadbsrv --network acme -e MARIADB_ROOT_PASSWORD=foobar -d mariadb + name: acme2certifier-${{ github.run_id }}.noarch.rpm + path: data/ - - name: "[ PREPARE ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 + - name: "Prepare acme_srv.cfg with certifier_ca_handler" + uses: ./.github/actions/wf_specific/certifier_ca_handler/certifier_setup_no_profile with: - time: 10s - - - name: "[ PREPARE ] configure mariadb" - run: | - docker exec mariadbsrv mariadb -u root --password=foobar -e"CREATE DATABASE acme2certifier CHARACTER SET UTF8;" - docker exec mariadbsrv mariadb -u root --password=foobar -e"GRANT ALL PRIVILEGES ON acme2certifier.* TO 'acme2certifier'@'%' IDENTIFIED BY '1mmSvDFl';" - docker exec mariadbsrv mariadb -u root --password=foobar -e"FLUSH PRIVILEGES;" - - - name: "Retrieve rpms from SBOM repo" - run: | - git clone https://$GH_SBOM_USER:$GH_SBOM_TOKEN@github.com/$GH_SBOM_USER/sbom /tmp/sbom - cp /tmp/sbom/rpm-repo/RPMs/*.rpm data - env: - GH_SBOM_USER: ${{ secrets.GH_SBOM_USER }} - GH_SBOM_TOKEN: ${{ secrets.GH_SBOM_TOKEN }} - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo mkdir -p acme-sh - mkdir -p data/acme_ca - sudo cp test/ca/certsrv_ca_certs.pem data/acme_ca/ca_certs.pem - sudo touch data/volume/acme_srv.cfg - sudo chmod 777 data/volume/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > data/volume/acme_srv.cfg - sudo echo "handler_file: /opt/acme2certifier/examples/ca_handler/certifier_ca_handler.py" >> data/volume/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> data/volume/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> data/volume/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> data/volume/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> data/volume/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> data/volume/acme_srv.cfg - sudo echo "profile_id: 101" >> data/volume/acme_srv.cfg - env: + WCCE_SSH_ACCESS_KEY: ${{ secrets.WCCE_SSH_ACCESS_KEY }} + WCCE_SSH_KNOWN_HOSTS: ${{ secrets.WCCE_SSH_KNOWN_HOSTS }} + WCCE_SSH_USER: ${{ secrets.WCCE_SSH_USER }} + WCCE_SSH_HOST: ${{ secrets.WCCE_SSH_HOST }} + WCCE_SSH_PORT: ${{ secrets.WCCE_SSH_PORT }} NCM_API_HOST: ${{ secrets.NCM_API_HOST }} NCM_API_USER: ${{ secrets.NCM_API_USER }} NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} + DATA_PATH: data/volume - - name: "[ PREPARE ] Almalinux instance" + - name: "Modify Django setup" run: | - cat examples/Docker/almalinux-systemd/Dockerfile | docker build -t almalinux-systemd -f - . --no-cache - docker run -d -id --privileged --network acme -p 22280:80 --name=acme-srv -v "$(pwd)/data":/tmp/acme2certifier almalinux-systemd + grep -i 'django.db.backends.mysql' data/acme2certifier/settings.py - - name: "[ RUN ] Execute install scipt" + - name: "Execute install scipt" run: | docker exec acme-srv sh /tmp/acme2certifier/django_tester.sh - - name: "Test http://acme-srv/directory is accessible" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "Test if https://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory - - - name: "[ CURL ] install curl and socat and test connction" - run: | - sudo apt-get install -y curl socat - curl -f http://localhost:22280 - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ ENROLL ] register via http" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --debug 2 - - - name: "[ ENROLL ] register via https" - run: | - docker exec -i acme-sh acme.sh --server https://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --insecure --debug 2 - - - name: "[ ENROLL] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server https://acme-srv --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --alpn --standalone --debug 3 --insecure --output-insecure --force - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - - name: "[ REGISTER] certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email - - - name: "[ ENROLL ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot - sudo chmod 777 certbot/archive/certbot/chain1.pem - sudo cp certbot/archive/certbot/chain1.pem chain1.pem - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < chain1.pem - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem + - name: "Test enrollment" + uses: ./.github/actions/acme_clients - name: "[ * ] collecting test logs" if: ${{ failure() }} + continue-on-error: true run: | mkdir -p ${{ github.workspace }}/artifact/upload docker exec acme-srv tar cvfz /tmp/acme2certifier/a2c.tgz /opt/acme2certifier docker exec acme-srv tar cvfz /tmp/acme2certifier/nginx.tgz /etc/nginx sudo cp -rp data/ ${{ github.workspace }}/artifact/data/ sudo cp -rp acme-sh/ ${{ github.workspace }}/artifact/acme-sh/ + sudo rm ${{ github.workspace }}/artifact/data/*.rpm + docker exec acme-srv cat /etc/nginx/nginx.conf.orig > ${{ github.workspace }}/artifact/data/nginx.conf.orig + docker exec acme-srv cat /etc/nginx/nginx.conf > ${{ github.workspace }}/artifact/data/nginx.conf + docker exec acme-srv rpm -qa | sort -n > ${{ github.workspace }}/artifact/data/packages.txt + docker exec mariadbsrv mariadb-dump -u root --password=foobar acme2certifier > ${{ github.workspace }}/artifact/data/acme2certifer.sql docker exec acme-srv cat /var/log/messages > ${{ github.workspace }}/artifact/acme-srv.log sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz data acme-srv.log acme-sh /tmp/mysql - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: ${{ failure() }} with: - name: nginx_django_rpm_mariadb.tar.gz + name: nginx_django_rpm_mariadb-rh${{ matrix.rhversion }}.tar.gz path: ${{ github.workspace }}/artifact/upload/ nginx_django_rpm_psql: name: "nginx_django_rpm_psql" runs-on: ubuntu-latest + needs: rpm_build_and_upload + strategy: + fail-fast: false + max-parallel: 1 + matrix: + rhversion: [8, 9] steps: - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: Retrieve Version from version.py - run: | - echo TAG_NAME=$(cat acme_srv/version.py | grep -i __version__ | head -n 1 | sed 's/__version__ = //g' | sed s/\'//g) >> $GITHUB_ENV - - run: echo "Latest tag is ${{ env.TAG_NAME }}" + uses: actions/checkout@v4 - - name: update version number in spec file and path in nginx ssl config - run: | - sudo sed -i "s/__version__/${{ env.TAG_NAME }}/g" examples/install_scripts/rpm/acme2certifier.spec - sudo sed -i "s/\/var\/www\/acme2certifier\/volume/\/etc\/nginx/g" examples/nginx/nginx_acme_srv_ssl.conf - git config --global user.email "grindelsack@gmail.com" - git config --global user.name "rpm update" - git add examples/nginx - git commit -a -m "rpm update" - - - name: build RPM package - id: rpm - uses: grindsa/rpmbuild@alma9 + - name: "Prepare Alma environment" + uses: ./.github/actions/rpm_prep with: - spec_file: "examples/install_scripts/rpm/acme2certifier.spec" - - - run: echo "path is ${{ steps.rpm.outputs.rpm_dir_path }}" - - - name: "[ PREPARE ] setup environment for alma installation" - run: | - docker network create acme - sudo mkdir -p data/volume - sudo mkdir -p data/acme2certifier - sudo mkdir -p data/nginx - sudo chmod -R 777 data - sudo cp ${{ steps.rpm.outputs.rpm_dir_path }}noarch/acme2certifier-${{ env.TAG_NAME }}-1.0.noarch.rpm data - sudo cp examples/Docker/almalinux-systemd/django_tester.sh data - sudo cp .github/acme2certifier_cert.pem data/nginx/acme2certifier_cert.pem - sudo cp .github/acme2certifier_key.pem data/nginx/acme2certifier_key.pem - sudo cp .github/django_settings_psql.py data/acme2certifier/settings.py - # sudo sed -i "s/\/var\/www\//\/opt\//g" data/acme2certifier/settings.py - sudo sed -i "s/USE_I18N = True/USE_I18N = False/g" data/acme2certifier/settings.py - - - name: "[ PREPARE ] postgres environment" - run: | - sudo mkdir -p /tmp/pgsql/data - sudo cp .github/a2c.psql /tmp/pgsql/a2c.psql - sudo cp .github/pgpass /tmp/pgsql/pgpass - sudo chmod 600 /tmp/pgsql/pgpass + GH_SBOM_USER: ${{ secrets.GH_SBOM_USER }} + GH_SBOM_TOKEN: ${{ secrets.GH_SBOM_TOKEN }} + RH_VERSION: ${{ matrix.rhversion }} + DJANGO_DB: psql + RPM_BUILD: false - - name: "[ PREPARE ] install postgres" + - name: "Retrieve version from version.py" run: | - docker run --name postgresdbsrv -v /tmp/pgsql/data:/var/lib/postgresql/data --network acme -e POSTGRES_PASSWORD=foobar -d postgres + echo TAG_NAME=$(cat acme_srv/version.py | grep -i __version__ | head -n 1 | sed 's/__version__ = //g' | sed s/\'//g) >> $GITHUB_ENV + - run: echo "Latest tag is ${{ env.TAG_NAME }}" - - name: "[ PREPARE ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 + - name: Download rpm package + uses: actions/download-artifact@v4 with: - time: 10s - - - name: "[ PREPARE ] configure postgres" - run: | - docker run -v /tmp/pgsql/a2c.psql:/tmp/a2c.psql -v /tmp/pgsql/pgpass:/root/.pgpass --rm --network acme postgres psql -U postgres -h postgresdbsrv -f /tmp/a2c.psql + name: acme2certifier-${{ github.run_id }}.noarch.rpm + path: data/ - - name: "[ PREPARE ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 + - name: "Prepare acme_srv.cfg with certifier_ca_handler" + uses: ./.github/actions/wf_specific/certifier_ca_handler/certifier_setup_no_profile with: - time: 10s - - - name: "Retrieve rpms from SBOM repo" - run: | - git clone https://$GH_SBOM_USER:$GH_SBOM_TOKEN@github.com/$GH_SBOM_USER/sbom /tmp/sbom - cp /tmp/sbom/rpm-repo/RPMs/*.rpm data - env: - GH_SBOM_USER: ${{ secrets.GH_SBOM_USER }} - GH_SBOM_TOKEN: ${{ secrets.GH_SBOM_TOKEN }} - - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo mkdir -p acme-sh - mkdir -p data/acme_ca - sudo cp test/ca/certsrv_ca_certs.pem data/acme_ca/ca_certs.pem - sudo touch data/volume/acme_srv.cfg - sudo chmod 777 data/volume/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > data/volume/acme_srv.cfg - sudo echo "handler_file: /opt/acme2certifier/examples/ca_handler/certifier_ca_handler.py" >> data/volume/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> data/volume/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> data/volume/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> data/volume/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> data/volume/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> data/volume/acme_srv.cfg - sudo echo "profile_id: 101" >> data/volume/acme_srv.cfg - env: + WCCE_SSH_ACCESS_KEY: ${{ secrets.WCCE_SSH_ACCESS_KEY }} + WCCE_SSH_KNOWN_HOSTS: ${{ secrets.WCCE_SSH_KNOWN_HOSTS }} + WCCE_SSH_USER: ${{ secrets.WCCE_SSH_USER }} + WCCE_SSH_HOST: ${{ secrets.WCCE_SSH_HOST }} + WCCE_SSH_PORT: ${{ secrets.WCCE_SSH_PORT }} NCM_API_HOST: ${{ secrets.NCM_API_HOST }} NCM_API_USER: ${{ secrets.NCM_API_USER }} NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "[ PREPARE ] Almalinux instance" - run: | - cat examples/Docker/almalinux-systemd/Dockerfile | docker build -t almalinux-systemd -f - . --no-cache - docker run -d -id --privileged --network acme -p 22280:80 --name=acme-srv -v "$(pwd)/data":/tmp/acme2certifier almalinux-systemd - - - name: "[ RUN ] Execute install scipt" - run: | - docker exec acme-srv sh /tmp/acme2certifier/django_tester.sh + DATA_PATH: data/volume - - name: "Test http://acme-srv/directory is accessible" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - name: "Test if https://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory - - - name: "[ CURL ] install curl and socat and test connction" - run: | - sudo apt-get install -y curl socat - curl -f http://localhost:22280 - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ ENROLL ] register via http" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --debug 2 - - - name: "[ ENROLL ] register via https" - run: | - docker exec -i acme-sh acme.sh --server https://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --insecure --debug 2 - - - name: "[ ENROLL] acme.sh" + - name: "Prepare acme_srv.cfg with openssl_ca_handler" run: | - docker exec -i acme-sh acme.sh --server https://acme-srv --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --alpn --standalone --debug 3 --insecure --output-insecure --force - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer + grep -i 'django.db.backends.postgresql_psycopg2' data/acme2certifier/settings.py - - name: "[ REGISTER] certbot" + - name: "Execute install scipt" run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email + docker exec acme-srv sh /tmp/acme2certifier/django_tester.sh - - name: "[ ENROLL ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem + - name: "Test enrollment" + uses: ./.github/actions/acme_clients - name: "[ * ] collecting test logs" if: ${{ failure() }} + continue-on-error: true run: | mkdir -p ${{ github.workspace }}/artifact/upload docker exec acme-srv tar cvfz /tmp/acme2certifier/a2c.tgz /opt/acme2certifier docker exec acme-srv tar cvfz /tmp/acme2certifier/nginx.tgz /etc/nginx sudo cp -rp data/ ${{ github.workspace }}/artifact/data/ sudo cp -rp acme-sh/ ${{ github.workspace }}/artifact/acme-sh/ + sudo rm ${{ github.workspace }}/artifact/data/*.rpm + docker exec acme-srv cat /etc/nginx/nginx.conf.orig > ${{ github.workspace }}/artifact/data/nginx.conf.orig + docker exec acme-srv cat /etc/nginx/nginx.conf > ${{ github.workspace }}/artifact/data/nginx.conf + docker exec acme-srv rpm -qa > ${{ github.workspace }}/artifact/data/packages.txt docker exec acme-srv cat /var/log/messages > ${{ github.workspace }}/artifact/acme-srv.log sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz data acme-srv.log acme-sh /tmp/pgsql - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: ${{ failure() }} with: - name: nginx_django_rpm_psql.tar.gz - path: ${{ github.workspace }}/artifact/upload/ \ No newline at end of file + name: nginx_django_rpm_psql-rh${{ matrix.rhversion }}.tar.gz + path: ${{ github.workspace }}/artifact/upload/ + + rpm_cleanup: + name: "rpm_cleanup" + runs-on: ubuntu-latest + needs: [nginx_django_rpm_psql, nginx_django_rpm_mariadb, nginx_django_rpm_sqlite] + steps: + - name: "Delete artifact" + uses: geekyeggo/delete-artifact@v5 + with: + name: acme2certifier-${{ github.run_id }}.noarch.rpm diff --git a/.github/workflows/dns-test.yml b/.github/workflows/dns-test.yml index 6d38b8b7..a1f925ad 100644 --- a/.github/workflows/dns-test.yml +++ b/.github/workflows/dns-test.yml @@ -12,47 +12,55 @@ jobs: dns_challenge_tests: name: "dns_challenge_tests" runs-on: ubuntu-latest + strategy: + fail-fast: false + max-parallel: 2 + matrix: + websrv: ['apache2', 'nginx'] + dbhandler: ['wsgi', 'django'] steps: - name: "checkout GIT" - uses: actions/checkout@v3 + uses: actions/checkout@v4 - - name: "[ PREPARE ] Build docker-compose (apache2_wsgi)" - working-directory: examples/Docker/ - run: | - sudo mkdir -p data - docker network create acme - docker-compose up -d - docker-compose logs + - name: "Build container" + uses: ./.github/actions/container_prep + with: + DB_HANDLER: ${{ matrix.dbhandler }} + WEB_SRV: ${{ matrix.websrv }} - - name: "Test http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory + - name: "Prepare acme_srv.cfg with certifier_ca_handler" + uses: ./.github/actions/wf_specific/certifier_ca_handler/certifier_setup_no_profile + with: + WCCE_SSH_ACCESS_KEY: ${{ secrets.WCCE_SSH_ACCESS_KEY }} + WCCE_SSH_KNOWN_HOSTS: ${{ secrets.WCCE_SSH_KNOWN_HOSTS }} + WCCE_SSH_USER: ${{ secrets.WCCE_SSH_USER }} + WCCE_SSH_HOST: ${{ secrets.WCCE_SSH_HOST }} + WCCE_SSH_PORT: ${{ secrets.WCCE_SSH_PORT }} + NCM_API_HOST: ${{ secrets.NCM_API_HOST }} + NCM_API_USER: ${{ secrets.NCM_API_USER }} + NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} + NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} + ACME_SRV_SRC: .github/openssl_ca_handler.py_acme_srv_default_handler_dns.cfg + DATA_PATH: examples/Docker/data - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" + - name: "Restart a2c" run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler_dns.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg cd examples/Docker/ docker-compose restart docker-compose logs - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - name: "Test http://acme-srv/directory is accessable again" + - name: "Sleep for 10s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 10s + + - name: "Test http://acme-srv/directory is accessible" run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - name: "[ PREPARE ] prepare acme.sh container" + - name: "Test if https://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory + + - name: "Prepare acme.sh container" run: | docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon sudo cp .github/dns_test.sh acme-sh/ @@ -61,7 +69,7 @@ jobs: docker exec -i acme-sh mv /acme.sh/dns_test.sh /root/.acme.sh/dnsapi/ docker exec -i acme-sh chmod +x /root/.acme.sh/dnsapi/dns_test.sh - - name: "[ PREPARE ] set DNS server" + - name: "Set DNS server" run: | cd examples/Docker/ docker-compose stop @@ -70,33 +78,33 @@ jobs: docker-compose start docker-compose logs - - name: "[ ENROLL ] acme.sh - single domain" + - name: "Enroll acme.sh - single domain" run: | docker exec -i acme-sh acme.sh --dnssleep 10 --server http://acme-srv --accountemail 'acme-sh@example.com' --issue --dns dns_test -d acme-sh.single --standalone --debug 3 --output-insecure --force awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.single_ecc/ca.cer openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.single_ecc/acme-sh.single.cer - - name: "[ ENROLL ] acme.sh - two domains" + - name: "Enroll acme.sh - two domains" run: | docker exec -i acme-sh acme.sh --dnssleep 10 --server http://acme-srv --accountemail 'acme-sh@example.com' --issue --dns dns_test -d acme-sh.first --dns dns_test -d acme-sh.second --standalone --debug 3 --output-insecure --force openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.first_ecc/acme-sh.first.cer - - name: "[ ENROLL ] acme.sh - single wildcard domain" + - name: "Enroll acme.sh - single wildcard domain" run: | docker exec -i acme-sh acme.sh --dnssleep 10 --server http://acme-srv --accountemail 'acme-sh@example.com' --issue --dns dns_test -d *.acme-sh.wildcard --standalone --debug 3 --output-insecure --force openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/*acme-sh.wildcard_ecc/*acme-sh.wildcard.cer - - name: "[ ENROLL ] acme.sh - double wildcard domain" + - name: "Enroll acme.sh - double wildcard domain" run: | docker exec -i acme-sh acme.sh --dnssleep 10 --server http://acme-srv --accountemail 'acme-sh@example.com' --issue --dns dns_test -d *.acme-sh.first-wildcard --dns dns_test -d *.acme-sh.second-wildcard --standalone --debug 3 --output-insecure --force openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/*.acme-sh.first-wildcard_ecc/*.acme-sh.first-wildcard.cer - - name: "[ ENROLL ] acme.sh - domain and wildcard domain" + - name: "Enroll acme.sh - domain and wildcard domain" run: | docker exec -i acme-sh acme.sh --dnssleep 10 --server http://acme-srv --accountemail 'acme-sh@example.com' --issue --dns dns_test -d acme-sh.fqdn-wildcard --dns dns_test -d *.acme-sh.fqdn-wildcard --standalone --debug 3 --output-insecure --force openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.fqdn-wildcard_ecc/acme-sh.fqdn-wildcard.cer - - name: "[ Test ] check TXT record exists" + - name: "check TXT record exists" if: ${{ failure() }} run: | docker exec -i acme-sh ps -a @@ -120,69 +128,49 @@ jobs: sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: ${{ failure() }} with: - name: dns_challenge_tests.tar.gz + name: dns_challenge_tests-${{ matrix.websrv }}-${{ matrix.dbhandler }}.tar.gz path: ${{ github.workspace }}/artifact/upload/ dns_challenge_tests_rpm: name: "dns_challenge_tests_rpm" runs-on: ubuntu-latest + strategy: + fail-fast: false + max-parallel: 1 + matrix: + rhversion: [8, 9] + steps: - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: Retrieve Version from version.py - run: | - echo TAG_NAME=$(cat acme_srv/version.py | grep -i __version__ | head -n 1 | sed 's/__version__ = //g' | sed s/\'//g) >> $GITHUB_ENV - - run: echo "Latest tag is ${{ env.TAG_NAME }}" - - - name: update version number in spec file - run: | - # sudo sed -i "s/Source0:.*/Source0: %{name}-%{version}.tar.gz/g" examples/install_scripts/rpm/acme2certifier.spec - sudo sed -i "s/__version__/${{ env.TAG_NAME }}/g" examples/install_scripts/rpm/acme2certifier.spec - cat examples/install_scripts/rpm/acme2certifier.spec + uses: actions/checkout@v4 - - name: build RPM package - id: rpm - uses: grindsa/rpmbuild@alma9 + - name: "Prepare Alma environment" + uses: ./.github/actions/rpm_prep with: - spec_file: "examples/install_scripts/rpm/acme2certifier.spec" + GH_SBOM_USER: ${{ secrets.GH_SBOM_USER }} + GH_SBOM_TOKEN: ${{ secrets.GH_SBOM_TOKEN }} + RH_VERSION: ${{ matrix.rhversion }} - - run: echo "path is ${{ steps.rpm.outputs.rpm_dir_path }}" - - - name: "[ PREPARE ] setup environment for alma installation" - run: | - docker network create acme - sudo mkdir -p data - sudo chmod -R 777 data - sudo cp ${{ steps.rpm.outputs.rpm_dir_path }}noarch/acme2certifier-${{ env.TAG_NAME }}-1.0.noarch.rpm data - sudo cp examples/Docker/almalinux-systemd/rpm_tester.sh data - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - mkdir -p data/acme_ca - sudo cp test/ca/certsrv_ca_certs.pem data/acme_ca/ca_certs.pem - sudo touch data/acme_srv.cfg - sudo chmod 777 data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler_dns.cfg > data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> data/acme_srv.cfg - sudo echo "profile_id: 101" >> data/acme_srv.cfg - env: + - name: "Prepare acme_srv.cfg with certifier_ca_handler" + uses: ./.github/actions/wf_specific/certifier_ca_handler/certifier_setup_no_profile + with: + WCCE_SSH_ACCESS_KEY: ${{ secrets.WCCE_SSH_ACCESS_KEY }} + WCCE_SSH_KNOWN_HOSTS: ${{ secrets.WCCE_SSH_KNOWN_HOSTS }} + WCCE_SSH_USER: ${{ secrets.WCCE_SSH_USER }} + WCCE_SSH_HOST: ${{ secrets.WCCE_SSH_HOST }} + WCCE_SSH_PORT: ${{ secrets.WCCE_SSH_PORT }} NCM_API_HOST: ${{ secrets.NCM_API_HOST }} NCM_API_USER: ${{ secrets.NCM_API_USER }} NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} + ACME_SRV_SRC: .github/openssl_ca_handler.py_acme_srv_default_handler_dns.cfg + DATA_PATH: data - - name: "[ PREPARE ] prepare acme.sh container" + - name: "Prepare acme.sh container" run: | docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon sudo cp .github/dns_test.sh acme-sh/ @@ -191,50 +179,45 @@ jobs: docker exec -i acme-sh mv /acme.sh/dns_test.sh /root/.acme.sh/dnsapi/ docker exec -i acme-sh chmod +x /root/.acme.sh/dnsapi/dns_test.sh - - name: "[ PREPARE ] set DNS server" + - name: "Set DNS server" run: | docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' acme-sh sudo sed -i "s/DNS-IP/$(docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' acme-sh)/g" data/acme_srv.cfg - - name: "[ PREPARE ] Almalinux instance" - run: | - cat examples/Docker/almalinux-systemd/Dockerfile | docker build -t almalinux-systemd -f - . --no-cache - docker run -d -id --privileged --network acme --name=acme-srv -v "$(pwd)/data":/tmp/acme2certifier almalinux-systemd - - - name: "[ RUN ] Execute install scipt" + - name: "Execute install scipt" run: | docker exec acme-srv sh /tmp/acme2certifier/rpm_tester.sh - - name: "Test http://acme-srv/directory is accessable" + - name: "Test http://acme-srv/directory is accessible" run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - name: "[ ENROLL ] acme.sh - single domain" + - name: "Enroll acme.sh - single domain" run: | docker exec -i acme-sh acme.sh --dnssleep 10 --server http://acme-srv --accountemail 'acme-sh@example.com' --issue --dns dns_test -d acme-sh.single --standalone --debug 3 --output-insecure --force awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.single_ecc/ca.cer openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.single_ecc/acme-sh.single.cer - - name: "[ ENROLL ] acme.sh - two domains" + - name: "Enroll acme.sh - two domains" run: | docker exec -i acme-sh acme.sh --dnssleep 10 --server http://acme-srv --accountemail 'acme-sh@example.com' --issue --dns dns_test -d acme-sh.first --dns dns_test -d acme-sh.second --standalone --debug 3 --output-insecure --force openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.first_ecc/acme-sh.first.cer - - name: "[ ENROLL ] acme.sh - single wildcard domain" + - name: "Enroll acme.sh - single wildcard domain" run: | docker exec -i acme-sh acme.sh --dnssleep 10 --server http://acme-srv --accountemail 'acme-sh@example.com' --issue --dns dns_test -d *.acme-sh.wildcard --standalone --debug 3 --output-insecure --force openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/*acme-sh.wildcard_ecc/*acme-sh.wildcard.cer - - name: "[ ENROLL ] acme.sh - double wildcard domain" + - name: "Enroll acme.sh - double wildcard domain" run: | docker exec -i acme-sh acme.sh --dnssleep 10 --server http://acme-srv --accountemail 'acme-sh@example.com' --issue --dns dns_test -d *.acme-sh.first-wildcard --dns dns_test -d *.acme-sh.second-wildcard --standalone --debug 3 --output-insecure --force openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/*.acme-sh.first-wildcard_ecc/*.acme-sh.first-wildcard.cer - - name: "[ ENROLL ] acme.sh - domain and wildcard domain" + - name: "Enroll acme.sh - domain and wildcard domain" run: | docker exec -i acme-sh acme.sh --dnssleep 10 --server http://acme-srv --accountemail 'acme-sh@example.com' --issue --dns dns_test -d acme-sh.fqdn-wildcard --dns dns_test -d *.acme-sh.fqdn-wildcard --standalone --debug 3 --output-insecure --force openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.fqdn-wildcard_ecc/acme-sh.fqdn-wildcard.cer - - name: "[ Test ] check TXT record exists" + - name: "check TXT record exists" if: ${{ failure() }} run: | docker exec -i acme-sh ps -a @@ -254,13 +237,16 @@ jobs: mkdir -p ${{ github.workspace }}/artifact/upload docker exec acme-srv tar cvfz /tmp/acme2certifier/a2c.tgz /opt/acme2certifier sudo cp -rp data/ ${{ github.workspace }}/artifact/data/ + sudo rm ${{ github.workspace }}/artifact/data/*.rpm sudo cp -rp acme-sh/ ${{ github.workspace }}/artifact/acme-sh/ + docker exec acme-srv cat /etc/nginx/nginx.conf.orig > ${{ github.workspace }}/artifact/data/nginx.conf.orig + docker exec acme-srv cat /etc/nginx/nginx.conf > ${{ github.workspace }}/artifact/data/nginx.conf docker exec acme-srv cat /var/log/messages > ${{ github.workspace }}/artifact/acme-srv.log sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz data acme-srv.log acme-sh - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: ${{ failure() }} with: - name: dns_challenge_tests_rpm.tar.gz + name: dns-rpm-rh${{ matrix.rhversion }}.tar.gz path: ${{ github.workspace }}/artifact/upload/ diff --git a/.github/workflows/eab-test.yml b/.github/workflows/eab-test.yml index a3dad9bf..4ae971d5 100644 --- a/.github/workflows/eab-test.yml +++ b/.github/workflows/eab-test.yml @@ -12,119 +12,120 @@ jobs: eab_apache2_wsgi: name: "eab_apache2_wsgi" runs-on: ubuntu-latest + strategy: + fail-fast: false + max-parallel: 2 + matrix: + websrv: ['apache2', 'nginx'] + dbhandler: ['wsgi', 'django'] steps: - name: "checkout GIT" - uses: actions/checkout@v3 + uses: actions/checkout@v4 - - name: "[ PREPARE ] Build docker-compose (apache2_wsgi)" - working-directory: examples/Docker/ + - name: "Build container" + uses: ./.github/actions/container_prep + with: + DB_HANDLER: ${{ matrix.dbhandler }} + WEB_SRV: ${{ matrix.websrv }} + + - name: "Create letsencrypt folder" run: | - sudo mkdir -p data - docker network create acme - docker-compose up -d - docker-compose logs + mkdir -p certbot + mkdir -p lego + mkdir -p acme-sh - - name: "Test http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory + - name: "Prepare acme_srv.cfg with certifier_ca_handler" + uses: ./.github/actions/wf_specific/certifier_ca_handler/certifier_setup_no_profile + with: + WCCE_SSH_ACCESS_KEY: ${{ secrets.WCCE_SSH_ACCESS_KEY }} + WCCE_SSH_KNOWN_HOSTS: ${{ secrets.WCCE_SSH_KNOWN_HOSTS }} + WCCE_SSH_USER: ${{ secrets.WCCE_SSH_USER }} + WCCE_SSH_HOST: ${{ secrets.WCCE_SSH_HOST }} + WCCE_SSH_PORT: ${{ secrets.WCCE_SSH_PORT }} + NCM_API_HOST: ${{ secrets.NCM_API_HOST }} + NCM_API_USER: ${{ secrets.NCM_API_USER }} + NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} + NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} + DATA_PATH: examples/Docker/data - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" + - name: "Restart a2c" run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg sudo echo -e "\n\n[EABhandler]" >> examples/Docker/data/acme_srv.cfg sudo echo "eab_handler_file: /var/www/acme2certifier/examples/eab_handler/json_handler.py" >> examples/Docker/data/acme_srv.cfg sudo echo "key_file: examples/eab_handler/key_file.json" >> examples/Docker/data/acme_srv.cfg cd examples/Docker/ docker-compose restart - docker-compose logs - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - name: "Test http://acme-srv/directory is accessable again" + - name: "Sleep for 10s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 10s + + - name: "Test http://acme-srv/directory is accessible" run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - name: "[ PREPARE ] create letsencrypt folder" + - name: "Test if https://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory + + - name: "Fail - Register lego" + id: legofail + continue-on-error: true run: | - mkdir certbot + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --http run - - name: "[ FAIL ] certbot without eab-credentials" + - name: "Check lego result" + if: steps.legofail.outcome != 'failure' + run: | + echo "legofail outcome is ${{steps.legofail.outcome }}" + exit 1 + + - name: "Enroll lego" + run: | + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_02 --hmac dGhpc19pc19hX3ZlcnlfbG9uZ19obWFjX3RvX21ha2Vfc3VyZV90aGF0X2l0c19tb3JlX3RoYW5fMjU2X2JpdHM -d lego.acme --http run + sudo cat lego/certificates/lego.acme.issuer.crt | awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + + - name: "Fail - Registercertbot without eab-credentials" id: certbotfail continue-on-error: true run: | docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email - - name: "[ CHECK ] certbot result " + - name: "check certbot result " if: steps.certbotfail.outcome != 'failure' run: | echo "certbot outcome is ${{steps.certbotfail.outcome }}" exit 1 - - name: "[ REGISTER] certbot" + - name: "Register certbot using eab-credentials" run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email --eab-kid keyid_02 --eab-hmac-key=bWFjXzAy + docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email --eab-kid keyid_02 --eab-hmac-key=dGhpc19pc19hX3ZlcnlfbG9uZ19obWFjX3RvX21ha2Vfc3VyZV90aGF0X2l0c19tb3JlX3RoYW5fMjU2X2JpdHM - - name: "[ ENROLL ] HTTP-01 single domain certbot" + - name: "Enroll HTTP-01 single domain certbot" run: | docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot - sudo chmod 777 certbot/archive/certbot/chain1.pem - sudo cp certbot/archive/certbot/chain1.pem chain1.pem - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < chain1.pem sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem - - name: "[ PREPARE ] prepare acme.sh container" - run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ FAIL] acme.sh" + - name: "Fail - Register acme.sh" id: acmeshfail continue-on-error: true run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --debug 3 - - name: "[ CHECK ] acme.sh result " + - name: "Check acme.sh result " if: steps.acmeshfail.outcome != 'failure' run: | echo "acmeshfail outcome is ${{steps.acmeshfail.outcome }}" exit 1 - - name: "[ REGISTER] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --eab-kid keyid_02 --eab-hmac-key bWFjXzAy --debug 3 - - - name: "[ ENROLL] acme.sh" + - name: "Register acme.sh with eab-credentials" run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --issue -d acme-sh.acme --standalone --debug 3 --output-insecure - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_02 --eab-hmac-key dGhpc19pc19hX3ZlcnlfbG9uZ19obWFjX3RvX21ha2Vfc3VyZV90aGF0X2l0c19tb3JlX3RoYW5fMjU2X2JpdHM --debug 3 - - name: "[ FAIL ] lego" - id: legofail - continue-on-error: true + - name: "Enroll acme.sh" run: | - mkdir lego - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --http run - - - name: "[ CHECK ] lego result " - if: steps.legofail.outcome != 'failure' - run: | - echo "legofail outcome is ${{steps.legofail.outcome }}" - exit 1 - - - name: "[ ENROLL ] lego" - run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_02 --hmac bWFjXzAy -d lego.acme --http run - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv -d acme-sh.acme --standalone --debug 3 --output-insecure + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - name: "[ * ] collecting test logs" if: ${{ failure() }} @@ -136,65 +137,56 @@ jobs: sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: ${{ failure() }} with: - name: eab-${{ matrix.keylength }}.tar.gz + name: eab-${{ matrix.websrv }}-${{ matrix.dbhandler }}.tar.gz path: ${{ github.workspace }}/artifact/upload/ - eab_apache2_wsgi_rpm: - name: "eab_apache2_wsgi_rpm" + eab_rpm: + name: "eab_rpm" runs-on: ubuntu-latest + strategy: + fail-fast: false + max-parallel: 1 + matrix: + rhversion: [8, 9] + execscript: ['rpm_tester.sh', 'django_tester.sh'] steps: - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: Retrieve Version from version.py - run: | - echo TAG_NAME=$(cat acme_srv/version.py | grep -i __version__ | head -n 1 | sed 's/__version__ = //g' | sed s/\'//g) >> $GITHUB_ENV - - run: echo "Latest tag is ${{ env.TAG_NAME }}" - - - name: update version number in spec file - run: | - # sudo sed -i "s/Source0:.*/Source0: %{name}-%{version}.tar.gz/g" examples/install_scripts/rpm/acme2certifier.spec - sudo sed -i "s/__version__/${{ env.TAG_NAME }}/g" examples/install_scripts/rpm/acme2certifier.spec - cat examples/install_scripts/rpm/acme2certifier.spec + uses: actions/checkout@v4 - - name: build RPM package - id: rpm - uses: grindsa/rpmbuild@alma9 + - name: "Prepare Alma environment" + uses: ./.github/actions/rpm_prep with: - spec_file: "examples/install_scripts/rpm/acme2certifier.spec" - - - run: echo "path is ${{ steps.rpm.outputs.rpm_dir_path }}" + GH_SBOM_USER: ${{ secrets.GH_SBOM_USER }} + GH_SBOM_TOKEN: ${{ secrets.GH_SBOM_TOKEN }} + RH_VERSION: ${{ matrix.rhversion }} - - name: "[ PREPARE ] setup environment for alma installation" + - name: "Create letsencrypt and lego folder" run: | - docker network create acme - sudo mkdir -p data - sudo chmod -R 777 data - sudo cp ${{ steps.rpm.outputs.rpm_dir_path }}noarch/acme2certifier-${{ env.TAG_NAME }}-1.0.noarch.rpm data - sudo cp examples/Docker/almalinux-systemd/rpm_tester.sh data + sudo mkdir -p acme-sh + sudo mkdir -p certbot + sudo mkdir -p lego - - name: "[ PREPARE ] create letsencrypt and lego folder" - run: | - mkdir certbot - mkdir lego + - name: "Prepare acme_srv.cfg with certifier_ca_handler" + if: matrix.execscript == 'rpm_tester.sh' + uses: ./.github/actions/wf_specific/certifier_ca_handler/certifier_setup_no_profile + with: + WCCE_SSH_ACCESS_KEY: ${{ secrets.WCCE_SSH_ACCESS_KEY }} + WCCE_SSH_KNOWN_HOSTS: ${{ secrets.WCCE_SSH_KNOWN_HOSTS }} + WCCE_SSH_USER: ${{ secrets.WCCE_SSH_USER }} + WCCE_SSH_HOST: ${{ secrets.WCCE_SSH_HOST }} + WCCE_SSH_PORT: ${{ secrets.WCCE_SSH_PORT }} + NCM_API_HOST: ${{ secrets.NCM_API_HOST }} + NCM_API_USER: ${{ secrets.NCM_API_USER }} + NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} + NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} + DATA_PATH: data - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" + - name: "Enable EABhandler" + if: matrix.execscript == 'rpm_tester.sh' run: | - mkdir -p data/acme_ca - sudo cp test/ca/certsrv_ca_certs.pem data/acme_ca/ca_certs.pem - sudo touch data/acme_srv.cfg - sudo chmod 777 data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > data/acme_srv.cfg - sudo echo "handler_file: /opt/acme2certifier/examples/ca_handler/certifier_ca_handler.py" >> data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> data/acme_srv.cfg - sudo echo "profile_id: 101" >> data/acme_srv.cfg sudo echo -e "\n\n[EABhandler]" >> data/acme_srv.cfg sudo echo "eab_handler_file: /opt/acme2certifier/examples/eab_handler/json_handler.py" >> data/acme_srv.cfg sudo echo "key_file: /opt/acme2certifier/examples/eab_handler/key_file.json" >> data/acme_srv.cfg @@ -205,84 +197,104 @@ jobs: NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - name: "[ PREPARE ] Almalinux instance" + - name: "Prepare acme_srv.cfg with certifier_ca_handler" + if: matrix.execscript == 'django_tester.sh' + uses: ./.github/actions/wf_specific/certifier_ca_handler/certifier_setup_no_profile + with: + WCCE_SSH_ACCESS_KEY: ${{ secrets.WCCE_SSH_ACCESS_KEY }} + WCCE_SSH_KNOWN_HOSTS: ${{ secrets.WCCE_SSH_KNOWN_HOSTS }} + WCCE_SSH_USER: ${{ secrets.WCCE_SSH_USER }} + WCCE_SSH_HOST: ${{ secrets.WCCE_SSH_HOST }} + WCCE_SSH_PORT: ${{ secrets.WCCE_SSH_PORT }} + NCM_API_HOST: ${{ secrets.NCM_API_HOST }} + NCM_API_USER: ${{ secrets.NCM_API_USER }} + NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} + NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} + DATA_PATH: data/volume + + - name: "Enable EABhandler" + if: matrix.execscript == 'django_tester.sh' run: | - cat examples/Docker/almalinux-systemd/Dockerfile | docker build -t almalinux-systemd -f - . --no-cache - docker run -d -id --privileged --network acme --name=acme-srv -v "$(pwd)/data":/tmp/acme2certifier almalinux-systemd + sudo echo -e "\n\n[EABhandler]" >> data/volume/acme_srv.cfg + sudo echo "eab_handler_file: /opt/acme2certifier/examples/eab_handler/json_handler.py" >>data/volume/acme_srv.cfg + sudo echo "key_file: /opt/acme2certifier/examples/eab_handler/key_file.json" >> data/volume/acme_srv.cfg - - name: "[ RUN ] Execute install scipt" + - name: "Execute install scipt" run: | - docker exec acme-srv sh /tmp/acme2certifier/rpm_tester.sh + docker exec acme-srv sh /tmp/acme2certifier/$EXEC_SCRIPT + env: + EXEC_SCRIPT: ${{ matrix.execscript }} + + - name: "Sleep for 10s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 10s - name: "Test http://acme-srv/directory is accessible" run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - name: "[ FAIL ] certbot without eab-credentials" + - name: "Test if https://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory + + - name: "Fail - Register lego" + id: legofail + continue-on-error: true + run: | + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --http run + + - name: "Check lego result" + if: steps.legofail.outcome != 'failure' + run: | + echo "legofail outcome is ${{steps.legofail.outcome }}" + exit 1 + + - name: "Enroll lego" + run: | + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_02 --hmac dGhpc19pc19hX3ZlcnlfbG9uZ19obWFjX3RvX21ha2Vfc3VyZV90aGF0X2l0c19tb3JlX3RoYW5fMjU2X2JpdHM -d lego.acme --http run + sudo cat lego/certificates/lego.acme.issuer.crt | awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + + - name: "Fail - Registercertbot without eab-credentials" id: certbotfail continue-on-error: true run: | docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email - - name: "[ CHECK ] certbot result " + - name: "check certbot result " if: steps.certbotfail.outcome != 'failure' run: | echo "certbot outcome is ${{steps.certbotfail.outcome }}" exit 1 - - name: "[ REGISTER] certbot" + - name: "Register certbot using eab-credentials" run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email --eab-kid keyid_02 --eab-hmac-key=bWFjXzAy + docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email --eab-kid keyid_02 --eab-hmac-key=dGhpc19pc19hX3ZlcnlfbG9uZ19obWFjX3RvX21ha2Vfc3VyZV90aGF0X2l0c19tb3JlX3RoYW5fMjU2X2JpdHM - - name: "[ ENROLL ] HTTP-01 single domain certbot" + - name: "Enroll HTTP-01 single domain certbot" run: | docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot - sudo chmod 777 certbot/archive/certbot/chain1.pem - sudo cp certbot/archive/certbot/chain1.pem chain1.pem - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < chain1.pem sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem - - name: "[ PREPARE ] prepare acme.sh container" - run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ FAIL] acme.sh" + - name: "Fail - Register acme.sh" id: acmeshfail continue-on-error: true run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --debug 3 - - name: "[ CHECK ] acme.sh result " + - name: "Check acme.sh result " if: steps.acmeshfail.outcome != 'failure' run: | echo "acmeshfail outcome is ${{steps.acmeshfail.outcome }}" exit 1 - - name: "[ REGISTER] acme.sh" + - name: "Register acme.sh with eab-credentials" run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --eab-kid keyid_02 --eab-hmac-key bWFjXzAy --debug 3 + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --register-account --server http://acme-srv --accountemail 'acme-sh@example.com' --eab-kid keyid_02 --eab-hmac-key dGhpc19pc19hX3ZlcnlfbG9uZ19obWFjX3RvX21ha2Vfc3VyZV90aGF0X2l0c19tb3JlX3RoYW5fMjU2X2JpdHM --debug 3 - - name: "[ ENROLL] acme.sh" + - name: "Enroll acme.sh" run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --issue -d acme-sh.acme --standalone --debug 3 --output-insecure - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - - name: "[ FAIL ] lego" - id: legofail - continue-on-error: true - run: | - mkdir lego - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --http run - - - name: "[ CHECK ] lego result " - if: steps.legofail.outcome != 'failure' - run: | - echo "legofail outcome is ${{steps.legofail.outcome }}" - exit 1 - - - name: "[ ENROLL ] lego" - run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" --eab --kid keyid_02 --hmac bWFjXzAy -d lego.acme --http run - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + docker run --rm -i -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest --issue --server http://acme-srv -d acme-sh.acme --standalone --debug 3 --output-insecure + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - name: "[ * ] collecting test logs" if: ${{ failure() }} @@ -291,12 +303,16 @@ jobs: docker exec acme-srv tar cvfz /tmp/acme2certifier/a2c.tgz /opt/acme2certifier sudo cp -rp data/ ${{ github.workspace }}/artifact/data/ sudo cp -rp acme-sh/ ${{ github.workspace }}/artifact/acme-sh/ + sudo rm ${{ github.workspace }}/artifact/data/*.rpm + docker exec acme-srv cat /etc/nginx/nginx.conf.orig > ${{ github.workspace }}/artifact/data/nginx.conf.orig + docker exec acme-srv cat /etc/nginx/nginx.conf > ${{ github.workspace }}/artifact/data/nginx.conf docker exec acme-srv cat /var/log/messages > ${{ github.workspace }}/artifact/acme-srv.log sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz data acme-srv.log acme-sh - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: ${{ failure() }} with: - name: eab-rpm.tar.gz + name: eab-rpm-{{ matrix.execscript }}-rh${{ matrix.rhversion }}.tar.gz path: ${{ github.workspace }}/artifact/upload/ + diff --git a/.github/workflows/enrollment-timeout.yml b/.github/workflows/enrollment-timeout.yml deleted file mode 100644 index 9d84a0ea..00000000 --- a/.github/workflows/enrollment-timeout.yml +++ /dev/null @@ -1,121 +0,0 @@ -name: Asynchronous enrollment and certificate reusage - -on: - push: - pull_request: - branches: [ devel ] - schedule: - # * is a special character in YAML so you have to quote this string - - cron: '0 2 * * 6' - -jobs: - async_enrollment_cert_reusage: - name: "Async_enrollment_cert_reusage" - runs-on: ubuntu-latest - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "[ PREPARE ] Build docker-compose (apache2_wsgi)" - working-directory: examples/Docker/ - run: | - sudo mkdir -p data - docker network create acme - docker-compose up -d - docker-compose logs - - - name: "Test http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - # sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - sudo sed -i "s/revocation_reason_check_disable: False/revocation_reason_check_disable: False\\ncert_reusage_timeframe: 300/g" examples/Docker/data/acme_srv.cfg - sudo cp examples/ca_handler/certifier_ca_handler.py examples/Docker/data/ca_handler.py - sudo sed -i "s/ cert_dic = self._cert_get(csr)/ cert_dic = self._cert_get(csr)\\n time.sleep(30)/g" examples/Docker/data/ca_handler.py - cd examples/Docker/ - docker-compose restart - docker-compose logs - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ ENROLL ] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --keylength 2048 --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --standalone --debug 3 --output-insecure - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh//acme-sh.acme/ca.cer - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme/acme-sh.acme.cer - - - name: "[ VERIFY ] Check timeout" - working-directory: examples/Docker/ - run: | - docker-compose logs | grep "Certificate.enroll_and_store() ended with: None:timeout" - sudo truncate -s 0 $(docker inspect --format='{{.LogPath}}' acme2certifier_acme-srv_1) - - - name: "[ ENROLL ] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --keylength 2048 --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --standalone --debug 3 --output-insecure --force - - - name: "[ VERIFY ] Check certificate reusage" - working-directory: examples/Docker/ - run: | - docker-compose logs | grep "Certificate._enroll(): reuse existing certificate" - - - name: "[ ENROL] lego" - run: | - mkdir lego - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --cert.timeout 150 --http run - - - name: "[ VERIFY ] Check timeout" - working-directory: examples/Docker/ - run: | - docker-compose logs | grep "Certificate.enroll_and_store() ended with: None:timeout" - sudo truncate -s 0 $(docker inspect --format='{{.LogPath}}' acme2certifier_acme-srv_1) - - - name: "[ REGISTER ] certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email - - - name: "[ ENROLL ] certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot - - - name: "[ VERIFY ] Check timeout" - working-directory: examples/Docker/ - run: | - docker-compose logs | grep "Certificate.enroll_and_store() ended with: None:timeout" - sudo truncate -s 0 $(docker inspect --format='{{.LogPath}}' acme2certifier_acme-srv_1) - - - - name: "[ * ] collecting test data" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp acme-sh/ ${{ github.workspace }}/artifact/acme-sh/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data acme-sh - - - name: "[ * ] uploading artifacts" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: async_enrollment_cert_reusage.tar.gz - path: ${{ github.workspace }}/artifact/upload/ diff --git a/.github/workflows/hooks-test.yml b/.github/workflows/hooks-test.yml index 9a874eff..f4ed5cf1 100644 --- a/.github/workflows/hooks-test.yml +++ b/.github/workflows/hooks-test.yml @@ -5,49 +5,94 @@ on: pull_request: branches: [ devel ] schedule: - # * is a special character in YAML so you have to quote this string - cron: '0 2 * * 6' jobs: - hooks_test: - name: "hooks_test" + + container_build: + name: "container_build" runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + websrv: ['apache2', 'nginx'] + dbhandler: ['wsgi', 'django'] + steps: - name: "checkout GIT" - uses: actions/checkout@v3 + uses: actions/checkout@v4 + + - name: "Build container" + uses: ./.github/actions/container_build_upload + with: + DB_HANDLER: ${{ matrix.dbhandler }} + WEB_SRV: ${{ matrix.websrv }} - - name: "[ PREPARE ] Build docker-compose (apache2_wsgi)" - working-directory: examples/Docker/ + hooks_tests: + name: "hooks_tests" + runs-on: ubuntu-latest + needs: container_build + strategy: + fail-fast: false + max-parallel: 2 + matrix: + websrv: ['apache2', 'nginx'] + dbhandler: ['wsgi', 'django'] + + steps: + - name: "checkout GIT" + uses: actions/checkout@v4 + + - name: "Download container" + uses: actions/download-artifact@v4 + with: + name: a2c-${{ github.run_id }}.${{ matrix.websrv }}.${{ matrix.dbhandler }}.tar.gz + path: /tmp + + - name: "Import container" run: | - sudo mkdir -p data/hooks - sudo chmod -R 777 data/hooks - docker network create acme - docker-compose up -d - docker-compose logs + sudo apt-get install -y docker-compose + gunzip /tmp/a2c-${{ github.run_id }}.${{ matrix.websrv }}.${{ matrix.dbhandler }}.tar.gz + docker load -i /tmp/a2c-${{ github.run_id }}.${{ matrix.websrv }}.${{ matrix.dbhandler }}.tar + docker images - - name: "Test http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory + - name: "Prepare container environment" + uses: ./.github/actions/container_prep + with: + DB_HANDLER: ${{ matrix.dbhandler }} + WEB_SRV: ${{ matrix.websrv }} + CONTAINER_BUILD: false - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg + - name: "Bring up a2c container" + uses: ./.github/actions/container_up + with: + DB_HANDLER: ${{ matrix.dbhandler }} + WEB_SRV: ${{ matrix.websrv }} + + - name: "Prepare acme_srv.cfg with certifier_ca_handler" + uses: ./.github/actions/wf_specific/certifier_ca_handler/certifier_setup_no_profile + with: + WCCE_SSH_ACCESS_KEY: ${{ secrets.WCCE_SSH_ACCESS_KEY }} + WCCE_SSH_KNOWN_HOSTS: ${{ secrets.WCCE_SSH_KNOWN_HOSTS }} + WCCE_SSH_USER: ${{ secrets.WCCE_SSH_USER }} + WCCE_SSH_HOST: ${{ secrets.WCCE_SSH_HOST }} + WCCE_SSH_PORT: ${{ secrets.WCCE_SSH_PORT }} + NCM_API_HOST: ${{ secrets.NCM_API_HOST }} + NCM_API_USER: ${{ secrets.NCM_API_USER }} + NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} + NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} + DATA_PATH: examples/Docker/data + + - name: "Restart a2c" + run: | + sudo mkdir -p examples/Docker/data/hooks + sudo chmod -R 777 examples/Docker/data/hooks sudo echo -e "\n\n[Hooks]" >> examples/Docker/data/acme_srv.cfg sudo echo "hooks_file: /var/www/acme2certifier/examples/hooks/cn_dump_hooks.py" >> examples/Docker/data/acme_srv.cfg sudo echo "save_path: volume/hooks" >> examples/Docker/data/acme_srv.cfg sudo echo "$HOOKS_CHECKSUM" > examples/Docker/data/hooks/checksums.sha256 - # sudo cat examples/Docker/data/acme_srv.cfg cd examples/Docker/ docker-compose restart - docker-compose logs env: HOOKS_CHECKSUM: ${{ secrets.HOOKS_CHECKSUM }} NCM_API_HOST: ${{ secrets.NCM_API_HOST }} @@ -56,18 +101,26 @@ jobs: NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - name: "Test http://acme-srv/directory is accessable again" + - name: "Sleep for 10s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 10s + + - name: "Test http://acme-srv/directory is accessible" run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - name: "[ PREPARE ] create letsencrypt folder" + - name: "Test if https://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory + + - name: "create letsencrypt folder" run: | mkdir certbot - - name: "[ REGISTER] certbot" + - name: "Register certbot" run: | docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email - - name: "[ ENROLL ] HTTP-01 single domain certbot" + - name: "Enroll HTTP-01 single domain certbot" run: | docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot sudo chmod 777 certbot/archive/certbot/chain1.pem @@ -75,30 +128,36 @@ jobs: awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < chain1.pem sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem - - name: "[ PREPARE ] prepare acme.sh container" + - name: "Prepare acme.sh container" run: | docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - name: "[ REGISTER] acme.sh" + - name: "Register acme.sh" run: | docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --debug 3 - - name: "[ ENROLL] acme.sh" + - name: "Enroll acme.sh" run: | docker exec -i acme-sh acme.sh --server http://acme-srv --issue -d acme-sh.acme --standalone --debug 3 --output-insecure awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - name: "[ ENROLL ] lego" + - name: "Enroll lego" run: | docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --http run sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt - - name: "[ CHECK ] compare checksums to validate hook file content" + - name: "Check compare checksums to validate hook file content" working-directory: examples/Docker/data/hooks run: | sha256sum -c checksums.sha256 + - name: "Check container configuration" + uses: ./.github/actions/container_check + with: + DB_HANDLER: ${{ matrix.dbhandler }} + WEB_SRV: ${{ matrix.websrv }} + - name: "[ * ] collecting test logs" if: ${{ failure() }} run: | @@ -109,180 +168,80 @@ jobs: sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: ${{ failure() }} with: - name: hooks.tar.gz + name: hooks-${{ matrix.websrv }}-${{ matrix.dbhandler }}.tar.gz path: ${{ github.workspace }}/artifact/upload/ - hooks_test_rpm: - name: "hooks_test_rpm" + hooks_exception_handling: + name: "hooks_exception_handling" runs-on: ubuntu-latest + needs: container_build + strategy: + fail-fast: false + max-parallel: 2 + matrix: + websrv: ['apache2', 'nginx'] + dbhandler: ['wsgi', 'django'] steps: - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: Retrieve Version from version.py - run: | - echo TAG_NAME=$(cat acme_srv/version.py | grep -i __version__ | head -n 1 | sed 's/__version__ = //g' | sed s/\'//g) >> $GITHUB_ENV - - run: echo "Latest tag is ${{ env.TAG_NAME }}" + uses: actions/checkout@v4 - - name: update version number in spec file + - name: "Create folders" run: | - # sudo sed -i "s/Source0:.*/Source0: %{name}-%{version}.tar.gz/g" examples/install_scripts/rpm/acme2certifier.spec - sudo sed -i "s/__version__/${{ env.TAG_NAME }}/g" examples/install_scripts/rpm/acme2certifier.spec - cat examples/install_scripts/rpm/acme2certifier.spec + mkdir lego + mkdir acme-sh + mkdir certbot - - name: build RPM package - id: rpm - uses: grindsa/rpmbuild@alma9 + - name: "Download container" + uses: actions/download-artifact@v4 with: - spec_file: "examples/install_scripts/rpm/acme2certifier.spec" + name: a2c-${{ github.run_id }}.${{ matrix.websrv }}.${{ matrix.dbhandler }}.tar.gz + path: /tmp - - run: echo "path is ${{ steps.rpm.outputs.rpm_dir_path }}" - - - name: "[ PREPARE ] setup environment for alma installation" + - name: "Import container" run: | - docker network create acme - sudo mkdir -p data - sudo chmod -R 777 data - sudo cp ${{ steps.rpm.outputs.rpm_dir_path }}noarch/acme2certifier-${{ env.TAG_NAME }}-1.0.noarch.rpm data - sudo cp examples/Docker/almalinux-systemd/rpm_tester.sh data + sudo apt-get install -y docker-compose + gunzip /tmp/a2c-${{ github.run_id }}.${{ matrix.websrv }}.${{ matrix.dbhandler }}.tar.gz + docker load -i /tmp/a2c-${{ github.run_id }}.${{ matrix.websrv }}.${{ matrix.dbhandler }}.tar + docker images - - name: "[ PREPARE ] create letsencrypt and lego folder" - run: | - mkdir acmme-sh - mkdir lego + - name: "Prepare container environment" + uses: ./.github/actions/container_prep + with: + DB_HANDLER: ${{ matrix.dbhandler }} + WEB_SRV: ${{ matrix.websrv }} + CONTAINER_BUILD: false - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - mkdir -p data/acme_ca - sudo cp test/ca/certsrv_ca_certs.pem data/acme_ca/ca_certs.pem - sudo touch data/acme_srv.cfg - sudo chmod 777 data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > data/acme_srv.cfg - sudo echo "handler_file: /opt/acme2certifier/examples/ca_handler/certifier_ca_handler.py" >> data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> data/acme_srv.cfg - sudo echo "profile_id: 101" >> data/acme_srv.cfg - sudo mkdir -p data/acme_ca/hooks - sudo chmod -R 777 data/acme_ca/hooks - sudo echo -e "\n\n[Hooks]" >> data/acme_srv.cfg - sudo echo "hooks_file: /opt/acme2certifier/examples/hooks/cn_dump_hooks.py" >> data/acme_srv.cfg - sudo echo "save_path: /tmp/acme2certifier/acme_ca/hooks" >> data/acme_srv.cfg - sudo echo "$HOOKS_CHECKSUM" > data/acme_ca/hooks/checksums.sha256 - env: - HOOKS_CHECKSUM: ${{ secrets.HOOKS_CHECKSUM }} + - name: "Bring up a2c container" + uses: ./.github/actions/container_up + with: + DB_HANDLER: ${{ matrix.dbhandler }} + WEB_SRV: ${{ matrix.websrv }} + + - name: "Prepare acme_srv.cfg with certifier_ca_handler" + uses: ./.github/actions/wf_specific/certifier_ca_handler/certifier_setup_no_profile + with: + WCCE_SSH_ACCESS_KEY: ${{ secrets.WCCE_SSH_ACCESS_KEY }} + WCCE_SSH_KNOWN_HOSTS: ${{ secrets.WCCE_SSH_KNOWN_HOSTS }} + WCCE_SSH_USER: ${{ secrets.WCCE_SSH_USER }} + WCCE_SSH_HOST: ${{ secrets.WCCE_SSH_HOST }} + WCCE_SSH_PORT: ${{ secrets.WCCE_SSH_PORT }} NCM_API_HOST: ${{ secrets.NCM_API_HOST }} NCM_API_USER: ${{ secrets.NCM_API_USER }} NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "[ PREPARE ] Almalinux instance" - run: | - cat examples/Docker/almalinux-systemd/Dockerfile | docker build -t almalinux-systemd -f - . --no-cache - docker run -d -id --privileged --network acme --name=acme-srv -v "$(pwd)/data":/tmp/acme2certifier almalinux-systemd - - - name: "[ RUN ] Execute install scipt" - run: | - docker exec acme-srv sh /tmp/acme2certifier/rpm_tester.sh - - - name: "Test http://acme-srv/directory is accessible" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "[ REGISTER] certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email - - - name: "[ ENROLL ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot - sudo chmod 777 certbot/archive/certbot/chain1.pem - sudo cp certbot/archive/certbot/chain1.pem chain1.pem - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < chain1.pem - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ REGISTER] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --debug 3 - - - name: "[ ENROLL] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --issue -d acme-sh.acme --standalone --debug 3 --output-insecure - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - - name: "[ ENROLL ] lego" - run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --http run - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt - - - name: "[ CHECK ] compare checksums to validate hook file content" - working-directory: data/acme_ca/hooks - run: | - sha256sum -c checksums.sha256 - - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - docker exec acme-srv tar cvfz /tmp/acme2certifier/a2c.tgz /opt/acme2certifier - sudo cp -rp data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp acme-sh/ ${{ github.workspace }}/artifact/acme-sh/ - docker exec acme-srv cat /var/log/messages > ${{ github.workspace }}/artifact/acme-srv.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz data acme-srv.log acme-sh - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: hooks-rpm.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - - hooks_exception_handling: - name: "hooks_exception_handling" - runs-on: ubuntu-latest - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 + DATA_PATH: examples/Docker/data - - name: "[ PREPARE ] Build docker-compose (apache2_wsgi)" - working-directory: examples/Docker/ + - name: "Restart a2c" run: | - sudo mkdir -p data/hooks - sudo chmod -R 777 data/hooks - docker network create acme - docker-compose up -d - docker-compose logs - - - name: "Test http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg + sudo mkdir -p examples/Docker/data/hooks sudo echo -e "\n\n[Hooks]" >> examples/Docker/data/acme_srv.cfg sudo echo "hooks_file: /var/www/acme2certifier/examples/hooks/exception_test_hooks.py" >> examples/Docker/data/acme_srv.cfg sudo echo "raise_pre_hook_exception: False" >> examples/Docker/data/acme_srv.cfg sudo echo "raise_post_hook_exception: False" >> examples/Docker/data/acme_srv.cfg sudo echo "raise_success_hook_exception: False" >> examples/Docker/data/acme_srv.cfg - # sudo cat examples/Docker/data/acme_srv.cfg cd examples/Docker/ docker-compose restart docker-compose logs @@ -294,55 +253,63 @@ jobs: NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - name: "Test http://acme-srv/directory is accessable again" + - name: "Sleep for 10s" + uses: juliangruber/sleep-action@v2.0.3 + with: + time: 10s + + - name: "Test http://acme-srv/directory is accessible" run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - name: "[ PREPARE ] prepare acme.sh container" + - name: "Test if https://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory + + - name: "Prepare acme.sh container" run: | docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - name: "[ REGISTER] acme.sh" + - name: "Register acme.sh" run: | docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --debug 3 - - name: "[ ENROLL] acme.sh - *_pre_hook_failure not configured " + - name: "Enroll acme.sh - *_pre_hook_failure not configured " run: | docker exec -i acme-sh acme.sh --server http://acme-srv --issue -d acme-sh.acme --standalone --debug 3 --output-insecure awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - name: "[ PREPARE ] reconfigure hook handler to trigger pre hook exception " + - name: "Reconfigure hook handler to trigger pre hook exception " run: | sudo sed -i "s/raise_pre_hook_exception: False/raise_pre_hook_exception: True/g" examples/Docker/data/acme_srv.cfg cd examples/Docker/ sudo truncate -s 0 $(docker inspect --format='{{.LogPath}}' acme2certifier_acme-srv_1) docker-compose restart - - name: "[ FAIL ] acme.sh enrollment fails due to pre-hook exception (default behaviour)" + - name: "acme.sh enrollment fails due to pre-hook exception (default behaviour)" id: prehookfailure continue-on-error: true run: | docker exec -i acme-sh acme.sh --server http://acme-srv --issue -d acme-sh.acme --standalone --force --debug 3 --output-insecure - - name: "[ CHECK ] result - acme.sh enrollment failed due to pre-hook exception " + - name: "Check result - acme.sh enrollment failed due to pre-hook exception " if: steps.prehookfailure.outcome != 'failure' run: | echo "prehookfailure outcome is ${{steps.prehookfailure.outcome }}" exit 1 - - name: "[ PREPARE ] reconfigure a2c to ignore pre-hook failures " + - name: "Reconfigure a2c to ignore pre-hook failures " run: | sudo echo "ignore_pre_hook_failure: True" >> examples/Docker/data/acme_srv.cfg cd examples/Docker/ sudo truncate -s 0 $(docker inspect --format='{{.LogPath}}' acme2certifier_acme-srv_1) docker-compose restart - - name: "[ ENROLL] acme.sh - ignore pre_hook_failures " + - name: "Enroll acme.sh - ignore pre_hook_failures " run: | docker exec -i acme-sh acme.sh --server http://acme-srv --issue -d acme-sh.acme --standalone --force --debug 3 --output-insecure openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - name: "[ PREPARE ] reconfigure hook handler to trigger success hook exception " + - name: "Reconfigure hook handler to trigger success hook exception " run: | sudo sed -i "s/raise_pre_hook_exception: True/raise_pre_hook_exception: False/g" examples/Docker/data/acme_srv.cfg sudo sed -i "s/raise_success_hook_exception: False/raise_success_hook_exception: True/g" examples/Docker/data/acme_srv.cfg @@ -350,31 +317,31 @@ jobs: sudo truncate -s 0 $(docker inspect --format='{{.LogPath}}' acme2certifier_acme-srv_1) docker-compose restart - - name: "[ FAIL ] acme.sh enrollment fails due to success-hook exception (default behaviour) " + - name: "acme.sh enrollment fails due to success-hook exception (default behaviour) " id: successhookfailure continue-on-error: true run: | docker exec -i acme-sh acme.sh --server http://acme-srv --issue -d acme-sh.acme --standalone --force --debug 3 --output-insecure - - name: "[ CHECK ] result - acme.sh enrollment failed due to success-hook exception " + - name: "Check result - acme.sh enrollment failed due to success-hook exception " if: steps.successhookfailure.outcome != 'failure' run: | echo "successhookfailure outcome is ${{steps.successhookfailure.outcome }}" exit 1 - - name: "[ PREPARE ] reconfigure a2c to ignore success-hook failures " + - name: "Reconfigure a2c to ignore success-hook failures " run: | sudo sed -i "s/ignore_pre_hook_failure: True/ignore_success_hook_failure: True/g" examples/Docker/data/acme_srv.cfg cd examples/Docker/ sudo truncate -s 0 $(docker inspect --format='{{.LogPath}}' acme2certifier_acme-srv_1) docker-compose restart - - name: "[ ENROLL] acme.sh - ignore sucess_hook_failures " + - name: "Enroll acme.sh - ignore sucess_hook_failures " run: | docker exec -i acme-sh acme.sh --server http://acme-srv --issue -d acme-sh.acme --standalone --force --debug 3 --output-insecure openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - name: "[ PREPARE ] reconfigure hook handler to trigger post hook exception " + - name: "Reconfigure hook handler to trigger post hook exception " run: | sudo sed -i "s/raise_success_hook_exception: True/raise_success_hook_exception: False/g" examples/Docker/data/acme_srv.cfg sudo sed -i "s/raise_post_hook_exception: False/raise_post_hook_exception: True/g" examples/Docker/data/acme_srv.cfg @@ -382,30 +349,36 @@ jobs: sudo truncate -s 0 $(docker inspect --format='{{.LogPath}}' acme2certifier_acme-srv_1) docker-compose restart - - name: "[ ENROLL] acme.sh - ignore post_hook_failures (default behaviour) " + - name: "Enroll acme.sh - ignore post_hook_failures (default behaviour) " run: | docker exec -i acme-sh acme.sh --server http://acme-srv --issue -d acme-sh.acme --standalone --force --debug 3 --output-insecure openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - name: "[ PREPARE ] reconfigure a2c to detect success-hook failures " + - name: "Reconfigure a2c to detect success-hook failures " run: | sudo sed -i "s/ignore_success_hook_failure: True/ignore_post_hook_failure: False/g" examples/Docker/data/acme_srv.cfg cd examples/Docker/ sudo truncate -s 0 $(docker inspect --format='{{.LogPath}}' acme2certifier_acme-srv_1) docker-compose restart - - name: "[ FAIL ] acme.sh enrollment fails due to post-hook exception " + - name: "Acme.sh enrollment fails due to post-hook exception " id: posthookfailure continue-on-error: true run: | docker exec -i acme-sh acme.sh --server http://acme-srv --issue -d acme-sh.acme --standalone --force --debug 3 --output-insecure - - name: "[ CHECK ] result - acme.sh enrollment failed due to post-hook exception " + - name: "Check result - acme.sh enrollment failed due to post-hook exception " if: steps.posthookfailure.outcome != 'failure' run: | echo "posthookfailure outcome is ${{steps.posthookfailure.outcome }}" exit 1 + - name: "Check container configuration" + uses: ./.github/actions/container_check + with: + DB_HANDLER: ${{ matrix.dbhandler }} + WEB_SRV: ${{ matrix.websrv }} + - name: "[ * ] collecting test logs" if: ${{ failure() }} run: | @@ -416,66 +389,208 @@ jobs: sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: ${{ failure() }} with: - name: hooks_exception_handling.tar.gz + name: hooks_exception_handling-${{ matrix.websrv }}-${{ matrix.dbhandler }}.tar.gz path: ${{ github.workspace }}/artifact/upload/ - hooks_exception_handling_rpm: - name: "hooks_exception_handling_rpm" + cleanup: + name: "cleanup" + runs-on: ubuntu-latest + needs: [hooks_tests, hooks_exception_handling] + strategy: + fail-fast: false + matrix: + websrv: ['apache2', 'nginx'] + dbhandler: ['wsgi', 'django'] + + steps: + - uses: geekyeggo/delete-artifact@v5 + with: + name: a2c-${{ github.run_id }}.${{ matrix.websrv }}.${{ matrix.dbhandler }}.tar.gz + + rpm_build_and_upload: + name: "rpm_build_and_upload" runs-on: ubuntu-latest steps: - name: "checkout GIT" - uses: actions/checkout@v3 + uses: actions/checkout@v4 + - name: "Build rpm package" + id: rpm_build + uses: ./.github/actions/rpm_build_upload - - name: Retrieve Version from version.py - run: | - echo TAG_NAME=$(cat acme_srv/version.py | grep -i __version__ | head -n 1 | sed 's/__version__ = //g' | sed s/\'//g) >> $GITHUB_ENV - - run: echo "Latest tag is ${{ env.TAG_NAME }}" + hooks_test_rpm: + name: "hooks_test_rpm" + runs-on: ubuntu-latest + needs: rpm_build_and_upload + strategy: + fail-fast: false + max-parallel: 1 + matrix: + rhversion: [8, 9] + steps: + - name: "checkout GIT" + uses: actions/checkout@v4 + + - name: "Prepare Alma environment" + uses: ./.github/actions/rpm_prep + with: + GH_SBOM_USER: ${{ secrets.GH_SBOM_USER }} + GH_SBOM_TOKEN: ${{ secrets.GH_SBOM_TOKEN }} + RH_VERSION: ${{ matrix.rhversion }} + RPM_BUILD: false - - name: update version number in spec file + - name: Download rpm package + uses: actions/download-artifact@v4 + with: + name: acme2certifier-${{ github.run_id }}.noarch.rpm + path: data/ + + - name: "create letsencrypt and lego folder" run: | - # sudo sed -i "s/Source0:.*/Source0: %{name}-%{version}.tar.gz/g" examples/install_scripts/rpm/acme2certifier.spec - sudo sed -i "s/__version__/${{ env.TAG_NAME }}/g" examples/install_scripts/rpm/acme2certifier.spec - cat examples/install_scripts/rpm/acme2certifier.spec + mkdir acme-sh + mkdir lego - - name: build RPM package - id: rpm - uses: grindsa/rpmbuild@alma9 + - name: "Prepare acme_srv.cfg with certifier_ca_handler" + uses: ./.github/actions/wf_specific/certifier_ca_handler/certifier_setup_no_profile with: - spec_file: "examples/install_scripts/rpm/acme2certifier.spec" + WCCE_SSH_ACCESS_KEY: ${{ secrets.WCCE_SSH_ACCESS_KEY }} + WCCE_SSH_KNOWN_HOSTS: ${{ secrets.WCCE_SSH_KNOWN_HOSTS }} + WCCE_SSH_USER: ${{ secrets.WCCE_SSH_USER }} + WCCE_SSH_HOST: ${{ secrets.WCCE_SSH_HOST }} + WCCE_SSH_PORT: ${{ secrets.WCCE_SSH_PORT }} + NCM_API_HOST: ${{ secrets.NCM_API_HOST }} + NCM_API_USER: ${{ secrets.NCM_API_USER }} + NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} + NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} + DATA_PATH: data + + - name: "Modify acme_srv.cfg" + run: | + sudo mkdir -p data/acme_ca/hooks + sudo cp test/ca/sub-ca-cert.pem test/ca/root-ca-cert.pem data/acme_ca/ + sudo chmod 777 data/acme_srv.cfg + sudo chmod -R 777 data/acme_ca/hooks + sudo echo -e "\n\n[Hooks]" >> data/acme_srv.cfg + sudo echo "hooks_file: /opt/acme2certifier/examples/hooks/cn_dump_hooks.py" >> data/acme_srv.cfg + sudo echo "save_path: /tmp/acme2certifier/acme_ca/hooks" >> data/acme_srv.cfg + sudo echo "$HOOKS_CHECKSUM" > data/acme_ca/hooks/checksums.sha256 + env: + HOOKS_CHECKSUM: ${{ secrets.HOOKS_CHECKSUM }} - - run: echo "path is ${{ steps.rpm.outputs.rpm_dir_path }}" + - name: "Execute install scipt" + run: | + docker exec acme-srv sh /tmp/acme2certifier/rpm_tester.sh + + - name: "Test http://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory + + - name: "Register certbot" + run: | + docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email - - name: "[ PREPARE ] setup environment for alma installation" + - name: "Enroll HTTP-01 single domain certbot" run: | - docker network create acme - sudo mkdir -p data - sudo chmod -R 777 data - sudo cp ${{ steps.rpm.outputs.rpm_dir_path }}noarch/acme2certifier-${{ env.TAG_NAME }}-1.0.noarch.rpm data - sudo cp examples/Docker/almalinux-systemd/rpm_tester.sh data + docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot + sudo chmod 777 certbot/archive/certbot/chain1.pem + sudo cp certbot/archive/certbot/chain1.pem chain1.pem + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < chain1.pem + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem - - name: "[ PREPARE ] create letsencrypt and lego folder" + - name: "Prepare acme.sh container" run: | - mkdir acmme-sh + docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon + + - name: "Register acme.sh" + run: | + docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --debug 3 + + - name: "Enroll acme.sh" + run: | + docker exec -i acme-sh acme.sh --server http://acme-srv --issue -d acme-sh.acme --standalone --debug 3 --output-insecure + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer + + - name: "Enroll lego" + run: | + docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --http run + sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + + - name: "Compare checksums to validate hook file content" + working-directory: data/acme_ca/hooks + run: | + sha256sum -c checksums.sha256 + + - name: "[ * ] collecting test logs" + if: ${{ failure() }} + run: | + mkdir -p ${{ github.workspace }}/artifact/upload + docker exec acme-srv tar cvfz /tmp/acme2certifier/a2c.tgz /opt/acme2certifier + sudo cp -rp data/ ${{ github.workspace }}/artifact/data/ + sudo cp -rp acme-sh/ ${{ github.workspace }}/artifact/acme-sh/ + sudo rm ${{ github.workspace }}/artifact/data/*.rpm + docker exec acme-srv cat /etc/nginx/nginx.conf.orig > ${{ github.workspace }}/artifact/data/nginx.conf.orig + docker exec acme-srv cat /etc/nginx/nginx.conf > ${{ github.workspace }}/artifact/data/nginx.conf + docker exec acme-srv cat /var/log/messages > ${{ github.workspace }}/artifact/acme-srv.log + sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz data acme-srv.log acme-sh + + - name: "[ * ] uploading artificates" + uses: actions/upload-artifact@v4 + if: ${{ failure() }} + with: + name: hooks-rpm-rh${{ matrix.rhversion }}.tar.gz + path: ${{ github.workspace }}/artifact/upload/ + + hooks_exception_handling_rpm: + name: "hooks_exception_handling_rpm" + runs-on: ubuntu-latest + needs: rpm_build_and_upload + strategy: + fail-fast: false + max-parallel: 1 + matrix: + rhversion: [8, 9] + steps: + - name: "checkout GIT" + uses: actions/checkout@v4 + + - name: "Prepare Alma environment" + uses: ./.github/actions/rpm_prep + with: + GH_SBOM_USER: ${{ secrets.GH_SBOM_USER }} + GH_SBOM_TOKEN: ${{ secrets.GH_SBOM_TOKEN }} + RH_VERSION: ${{ matrix.rhversion }} + RPM_BUILD: false + + - name: Download rpm package + uses: actions/download-artifact@v4 + with: + name: acme2certifier-${{ github.run_id }}.noarch.rpm + path: data/ + + - name: "create letsencrypt and lego folder" + run: | + mkdir acme-sh mkdir lego - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" + - name: "Prepare acme_srv.cfg with certifier_ca_handler" + uses: ./.github/actions/wf_specific/certifier_ca_handler/certifier_setup_no_profile + with: + WCCE_SSH_ACCESS_KEY: ${{ secrets.WCCE_SSH_ACCESS_KEY }} + WCCE_SSH_KNOWN_HOSTS: ${{ secrets.WCCE_SSH_KNOWN_HOSTS }} + WCCE_SSH_USER: ${{ secrets.WCCE_SSH_USER }} + WCCE_SSH_HOST: ${{ secrets.WCCE_SSH_HOST }} + WCCE_SSH_PORT: ${{ secrets.WCCE_SSH_PORT }} + NCM_API_HOST: ${{ secrets.NCM_API_HOST }} + NCM_API_USER: ${{ secrets.NCM_API_USER }} + NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} + NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} + DATA_PATH: data + + - name: "Modify acme_srv.cfg" run: | - mkdir -p data/acme_ca - sudo cp test/ca/certsrv_ca_certs.pem data/acme_ca/ca_certs.pem - sudo touch data/acme_srv.cfg - sudo chmod 777 data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > data/acme_srv.cfg - sudo echo "handler_file: /opt/acme2certifier/examples/ca_handler/certifier_ca_handler.py" >> data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> data/acme_srv.cfg - sudo echo "profile_id: 101" >> data/acme_srv.cfg sudo mkdir -p data/acme_ca/hooks sudo chmod -R 777 data/acme_ca/hooks sudo echo -e "\n\n[Hooks]" >> data/acme_srv.cfg @@ -491,110 +606,106 @@ jobs: NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - name: "[ PREPARE ] Almalinux instance" - run: | - cat examples/Docker/almalinux-systemd/Dockerfile | docker build -t almalinux-systemd -f - . --no-cache - docker run -d -id --privileged --network acme --name=acme-srv -v "$(pwd)/data":/tmp/acme2certifier almalinux-systemd - - - name: "[ RUN ] Execute install scipt" + - name: "Execute install scipt" run: | docker exec acme-srv sh /tmp/acme2certifier/rpm_tester.sh - name: "Test http://acme-srv/directory is accessible" run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - name: "[ PREPARE ] prepare acme.sh container" + + - name: "Prepare acme.sh container" run: | docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - name: "[ REGISTER] acme.sh" + - name: "Register acme.sh" run: | docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --debug 3 - - name: "[ ENROLL] acme.sh - *_pre_hook_failure not configured " + - name: "Enroll acme.sh - *_pre_hook_failure not configured " run: | docker exec -i acme-sh acme.sh --server http://acme-srv --issue -d acme-sh.acme --standalone --debug 3 --output-insecure awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - name: "[ PREPARE ] reconfigure hook handler to trigger pre hook exception " + - name: "reconfigure hook handler to trigger pre hook exception " run: | sudo sed -i "s/raise_pre_hook_exception: False/raise_pre_hook_exception: True/g" data/acme_srv.cfg docker exec acme-srv sh /tmp/acme2certifier/rpm_tester.sh restart - - name: "[ FAIL ] acme.sh enrollment fails due to pre-hook exception (default behaviour)" + - name: "acme.sh enrollment fails due to pre-hook exception (default behaviour)" id: prehookfailure continue-on-error: true run: | docker exec -i acme-sh acme.sh --server http://acme-srv --issue -d acme-sh.acme --standalone --force --debug 3 --output-insecure - - name: "[ CHECK ] result - acme.sh enrollment failed due to pre-hook exception " + - name: "Check result - acme.sh enrollment failed due to pre-hook exception " if: steps.prehookfailure.outcome != 'failure' run: | echo "prehookfailure outcome is ${{steps.prehookfailure.outcome }}" exit 1 - - name: "[ PREPARE ] reconfigure a2c to ignore pre-hook failures " + - name: "reconfigure a2c to ignore pre-hook failures " run: | sudo echo "ignore_pre_hook_failure: True" >> data/acme_srv.cfg docker exec acme-srv sh /tmp/acme2certifier/rpm_tester.sh restart - - name: "[ ENROLL] acme.sh - ignore pre_hook_failures " + - name: "Enroll acme.sh - ignore pre_hook_failures " run: | docker exec -i acme-sh acme.sh --server http://acme-srv --issue -d acme-sh.acme --standalone --force --debug 3 --output-insecure openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - name: "[ PREPARE ] reconfigure hook handler to trigger success hook exception " + - name: "reconfigure hook handler to trigger success hook exception " run: | sudo sed -i "s/raise_pre_hook_exception: True/raise_pre_hook_exception: False/g" data/acme_srv.cfg sudo sed -i "s/raise_success_hook_exception: False/raise_success_hook_exception: True/g" data/acme_srv.cfg docker exec acme-srv sh /tmp/acme2certifier/rpm_tester.sh restart - - name: "[ FAIL ] acme.sh enrollment fails due to success-hook exception (default behaviour) " + - name: "acme.sh enrollment fails due to success-hook exception (default behaviour) " id: successhookfailure continue-on-error: true run: | docker exec -i acme-sh acme.sh --server http://acme-srv --issue -d acme-sh.acme --standalone --force --debug 3 --output-insecure - - name: "[ CHECK ] result - acme.sh enrollment failed due to success-hook exception " + - name: "Check result - acme.sh enrollment failed due to success-hook exception " if: steps.successhookfailure.outcome != 'failure' run: | echo "successhookfailure outcome is ${{steps.successhookfailure.outcome }}" exit 1 - - name: "[ PREPARE ] reconfigure a2c to ignore success-hook failures " + - name: "reconfigure a2c to ignore success-hook failures " run: | sudo sed -i "s/ignore_pre_hook_failure: True/ignore_success_hook_failure: True/g" data/acme_srv.cfg docker exec acme-srv sh /tmp/acme2certifier/rpm_tester.sh restart - - name: "[ ENROLL] acme.sh - ignore sucess_hook_failures " + - name: "Enroll acme.sh - ignore sucess_hook_failures " run: | docker exec -i acme-sh acme.sh --server http://acme-srv --issue -d acme-sh.acme --standalone --force --debug 3 --output-insecure openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - name: "[ PREPARE ] reconfigure hook handler to trigger post hook exception " + - name: "reconfigure hook handler to trigger post hook exception " run: | sudo sed -i "s/raise_success_hook_exception: True/raise_success_hook_exception: False/g" data/acme_srv.cfg sudo sed -i "s/raise_post_hook_exception: False/raise_post_hook_exception: True/g" data/acme_srv.cfg docker exec acme-srv sh /tmp/acme2certifier/rpm_tester.sh restart - - name: "[ ENROLL] acme.sh - ignore post_hook_failures (default behaviour) " + - name: "Enroll acme.sh - ignore post_hook_failures (default behaviour) " run: | docker exec -i acme-sh acme.sh --server http://acme-srv --issue -d acme-sh.acme --standalone --force --debug 3 --output-insecure openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - name: "[ PREPARE ] reconfigure a2c to detect success-hook failures " + - name: "reconfigure a2c to detect success-hook failures " run: | sudo sed -i "s/ignore_success_hook_failure: True/ignore_post_hook_failure: False/g" data/acme_srv.cfg docker exec acme-srv sh /tmp/acme2certifier/rpm_tester.sh restart - - name: "[ FAIL ] acme.sh enrollment fails due to post-hook exception " + - name: "acme.sh enrollment fails due to post-hook exception " id: posthookfailure continue-on-error: true run: | docker exec -i acme-sh acme.sh --server http://acme-srv --issue -d acme-sh.acme --standalone --force --debug 3 --output-insecure - - name: "[ CHECK ] result - acme.sh enrollment failed due to post-hook exception " + - name: "Check result - acme.sh enrollment failed due to post-hook exception " if: steps.posthookfailure.outcome != 'failure' run: | echo "posthookfailure outcome is ${{steps.posthookfailure.outcome }}" @@ -607,12 +718,17 @@ jobs: docker exec acme-srv tar cvfz /tmp/acme2certifier/a2c.tgz /opt/acme2certifier sudo cp -rp data/ ${{ github.workspace }}/artifact/data/ sudo cp -rp acme-sh/ ${{ github.workspace }}/artifact/acme-sh/ + sudo rm ${{ github.workspace }}/artifact/data/*.rpm + docker exec acme-srv cat /etc/nginx/nginx.conf.orig > ${{ github.workspace }}/artifact/data/nginx.conf.orig + docker exec acme-srv cat /etc/nginx/nginx.conf > ${{ github.workspace }}/artifact/data/nginx.conf docker exec acme-srv cat /var/log/messages > ${{ github.workspace }}/artifact/acme-srv.log sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz data acme-srv.log acme-sh - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: ${{ failure() }} with: - name: hooks-rpm.tar.gz - path: ${{ github.workspace }}/artifact/upload/ \ No newline at end of file + name: hooks-rpm-rh${{ matrix.rhversion }}.tar.gz + path: ${{ github.workspace }}/artifact/upload/ + + diff --git a/.github/workflows/ip-address-tests.yml b/.github/workflows/ip-address-tests.yml index 1bddb1a7..82df5c35 100644 --- a/.github/workflows/ip-address-tests.yml +++ b/.github/workflows/ip-address-tests.yml @@ -9,160 +9,58 @@ on: - cron: '0 2 * * 6' jobs: - ip_apache2_wsgi: - name: "ip_apache2_wsgi" + ip_tests: + name: "ip_tests" runs-on: ubuntu-latest + strategy: + fail-fast: false + max-parallel: 2 + matrix: + websrv: ['apache2', 'nginx'] + dbhandler: ['wsgi', 'django'] steps: - name: "checkout GIT" - uses: actions/checkout@v3 + uses: actions/checkout@v4 - - name: "[ PREPARE ] get runner ip" + - name: "get runner ip" run: | echo RUNNER_IP=$(ip addr show eth0 | grep -i "inet " | cut -d ' ' -f 6 | cut -d '/' -f 1) >> $GITHUB_ENV echo RUNNER_PATH=$(pwd | sed 's_/_\\/_g') >> $GITHUB_ENV - run: echo "runner IP is ${{ env.RUNNER_IP }}" - - name: "Build docker-compose (apache2_wsgi)" - working-directory: examples/Docker/ - run: | - sudo mkdir -p data - docker network create acme - docker-compose up -d - docker-compose logs + - name: "Build container" + uses: ./.github/actions/container_prep + with: + DB_HANDLER: ${{ matrix.dbhandler }} + WEB_SRV: ${{ matrix.websrv }} - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - sudo cp .github/acme2certifier.pem examples/Docker/data/acme2certifier.pem - cd examples/Docker/ - docker-compose restart - docker-compose logs - env: + - name: "Prepare acme_srv.cfg with certifier_ca_handler" + uses: ./.github/actions/wf_specific/certifier_ca_handler/certifier_setup_no_profile + with: + WCCE_SSH_ACCESS_KEY: ${{ secrets.WCCE_SSH_ACCESS_KEY }} + WCCE_SSH_KNOWN_HOSTS: ${{ secrets.WCCE_SSH_KNOWN_HOSTS }} + WCCE_SSH_USER: ${{ secrets.WCCE_SSH_USER }} + WCCE_SSH_HOST: ${{ secrets.WCCE_SSH_HOST }} + WCCE_SSH_PORT: ${{ secrets.WCCE_SSH_PORT }} NCM_API_HOST: ${{ secrets.NCM_API_HOST }} NCM_API_USER: ${{ secrets.NCM_API_USER }} NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "Sleep for 5s" - uses: juliangruber/sleep-action@v1 - with: - time: 5s - - - name: "Test http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "Test if https://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory - - - name: "create lego folder" - run: | - mkdir lego - - - name: "Enroll HTTP-01 single domain and ip address " - run: | - docker run -i -p 80:80 -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme -d $RUNNER_IP --http run - sudo chmod 777 lego/certificates/lego.acme.issuer.crt - sudo cp lego/certificates/lego.acme.issuer.crt lego.acme.issuer.crt - sudo awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < lego.acme.issuer.crt - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt - sudo openssl x509 -in lego/certificates/lego.acme.crt --text --noout | grep "IP Address" - env: - RUNNER_IP: ${{ env.RUNNER_IP }} + DATA_PATH: examples/Docker/data - - name: "[ * ] collecting test logs" - if: ${{ failure() }} + - name: "Restart a2c" run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp lego/ ${{ github.workspace }}/artifact/lego/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data lego - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: ip_apache2_wsgi.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - - ip_apache2_django: - name: "ip_apache2_django" - runs-on: ubuntu-latest - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "[ PREPARE ] get runner ip" - run: | - echo RUNNER_IP=$(ip addr show eth0 | grep -i "inet " | cut -d ' ' -f 6 | cut -d '/' -f 1) >> $GITHUB_ENV - echo RUNNER_PATH=$(pwd | sed 's_/_\\/_g') >> $GITHUB_ENV - - run: echo "runner IP is ${{ env.RUNNER_IP }}" - - - name: "Build docker-compose (apache2_django)" - working-directory: examples/Docker/ - run: | - sed -i "s/wsgi/django/g" .env - sudo mkdir -p data - docker network create acme - docker-compose up -d - docker-compose logs - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - sudo cp .github/django_settings.py examples/Docker/data/settings.py - sudo cp .github/acme2certifier.pem examples/Docker/data/acme2certifier.pem cd examples/Docker/ docker-compose restart docker-compose logs - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - name: "Sleep for 5s" - uses: juliangruber/sleep-action@v1 - with: - time: 5s - - - name: "Test http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "Test if https://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory - - - name: "create lego folder" - run: | - mkdir lego + - name: "Test enrollment" + uses: ./.github/actions/acme_clients - name: "Enroll HTTP-01 single domain and ip address " run: | + sudo rm -rf lego/* docker run -i -p 80:80 -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme -d $RUNNER_IP --http run - sudo chmod 777 lego/certificates/lego.acme.issuer.crt - sudo cp lego/certificates/lego.acme.issuer.crt lego.acme.issuer.crt - sudo awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < lego.acme.issuer.crt sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt sudo openssl x509 -in lego/certificates/lego.acme.crt --text --noout | grep "IP Address" env: @@ -179,170 +77,80 @@ jobs: sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data lego - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: ${{ failure() }} with: - name: ip_apache2_django.tar.gz + name: ip_tests-${{ matrix.websrv }}-${{ matrix.dbhandler }}.tar.gz path: ${{ github.workspace }}/artifact/upload/ - ip_nginx_wsgi: - name: "ip_nginx_wsgi" + ip_rpm: + name: "ip_rpm" runs-on: ubuntu-latest + strategy: + fail-fast: false + max-parallel: 1 + matrix: + rhversion: [8, 9] + execscript: ['rpm_tester.sh', 'django_tester.sh'] steps: - name: "checkout GIT" - uses: actions/checkout@v3 + uses: actions/checkout@v4 - - name: "[ PREPARE ] get runner ip" + - name: "get runner ip" run: | echo RUNNER_IP=$(ip addr show eth0 | grep -i "inet " | cut -d ' ' -f 6 | cut -d '/' -f 1) >> $GITHUB_ENV echo RUNNER_PATH=$(pwd | sed 's_/_\\/_g') >> $GITHUB_ENV - run: echo "runner IP is ${{ env.RUNNER_IP }}" - - name: "Build docker-compose (nginx_wsgi)" - working-directory: examples/Docker/ - run: | - sed -i "s/apache2/nginx/g" .env - sudo mkdir -p data - docker network create acme - docker-compose up -d - docker-compose logs + - name: "Prepare Alma environment" + uses: ./.github/actions/rpm_prep + with: + GH_SBOM_USER: ${{ secrets.GH_SBOM_USER }} + GH_SBOM_TOKEN: ${{ secrets.GH_SBOM_TOKEN }} + RH_VERSION: ${{ matrix.rhversion }} - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - sudo cp .github/acme2certifier_cert.pem examples/Docker/data/acme2certifier_cert.pem - sudo cp .github/acme2certifier_key.pem examples/Docker/data/acme2certifier_key.pem - cd examples/Docker/ - docker-compose restart - docker-compose logs - env: + - name: "WSGI - Prepare acme_srv.cfg with certifier_ca_handler" + if: matrix.execscript == 'rpm_tester.sh' + uses: ./.github/actions/wf_specific/certifier_ca_handler/certifier_setup_no_profile + with: + WCCE_SSH_ACCESS_KEY: ${{ secrets.WCCE_SSH_ACCESS_KEY }} + WCCE_SSH_KNOWN_HOSTS: ${{ secrets.WCCE_SSH_KNOWN_HOSTS }} + WCCE_SSH_USER: ${{ secrets.WCCE_SSH_USER }} + WCCE_SSH_HOST: ${{ secrets.WCCE_SSH_HOST }} + WCCE_SSH_PORT: ${{ secrets.WCCE_SSH_PORT }} NCM_API_HOST: ${{ secrets.NCM_API_HOST }} NCM_API_USER: ${{ secrets.NCM_API_USER }} NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "Sleep for 5s" - uses: juliangruber/sleep-action@v1 - with: - time: 5s + DATA_PATH: data - - name: "Test http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "Test if https://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory - - - name: "create lego folder" - run: | - mkdir lego - - - name: "Enroll HTTP-01 single domain and ip address " - run: | - docker run -i -p 80:80 -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme -d $RUNNER_IP --http run - sudo chmod 777 lego/certificates/lego.acme.issuer.crt - sudo cp lego/certificates/lego.acme.issuer.crt lego.acme.issuer.crt - sudo awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < lego.acme.issuer.crt - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt - sudo openssl x509 -in lego/certificates/lego.acme.crt --text --noout | grep "IP Address" - env: - RUNNER_IP: ${{ env.RUNNER_IP }} - - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp lego/ ${{ github.workspace }}/artifact/lego/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data lego - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} + - name: "Django - Prepare acme_srv.cfg with certifier_ca_handler" + if: matrix.execscript == 'django_tester.sh' + uses: ./.github/actions/wf_specific/certifier_ca_handler/certifier_setup_no_profile with: - name: ip_nginx_wsgi.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - - ip_nginx_django: - name: "ip_nginx_django" - runs-on: ubuntu-latest - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "[ PREPARE ] get runner ip" - run: | - echo RUNNER_IP=$(ip addr show eth0 | grep -i "inet " | cut -d ' ' -f 6 | cut -d '/' -f 1) >> $GITHUB_ENV - echo RUNNER_PATH=$(pwd | sed 's_/_\\/_g') >> $GITHUB_ENV - - run: echo "runner IP is ${{ env.RUNNER_IP }}" - - - name: "Build docker-compose (nginx_django)" - working-directory: examples/Docker/ - run: | - sed -i "s/wsgi/django/g" .env - sed -i "s/apache2/nginx/g" .env - sudo mkdir -p data - docker network create acme - docker-compose up -d - docker-compose logs - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - sudo cp .github/django_settings.py examples/Docker/data/settings.py - sudo cp .github/acme2certifier_cert.pem examples/Docker/data/acme2certifier_cert.pem - sudo cp .github/acme2certifier_key.pem examples/Docker/data/acme2certifier_key.pem - cd examples/Docker/ - docker-compose restart - docker-compose logs - env: + WCCE_SSH_ACCESS_KEY: ${{ secrets.WCCE_SSH_ACCESS_KEY }} + WCCE_SSH_KNOWN_HOSTS: ${{ secrets.WCCE_SSH_KNOWN_HOSTS }} + WCCE_SSH_USER: ${{ secrets.WCCE_SSH_USER }} + WCCE_SSH_HOST: ${{ secrets.WCCE_SSH_HOST }} + WCCE_SSH_PORT: ${{ secrets.WCCE_SSH_PORT }} NCM_API_HOST: ${{ secrets.NCM_API_HOST }} NCM_API_USER: ${{ secrets.NCM_API_USER }} NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "Sleep for 5s" - uses: juliangruber/sleep-action@v1 - with: - time: 5s - - - name: "Test http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "Test if https://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory + DATA_PATH: data/volume - - name: "create lego folder" + - name: "Execute install scipt" run: | - mkdir lego + docker exec acme-srv sh /tmp/acme2certifier/$EXEC_SCRIPT + env: + EXEC_SCRIPT: ${{ matrix.execscript }} + + - name: "Test enrollment" + uses: ./.github/actions/acme_clients - name: "Enroll HTTP-01 single domain and ip address " run: | docker run -i -p 80:80 -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme -d $RUNNER_IP --http run - sudo chmod 777 lego/certificates/lego.acme.issuer.crt - sudo cp lego/certificates/lego.acme.issuer.crt lego.acme.issuer.crt - sudo awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < lego.acme.issuer.crt sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt sudo openssl x509 -in lego/certificates/lego.acme.crt --text --noout | grep "IP Address" env: @@ -352,15 +160,19 @@ jobs: if: ${{ failure() }} run: | mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ + docker exec acme-srv tar cvfz /tmp/acme2certifier/a2c.tgz /opt/acme2certifier + sudo cp -rp data/ ${{ github.workspace }}/artifact/data/ sudo cp -rp lego/ ${{ github.workspace }}/artifact/lego/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data lego + sudo rm ${{ github.workspace }}/artifact/data/*.rpm + docker exec acme-srv cat /etc/nginx/nginx.conf.orig > ${{ github.workspace }}/artifact/data/nginx.conf.orig + docker exec acme-srv cat /etc/nginx/nginx.conf > ${{ github.workspace }}/artifact/data/nginx.conf + docker exec acme-srv cat /var/log/messages > ${{ github.workspace }}/artifact/acme-srv.log + sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz data acme-srv.log lego - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: ${{ failure() }} with: - name: ip_nginx_django.tar.gz + name: ip_wsgi_rpm-rh${{ matrix.rhversion }}-${{ matrix.execscript }}.tar.gz path: ${{ github.workspace }}/artifact/upload/ + diff --git a/.github/workflows/ipv6-test.yml b/.github/workflows/ipv6-test.yml index 1961964c..d3c55445 100644 --- a/.github/workflows/ipv6-test.yml +++ b/.github/workflows/ipv6-test.yml @@ -9,204 +9,70 @@ jobs: ipv6_apache2_wsgi: name: "ipv6_apache2_wsgi" runs-on: ubuntu-latest + strategy: + fail-fast: false + max-parallel: 2 + matrix: + websrv: ['apache2', 'nginx'] + dbhandler: ['wsgi', 'django'] + steps: - name: "checkout GIT" - uses: actions/checkout@v3 - - name: "[ PREPARE ] Build docker-compose (apache2_wsgi)" - working-directory: examples/Docker/ - run: | - sudo mkdir -p data - docker network create acme --ipv6 --subnet "fdbb:6445:65b4:0a60::/64" - docker-compose up -d - docker-compose logs + uses: actions/checkout@v4 - - name: "Test http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory + - name: "Build container" + uses: ./.github/actions/container_prep + with: + DB_HANDLER: ${{ matrix.dbhandler }} + WEB_SRV: ${{ matrix.websrv }} + IPV6: true - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - cd examples/Docker/ - docker-compose restart - docker-compose logs - env: + - name: "Prepare acme_srv.cfg with certifier_ca_handler" + uses: ./.github/actions/wf_specific/certifier_ca_handler/certifier_setup_no_profile + with: + WCCE_SSH_ACCESS_KEY: ${{ secrets.WCCE_SSH_ACCESS_KEY }} + WCCE_SSH_KNOWN_HOSTS: ${{ secrets.WCCE_SSH_KNOWN_HOSTS }} + WCCE_SSH_USER: ${{ secrets.WCCE_SSH_USER }} + WCCE_SSH_HOST: ${{ secrets.WCCE_SSH_HOST }} + WCCE_SSH_PORT: ${{ secrets.WCCE_SSH_PORT }} NCM_API_HOST: ${{ secrets.NCM_API_HOST }} NCM_API_USER: ${{ secrets.NCM_API_USER }} NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "create acme-sh folder" - run: | - mkdir acme-sh - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ ENROLL ] HTTP-01 single domain acme.sh using ipv6" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --keylength 2048 --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --standalone --listen-v6 --debug 3 --output-insecure - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme/ca.cer - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme/acme-sh.acme.cer - - - name: "[ ENROLL ] HTTP-01 single domain acme.sh using ipv6 with ipv4 fallback" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --keylength 2048 --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --standalone --listen-v4 --debug 3 --output-insecure --force - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme/acme-sh.acme.cer - - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp acme-sh/ ${{ github.workspace }}/artifact/acme-sh/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data acme-sh - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: ipv6_apache2_wsgi.tar.gz - path: ${{ github.workspace }}/artifact/upload/ + DATA_PATH: examples/Docker/data - ipv6_nginx_wsgi: - name: "ipv6_nginx_wsgi" - runs-on: ubuntu-latest - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - name: "[ PREPARE ] Build docker-compose (nginx_wsgi)" - working-directory: examples/Docker/ + - name: "Restart a2c" run: | - sed -i "s/apache2/nginx/g" .env - sudo mkdir -p data - docker network create acme --ipv6 --subnet "fdbb:6445:65b4:0a60::/64" - docker-compose up -d - docker-compose logs - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg cd examples/Docker/ docker-compose restart docker-compose logs - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "create acme-sh folder" - run: | - mkdir acme-sh - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ ENROLL ] HTTP-01 single domain acme.sh using ipv6" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --keylength 2048 --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --standalone --listen-v6 --debug 3 --output-insecure - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme/ca.cer - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme/acme-sh.acme.cer - - - name: "[ ENROLL ] HTTP-01 single domain acme.sh using ipv6 with ipv4 fallback" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --keylength 2048 --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --standalone --listen-v4 --debug 3 --output-insecure --force - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme/acme-sh.acme.cer - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp acme-sh/ ${{ github.workspace }}/artifact/acme-sh/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data acme-sh - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} + - name: "Sleep for 10s" + uses: juliangruber/sleep-action@v2.0.3 with: - name: ipv6_nginx_wsgi.tar.gz - path: ${{ github.workspace }}/artifact/upload/ + time: 10s - ipv6_apache2_django: - name: "ipv6_apache2_django" - runs-on: ubuntu-latest - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - name: "[ PREPARE ] Build docker-compose (apache2_django)" - working-directory: examples/Docker/ - run: | - sed -i "s/wsgi/django/g" .env - sudo mkdir -p data - docker network create acme --ipv6 --subnet "fdbb:6445:65b4:0a60::/64" - docker-compose up -d - docker-compose logs + - name: "Test http://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - sudo cp .github/django_settings.py examples/Docker/data/settings.py - cd examples/Docker/ - docker-compose restart - docker-compose logs - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} + - name: "Test if https://acme-srv/directory is accessible" + run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory - name: "create acme-sh folder" run: | mkdir acme-sh - - name: "[ PREPARE ] prepare acme.sh container" + - name: "prepare acme.sh container" run: | docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - name: "[ ENROLL ] HTTP-01 single domain acme.sh using ipv6" + - name: "Enroll HTTP-01 single domain acme.sh using ipv6" run: | docker exec -i acme-sh acme.sh --server http://acme-srv --keylength 2048 --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --standalone --listen-v6 --debug 3 --output-insecure awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme/ca.cer openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme/acme-sh.acme.cer - - name: "[ ENROLL ] HTTP-01 single domain acme.sh using ipv6 with ipv4 fallback" + - name: "Enroll HTTP-01 single domain acme.sh using ipv6 with ipv4 fallback" run: | docker exec -i acme-sh acme.sh --server http://acme-srv --keylength 2048 --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --standalone --listen-v4 --debug 3 --output-insecure --force openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme/acme-sh.acme.cer @@ -220,84 +86,92 @@ jobs: cd examples/Docker docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data acme-sh + - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: ${{ failure() }} with: - name: ipv6_apache2_django.tar.gz + name: ipv6_tests-${{ matrix.websrv }}-${{ matrix.dbhandler }}.tar.gz path: ${{ github.workspace }}/artifact/upload/ - ipv6_nginx_django: - name: "ipv6_nginx_django" + rpm_ipv6: + name: "rpm_ipv6" runs-on: ubuntu-latest + strategy: + fail-fast: false + max-parallel: 1 + matrix: + rhversion: [8, 9] + execscript: ['rpm_tester.sh', 'django_tester.sh'] + steps: - name: "checkout GIT" - uses: actions/checkout@v3 - - name: "[ PREPARE ] Build docker-compose (nginx_django)" - working-directory: examples/Docker/ - run: | - sed -i "s/wsgi/django/g" .env - sed -i "s/apache2/nginx/g" .env - sudo mkdir -p data - docker network create acme --ipv6 --subnet "fdbb:6445:65b4:0a60::/64" - docker-compose up -d - docker-compose logs + uses: actions/checkout@v4 - - name: "create acme-sh folder" - run: | - mkdir acme-sh + - name: "Prepare Alma environment" + uses: ./.github/actions/rpm_prep + with: + GH_SBOM_USER: ${{ secrets.GH_SBOM_USER }} + GH_SBOM_TOKEN: ${{ secrets.GH_SBOM_TOKEN }} + RH_VERSION: ${{ matrix.rhversion }} + IPV6: true - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" + - name: "create lego and certbot folder" run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - sudo cp .github/django_settings.py examples/Docker/data/settings.py - cd examples/Docker/ - docker-compose restart - docker-compose logs - env: + mkdir lego + mkdir certbot + + - name: "Prepare acme_srv.cfg with certifier_ca_handler" + uses: ./.github/actions/wf_specific/certifier_ca_handler/certifier_setup_no_profile + with: + WCCE_SSH_ACCESS_KEY: ${{ secrets.WCCE_SSH_ACCESS_KEY }} + WCCE_SSH_KNOWN_HOSTS: ${{ secrets.WCCE_SSH_KNOWN_HOSTS }} + WCCE_SSH_USER: ${{ secrets.WCCE_SSH_USER }} + WCCE_SSH_HOST: ${{ secrets.WCCE_SSH_HOST }} + WCCE_SSH_PORT: ${{ secrets.WCCE_SSH_PORT }} NCM_API_HOST: ${{ secrets.NCM_API_HOST }} NCM_API_USER: ${{ secrets.NCM_API_USER }} NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} + DATA_PATH: data + + - name: "Execute install scipt" + run: | + docker exec acme-srv sh /tmp/acme2certifier/$EXEC_SCRIPT + env: + EXEC_SCRIPT: ${{ matrix.execscript }} - - name: "[ PREPARE ] prepare acme.sh container" + - name: "Prepare acme.sh container" run: | docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - name: "[ ENROLL ] HTTP-01 single domain acme.sh using ipv6" + - name: "Enroll acme.sh" run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --keylength 2048 --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --standalone --listen-v6 --debug 3 --output-insecure - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme/ca.cer - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme/acme-sh.acme.cer + docker exec -i acme-sh acme.sh --server http://acme-srv --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --standalone --listen-v6 --debug 3 --output-insecure + awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - name: "[ ENROLL ] HTTP-01 single domain acme.sh using ipv6 with ipv4 fallback" + - name: "Enroll acme.sh using ipv6 with ipv4 fallback" run: | docker exec -i acme-sh acme.sh --server http://acme-srv --keylength 2048 --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --standalone --listen-v4 --debug 3 --output-insecure --force - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme/acme-sh.acme.cer + openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - name: "[ * ] collecting test logs" if: ${{ failure() }} run: | mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp acme-sh/ ${{ github.workspace }}/artifact/acme-sh/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data acme-sh + docker exec acme-srv tar cvfz /tmp/acme2certifier/a2c.tgz /opt/acme2certifier + sudo cp -rp data/ ${{ github.workspace }}/artifact/data/ + sudo rm ${{ github.workspace }}/artifact/data/*.rpm + docker exec acme-srv cat /etc/nginx/nginx.conf.orig > ${{ github.workspace }}/artifact/data/nginx.conf.orig + docker exec acme-srv cat /etc/nginx/nginx.conf > ${{ github.workspace }}/artifact/data/nginx.conf + docker exec acme-srv cat /var/log/messages > ${{ github.workspace }}/artifact/acme-srv.log + sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz data acme-srv.log - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: ${{ failure() }} with: - name: ipv6_nginx_django.tar.gz + name: rpm_ipv6-rh${{ matrix.rhversion }}.tar.gz path: ${{ github.workspace }}/artifact/upload/ + diff --git a/.github/workflows/lego-application-test.yml b/.github/workflows/lego-application-test.yml deleted file mode 100644 index dde018ae..00000000 --- a/.github/workflows/lego-application-test.yml +++ /dev/null @@ -1,417 +0,0 @@ -name: Application Tests - lego - -on: - push: - pull_request: - branches: [ devel ] - schedule: - # * is a special character in YAML so you have to quote this string - - cron: '0 2 * * 6' - -jobs: - - lego_apache2_wsgi: - name: "lego_apache2_wsgi" - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - keylength: [rsa2048, rsa4096, ec256] - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "[ PREPARE ] Build docker-compose (apache2_wsgi)" - working-directory: examples/Docker/ - run: | - sudo mkdir -p data - docker network create acme - docker-compose up -d - docker-compose logs - - - name: "Test http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - cd examples/Docker/ - docker-compose restart - docker-compose logs - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "create lego folder" - run: | - mkdir lego - - - name: "[ ENROLL ] HTTP-01 single domain lego" - run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --key-type ${{ matrix.keylength }} --email "lego@example.com" -d lego.acme --http run - sudo chmod 777 lego/certificates/lego.acme.issuer.crt - sudo cp lego/certificates/lego.acme.issuer.crt lego.acme.issuer.crt - sudo awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < lego.acme.issuer.crt - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt - - - name: "[ RENEW ] HTTP-01 single domain lego" - run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --key-type ${{ matrix.keylength }} --email "lego@example.com" -d lego.acme --http renew - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt - - - name: "[ REVOKE ] HTTP-01 single domain lego" - run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --key-type ${{ matrix.keylength }} --email "lego@example.com" -d lego.acme revoke - - - name: "[ ENROLL ] HTTP-01 2x domain lego" - run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --key-type ${{ matrix.keylength }} --email "lego@example.com" -d lego.acme -d lego --http run - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt - - - name: "[ RENEW ] HTTP-01 2x domain lego" - run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --key-type ${{ matrix.keylength }} --email "lego@example.com" -d lego.acme -d lego --http renew - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt - - - name: "[ REVOKE ] HTTP-01 2x domain lego" - run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --key-type ${{ matrix.keylength }} --email "lego@example.com" -d lego.acme revoke - - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp lego/ ${{ github.workspace }}/artifact/lego/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data lego - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: lego_key-${{ matrix.keylength }}.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - - lego_apache2_django: - name: "lego_apache2_django" - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - keylength: [rsa2048, rsa4096, ec256] - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "[ PREPARE ] Build docker-compose (apache2_django)" - working-directory: examples/Docker/ - run: | - sed -i "s/wsgi/django/g" .env - sudo mkdir -p data - docker network create acme - docker-compose up -d - docker-compose logs - - - name: "[ WAIT ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "Test http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - sudo cp .github/acme2certifier.pem examples/Docker/data/acme2certifier.pem - sudo cp .github/django_settings.py examples/Docker/data/settings.py - cd examples/Docker/ - docker-compose restart - docker-compose logs - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "create lego folder" - run: | - mkdir lego - - - name: "[ ENROLL ] HTTP-01 single domain lego" - run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --key-type ${{ matrix.keylength }} --email "lego@example.com" -d lego.acme --http run - sudo chmod 777 lego/certificates/lego.acme.issuer.crt - sudo cp lego/certificates/lego.acme.issuer.crt lego.acme.issuer.crt - sudo awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < lego.acme.issuer.crt - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt - - - name: "[ RENEW ] HTTP-01 single domain lego" - run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --key-type ${{ matrix.keylength }} --email "lego@example.com" -d lego.acme --http renew - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt - - - name: "[ REVOKE ] HTTP-01 single domain lego" - run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --key-type ${{ matrix.keylength }} --email "lego@example.com" -d lego.acme revoke - - - name: "[ ENROLL ] HTTP-01 2x domain lego" - run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --key-type ${{ matrix.keylength }} --email "lego@example.com" -d lego.acme -d lego --http run - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt - - - name: "[ RENEW ] HTTP-01 2x domain lego" - run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --key-type ${{ matrix.keylength }} --email "lego@example.com" -d lego.acme -d lego --http renew - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt - - - name: "[ REVOKE ] HTTP-01 2x domain lego" - run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --key-type ${{ matrix.keylength }} --email "lego@example.com" -d lego.acme revoke - - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp lego/ ${{ github.workspace }}/artifact/lego/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data lego - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: lego_key-${{ matrix.keylength }}.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - - lego_nginx_wsgi: - name: "lego_nginx_wsgi" - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - keylength: [rsa2048, rsa4096, ec256] - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "[ PREPARE ] Build docker-compose (nginx_django)" - working-directory: examples/Docker/ - run: | - sed -i "s/apache2/nginx/g" .env - sudo mkdir -p data - docker network create acme - docker-compose up -d - docker-compose logs - - - name: "[ WAIT ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "Test http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - cd examples/Docker/ - docker-compose restart - docker-compose logs - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "create lego folder" - run: | - mkdir lego - - - name: "[ ENROLL ] HTTP-01 single domain lego" - run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --key-type ${{ matrix.keylength }} --email "lego@example.com" -d lego.acme --http run - sudo chmod 777 lego/certificates/lego.acme.issuer.crt - sudo cp lego/certificates/lego.acme.issuer.crt lego.acme.issuer.crt - sudo awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < lego.acme.issuer.crt - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt - - - name: "[ RENEW ] HTTP-01 single domain lego" - run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --key-type ${{ matrix.keylength }} --email "lego@example.com" -d lego.acme --http renew - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt - - - name: "[ REVOKE ] HTTP-01 single domain lego" - run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --key-type ${{ matrix.keylength }} --email "lego@example.com" -d lego.acme revoke - - - name: "[ ENROLL ] HTTP-01 2x domain lego" - run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --key-type ${{ matrix.keylength }} --email "lego@example.com" -d lego.acme -d lego --http run - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt - - - name: "[ RENEW ] HTTP-01 2x domain lego" - run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --key-type ${{ matrix.keylength }} --email "lego@example.com" -d lego.acme -d lego --http renew - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt - - - name: "[ REVOKE ] HTTP-01 2x domain lego" - run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --key-type ${{ matrix.keylength }} --email "lego@example.com" -d lego.acme revoke - - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp lego/ ${{ github.workspace }}/artifact/lego/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data lego - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: lego_key-${{ matrix.keylength }}.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - - lego_nginx_django: - name: "lego_nginx_django" - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - keylength: [rsa2048, rsa4096, ec256] - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "[ PREPARE ] Build docker-compose (nginx_django)" - working-directory: examples/Docker/ - run: | - sed -i "s/wsgi/django/g" .env - sed -i "s/apache2/nginx/g" .env - sudo mkdir -p data - docker network create acme - docker-compose up -d - docker-compose logs - - - name: "[ WAIT ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "Test http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - sudo cp .github/django_settings.py examples/Docker/data/settings.py - cd examples/Docker/ - docker-compose restart - docker-compose logs - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "create lego folder" - run: | - mkdir lego - - - name: "[ ENROLL ] HTTP-01 single domain lego" - run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --key-type ${{ matrix.keylength }} --email "lego@example.com" -d lego.acme --http run - sudo chmod 777 lego/certificates/lego.acme.issuer.crt - sudo cp lego/certificates/lego.acme.issuer.crt lego.acme.issuer.crt - sudo awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < lego.acme.issuer.crt - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt - - - name: "[ RENEW ] HTTP-01 single domain lego" - run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --key-type ${{ matrix.keylength }} --email "lego@example.com" -d lego.acme --http renew - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt - - - name: "[ REVOKE ] HTTP-01 single domain lego" - run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --key-type ${{ matrix.keylength }} --email "lego@example.com" -d lego.acme revoke - - - name: "[ ENROLL ] HTTP-01 2x domain lego" - run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --key-type ${{ matrix.keylength }} --email "lego@example.com" -d lego.acme -d lego --http run - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt - - - name: "[ RENEW ] HTTP-01 2x domain lego" - run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --key-type ${{ matrix.keylength }} --email "lego@example.com" -d lego.acme -d lego --http renew - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt - - - name: "[ REVOKE ] HTTP-01 2x domain lego" - run: | - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --key-type ${{ matrix.keylength }} --email "lego@example.com" -d lego.acme revoke - - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp lego/ ${{ github.workspace }}/artifact/lego/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data lego - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: lego_key-${{ matrix.keylength }}.tar.gz - path: ${{ github.workspace }}/artifact/upload/ diff --git a/.github/workflows/manual-install-test.yml b/.github/workflows/manual-install-test.yml deleted file mode 100644 index 12439684..00000000 --- a/.github/workflows/manual-install-test.yml +++ /dev/null @@ -1,576 +0,0 @@ -name: Manual Installation tests - -on: - push: - pull_request: - branches: [ devel ] - schedule: - # * is a special character in YAML so you have to quote this string - - cron: '0 2 * * 6' - -jobs: - apache2_wsgi: - name: "apache2_wsgi" - runs-on: ubuntu-latest - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "[ PREPARE ] get runner ip" - run: | - echo RUNNER_IP=$(ip addr show eth0 | grep -i "inet " | cut -d ' ' -f 6 | cut -d '/' -f 1) >> $GITHUB_ENV - echo RUNNER_PATH=$(pwd | sed 's_/_\\/_g') >> $GITHUB_ENV - - run: echo "runner IP is ${{ env.RUNNER_IP }}" - - - name: Branch name - run: echo running on branch ${GITHUB_REF##*/} - - - name: "Run install script" - run: | - sudo mkdir -p data - chmod a+rx examples/install_scripts/a2c-ubuntu22-apache2.sh - examples/install_scripts/a2c-ubuntu22-apache2.sh ${GITHUB_REF##*/} - - - name: "Local modification to get a2c running" - run: | - sudo apt-get install -y socat - sudo chmod 777 /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo echo "profile_id: 101" >> /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo sed -i "s/Listen 80/Listen 8080/g" /etc/apache2/ports.conf - sudo sed -i "s/*:80/*:8080/g" /etc/apache2/sites-available/acme2certifier.conf - sudo sed -i "s/examples\/ca_handler/\/var\/www\/acme2certifier\/examples\/ca_handler/g" /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo sed -i "s/volume\/acme_ca/\/var\/www\/acme2certifier\/volume\/acme_ca/g" /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo sed -i "s/challenge_validation_disable: False/challenge_validation_disable: True/g" /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo service apache2 restart - cat /var/www/acme2certifier/acme_srv/acme_srv.cfg - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "Test http://acme-srv/directory is accessable" - run: curl -f http://127.0.0.1:8080/directory - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ REGISTER] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://${{ env.RUNNER_IP }}:8080 --register-account --accountemail 'acme-sh@example.com' --debug 3 - - - name: "[ ENROLL] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://${{ env.RUNNER_IP }}:8080 --issue -d acme-sh.acme --standalone --debug 3 --output-insecure - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp /var/log/apache2 ${{ github.workspace }}/artifact/data/ - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz data - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: apache.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - - nginx_wsgi: - name: "nginx_wsgi" - runs-on: ubuntu-latest - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "[ PREPARE ] get runner ip" - run: | - echo RUNNER_IP=$(ip addr show eth0 | grep -i "inet " | cut -d ' ' -f 6 | cut -d '/' -f 1) >> $GITHUB_ENV - echo RUNNER_PATH=$(pwd | sed 's_/_\\/_g') >> $GITHUB_ENV - - run: echo "runner IP is ${{ env.RUNNER_IP }}" - - - name: Branch name - run: echo running on branch ${GITHUB_REF##*/} - - - name: "Run install script" - run: | - sudo mkdir -p data - sh examples/install_scripts/a2c-ubuntu22-nginx.sh - - - name: "Local modification to get a2c running" - run: | - sudo apt-get install -y socat - sudo chmod 777 /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo echo "profile_id: 101" >> /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo sed -i "s/listen 80/listen 8080/g" /etc/nginx/sites-enabled/acme_srv.conf - sudo sed -i "s/listen [::]:80/listen [::]:8080/g" /etc/nginx/sites-enabled/acme_srv.conf - sudo sed -i "s/examples\/ca_handler/\/var\/www\/acme2certifier\/examples\/ca_handler/g" /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo sed -i "s/volume\/acme_ca/\/var\/www\/acme2certifier\/volume\/acme_ca/g" /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo sed -i "s/challenge_validation_disable: False/challenge_validation_disable: True/g" /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo service nginx restart - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "Test http://acme-srv/directory is accessable" - run: curl -f http://127.0.0.1:8080/directory - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ REGISTER] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://${{ env.RUNNER_IP }}:8080 --register-account --accountemail 'acme-sh@example.com' --debug 3 - - - name: "[ ENROLL] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://${{ env.RUNNER_IP }}:8080 --issue -d acme-sh.acme --standalone --debug 3 --output-insecure - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp /var/log/apache2 ${{ github.workspace }}/artifact/data/ - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz data - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: nginx.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - - alma_nginx_wsgi: - name: "alma_nginx_wsgi" - runs-on: ubuntu-latest - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "[ PREPARE ] get runner ip" - run: | - echo RUNNER_IP=$(ip addr show eth0 | grep -i "inet " | cut -d ' ' -f 6 | cut -d '/' -f 1) >> $GITHUB_ENV - echo RUNNER_PATH=$(pwd | sed 's_/_\\/_g') >> $GITHUB_ENV - - run: echo "runner IP is ${{ env.RUNNER_IP }}" - - - name: Branch name - run: echo running on branch ${GITHUB_REF##*/} - - - name: "[ PREPARE ] environment" - run: | - docker network create acme - echo "exit 0" >> examples/install_scripts/a2c-centos9-nginx.sh - - - name: "[ PREPARE ] Almalinux instance" - run: | - cat examples/Docker/almalinux-systemd/Dockerfile | docker build -t almalinux-systemd -f - . --no-cache - docker run -d -id --privileged --network acme --name=acme-srv -v "$(pwd)/":/tmp/acme2certifier almalinux-systemd - - - name: "[ RUN ] Execute install scipt" - run: | - docker exec acme-srv sh /tmp/acme2certifier/examples/Docker/almalinux-systemd/script_tester.sh - - - name: "Test http://acme-srv/directory is accessible" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - sudo mkdir acme-sh - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ REGISTER] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --debug 3 - - - name: "[ ENROLL] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --issue -d acme-sh.acme --standalone --debug 3 --output-insecure - openssl verify -CAfile test/ca/root-ca-cert.pem -untrusted test/ca/sub-ca-cert.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp acme-sh/ ${{ github.workspace }}/artifact/acme-sh/ - docker exec acme-srv cat /var/log/messages > ${{ github.workspace }}/artifact/acme-srv.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz acme-srv.log acme-sh - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: alma_nginx_wsgi.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - - alma_nginx_wsgi_rpm: - name: "alma_nginx_wsgi_rpm" - runs-on: ubuntu-latest - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: Branch name - run: echo running on branch ${GITHUB_REF##*/} - - - name: Retrieve Version from version.py - run: | - echo TAG_NAME=$(cat acme_srv/version.py | grep -i __version__ | head -n 1 | sed 's/__version__ = //g' | sed s/\'//g) >> $GITHUB_ENV - - run: echo "Latest tag is ${{ env.TAG_NAME }}" - - - name: update version number in spec file - run: | - # sudo sed -i "s/Source0:.*/Source0: %{name}-%{version}.tar.gz/g" examples/install_scripts/rpm/acme2certifier.spec - sudo sed -i "s/__version__/${{ env.TAG_NAME }}/g" examples/install_scripts/rpm/acme2certifier.spec - cat examples/install_scripts/rpm/acme2certifier.spec - - - name: build RPM package - id: rpm - uses: grindsa/rpmbuild@alma9 - with: - spec_file: "examples/install_scripts/rpm/acme2certifier.spec" - - - run: echo "path is ${{ steps.rpm.outputs.rpm_dir_path }}" - - - name: "[ PREPARE ] Setup environment" - run: | - docker network create acme - mkdir -p data/acme_ca/certs/ - sudo cp ${{ steps.rpm.outputs.rpm_dir_path }}noarch/acme2certifier-${{ env.TAG_NAME }}-1.0.noarch.rpm data - sudo cp .github/openssl_ca_handler.py_acme_srv_choosen_handler.cfg data/acme_srv.cfg - sudo chmod 777 data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> data/acme_srv.cfg - sudo echo "profile_id: 101" >> data/acme_srv.cfg - sudo cp examples/Docker/almalinux-systemd/rpm_tester.sh data - cat data/acme_srv.cfg - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "[ PREPARE ] Almalinux instance" - run: | - cat examples/Docker/almalinux-systemd/Dockerfile | docker build -t almalinux-systemd -f - . --no-cache - docker run -d -id --privileged --network acme --name=acme-srv -v "$(pwd)/data":/tmp/acme2certifier almalinux-systemd - - - name: "[ RUN ] Execute install scipt" - run: | - docker exec acme-srv sh /tmp/acme2certifier/rpm_tester.sh - - - name: "Test http://acme-srv/directory is accessible" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - sudo mkdir acme-sh - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ REGISTER] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --debug 3 - - - name: "[ ENROLL] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --issue -d acme-sh.acme --standalone --debug 3 --output-insecure - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp acme-sh/ ${{ github.workspace }}/artifact/acme-sh/ - docker exec acme-srv cat /var/log/messages > ${{ github.workspace }}/artifact/acme-srv.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz data acme-srv.log acme-sh - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: alma_nginx_wsgi_rpm.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - - deb_apache2: - name: "deb_apache2" - runs-on: ubuntu-latest - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "[ PREPARE ] get runner ip" - run: | - echo RUNNER_IP=$(ip addr show eth0 | grep -i "inet " | cut -d ' ' -f 6 | cut -d '/' -f 1) >> $GITHUB_ENV - echo RUNNER_PATH=$(pwd | sed 's_/_\\/_g') >> $GITHUB_ENV - - run: echo "runner IP is ${{ env.RUNNER_IP }}" - - - name: Retrieve Version from version.py - run: | - echo TAG_NAME=$(cat acme_srv/version.py | grep -i __version__ | head -n 1 | sed 's/__version__ = //g' | sed s/\'//g) >> $GITHUB_ENV - - run: echo "Latest tag is ${{ env.TAG_NAME }}" - - - name: "[ PREPARE ] environment to build deb package" - run: | - sudo apt-get update && sudo apt-get -y upgrade - sudo apt-get -y install build-essential fakeroot dpkg-dev devscripts debhelper - rm setup.py - cp -R examples/install_scripts/debian ./ - sudo sed -i "s/__version__/${{ env.TAG_NAME }}/g" debian/changelog - cd ../ - tar cvfz ../acme2certifier_${{ env.TAG_NAME }}.orig.tar.gz ./ - - - - name: "[ BUILD ] build debian package" - run: | - dpkg-buildpackage -uc -us - dpkg -c ../acme2certifier_${{ env.TAG_NAME }}-1_all.deb - - - name: "[ Install ] install apache2 and acme2certifier packages" - run: | - sudo apt-get update - sudo apt-get install -y apache2 apache2-data libapache2-mod-wsgi-py3 - sudo apt-get install -y ../acme2certifier_${{ env.TAG_NAME }}-1_all.deb - - - name: "[ PREPARE ] configure a2c" - run: | - sudo cp /var/www/acme2certifier/examples/apache2/apache_wsgi.conf /etc/apache2/sites-available/acme2certifier.conf - sudo a2ensite acme2certifier - sudo rm /etc/apache2/sites-enabled/000-default.conf - sudo cp .github/openssl_ca_handler.py_acme_srv_choosen_handler.cfg /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo chmod 777 /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo echo "profile_id: 101" >> /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo chown -R www-data.www-data /var/www/acme2certifier - sudo systemctl start apache2 - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "[ TEST ] Test http://acme-srv/directory is accessable" - run: curl -f http://127.0.0.1/directory - - - name: "[ PREPARE ] Modfiy configuration to allow certifiate enrollment" - run: | - # sudo apt-get install -y socat - sudo sed -i "s/Listen 80/Listen 8080/g" /etc/apache2/ports.conf - sudo sed -i "s/*:80/*:8080/g" /etc/apache2/sites-available/acme2certifier.conf - sudo sed -i "s/examples\/ca_handler/\/var\/www\/acme2certifier\/examples\/ca_handler/g" /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo sed -i "s/volume\/acme_ca/\/var\/www\/acme2certifier\/volume\/acme_ca/g" /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo sed -i "s/challenge_validation_disable: False/challenge_validation_disable: True/g" /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo systemctl restart apache2 - - - name: "[ TEST ] Test http://acme-srv/directory is accessable" - run: curl -f http://127.0.0.1:8080/directory - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ REGISTER] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://${{ env.RUNNER_IP }}:8080 --register-account --accountemail 'acme-sh@example.com' --debug 3 - - - name: "[ ENROLL] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://${{ env.RUNNER_IP }}:8080 --issue -d acme-sh.acme --standalone --debug 3 --output-insecure - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp /var/log/apache2 ${{ github.workspace }}/artifact/data/ - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz data - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: deb_apache.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - - deb_nginx: - name: "deb_nginx" - runs-on: ubuntu-latest - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "[ PREPARE ] get runner ip" - run: | - echo RUNNER_IP=$(ip addr show eth0 | grep -i "inet " | cut -d ' ' -f 6 | cut -d '/' -f 1) >> $GITHUB_ENV - echo RUNNER_PATH=$(pwd | sed 's_/_\\/_g') >> $GITHUB_ENV - - run: echo "runner IP is ${{ env.RUNNER_IP }}" - - - name: Retrieve Version from version.py - run: | - echo TAG_NAME=$(cat acme_srv/version.py | grep -i __version__ | head -n 1 | sed 's/__version__ = //g' | sed s/\'//g) >> $GITHUB_ENV - - run: echo "Latest tag is ${{ env.TAG_NAME }}" - - - name: "[ PREPARE ] environment to build deb package" - run: | - sudo apt-get update && sudo apt-get -y upgrade - sudo apt-get -y install build-essential fakeroot dpkg-dev devscripts debhelper - rm setup.py - cp -R examples/install_scripts/debian ./ - sudo sed -i "s/__version__/${{ env.TAG_NAME }}/g" debian/changelog - cd ../ - tar cvfz ../acme2certifier_${{ env.TAG_NAME }}.orig.tar.gz ./ - - - name: "[ BUILD ] build debian package" - run: | - dpkg-buildpackage -uc -us - dpkg -c ../acme2certifier_${{ env.TAG_NAME }}-1_all.deb - - - name: "[ Install ] install nginx and acme2certifier packages" - run: | - sudo apt-get update - sudo apt-get install -y python3-pip nginx uwsgi uwsgi-plugin-python3 - sudo apt-get install -y ../acme2certifier_${{ env.TAG_NAME }}-1_all.deb - - - name: "[PREPARE] Local modification to get a2c running" - run: | - sed -i "s/run\/uwsgi\/acme.sock/var\/www\/acme2certifier\/acme.sock/g" examples/nginx/nginx_acme_srv.conf - sudo cp examples/nginx/nginx_acme_srv.conf /etc/nginx/sites-available/acme_srv.conf - sudo rm /etc/nginx/sites-enabled/default - sudo ln -s /etc/nginx/sites-available/acme_srv.conf /etc/nginx/sites-enabled/acme_srv.conf - sudo chown -R www-data.www-data /var/www/acme2certifier/ - sudo systemctl start nginx - - - name: "[PREPARE] Modify uwsgi configuration file" - run: | - sed -i "s/\/run\/uwsgi\/acme.sock/acme.sock/g" examples/nginx/acme2certifier.ini - sed -i "s/nginx/www-data/g" examples/nginx/acme2certifier.ini - echo "plugins=python3" >> examples/nginx/acme2certifier.ini - sudo cp examples/nginx/acme2certifier.ini /var/www/acme2certifier - - - name: "[PREPARE] create a2c service" - run: | - cat < acme2certifier.service - [Unit] - Description=uWSGI instance to serve acme2certifier - After=network.target - - [Service] - User=www-data - Group=www-data - WorkingDirectory=/var/www/acme2certifier - Environment="PATH=/var/www/acme2certifier" - ExecStart=uwsgi --ini acme2certifier.ini - - [Install] - WantedBy=multi-user.target - EOT - - sudo cp acme2certifier.service /etc/systemd/system/acme2certifier.service - sudo systemctl start acme2certifier - sudo systemctl enable acme2certifier - - - name: "[ TEST ] Test http://acme-srv/directory is accessable" - run: curl -f http://127.0.0.1/directory - - - name: "[ PREPARE ] configure a2c" - run: | - sudo cp /var/www/acme2certifier/examples/apache2/apache_wsgi.conf /etc/apache2/sites-available/acme2certifier.conf - sudo a2ensite acme2certifier - sudo rm /etc/apache2/sites-enabled/000-default.conf - sudo chmod 777 /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo cp .github/openssl_ca_handler.py_acme_srv_choosen_handler.cfg /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo echo "profile_id: 101" >> /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo chown -R www-data.www-data /var/www/acme2certifier - sudo systemctl start nginx - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - - - name: "[ PREPARE ] Modfiy configuration to allow certifiate enrollment" - run: | - sudo sed -i "s/listen 80/listen 8080/g" /etc/nginx/sites-enabled/acme_srv.conf - sudo sed -i "s/listen [::]:80/listen [::]:8080/g" /etc/nginx/sites-enabled/acme_srv.conf - sudo sed -i "s/examples\/ca_handler/\/var\/www\/acme2certifier\/examples\/ca_handler/g" /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo sed -i "s/volume\/acme_ca/\/var\/www\/acme2certifier\/volume\/acme_ca/g" /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo sed -i "s/challenge_validation_disable: False/challenge_validation_disable: True/g" /var/www/acme2certifier/acme_srv/acme_srv.cfg - sudo systemctl restart nginx - - - name: "[ TEST ] Test http://acme-srv/directory is accessable" - run: curl -f http://127.0.0.1:8080/directory - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ REGISTER] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://${{ env.RUNNER_IP }}:8080 --register-account --accountemail 'acme-sh@example.com' --debug 3 - - - name: "[ ENROLL] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://${{ env.RUNNER_IP }}:8080 --issue -d acme-sh.acme --standalone --debug 3 --output-insecure - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp /var/log/nginx ${{ github.workspace }}/artifact/data/ - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz data - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: deb_nginx.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - diff --git a/.github/workflows/markdown-check.yml b/.github/workflows/markdown-check.yml deleted file mode 100644 index 3cb45b18..00000000 --- a/.github/workflows/markdown-check.yml +++ /dev/null @@ -1,30 +0,0 @@ -# workflow to run the acme2certifier unittest suite - -name: Markdown check - -on: - push: - pull_request: - branches: [ devel ] - schedule: - # * is a special character in YAML so you have to quote this string - - cron: '0 2 * * 6' - -jobs: - markdown-check: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@master - - uses: gaurav-nelson/github-action-markdown-link-check@v1 - - name: Lint changelog file root - uses: avto-dev/markdown-lint@v1 - with: - args: '*.md' - - name: Lint changelog file docs - uses: avto-dev/markdown-lint@v1 - with: - args: './docs/*.md' - - name: Lint changelog file docker - uses: avto-dev/markdown-lint@v1 - with: - args: './examples/Docker/*.md' diff --git a/.github/workflows/proxy-test.yml b/.github/workflows/proxy-test.yml deleted file mode 100644 index 23833cbe..00000000 --- a/.github/workflows/proxy-test.yml +++ /dev/null @@ -1,478 +0,0 @@ -name: Proxy tests - -on: - push: - pull_request: - branches: [ devel ] - schedule: - # * is a special character in YAML so you have to quote this string - - cron: '0 2 * * 6' - -jobs: - proxy_tests: - name: "proxy_tests" - runs-on: ubuntu-latest - steps: - - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "[ PREPARE ] create network" - run: | - docker network create acme - - - name: "[ PREPARE ] proxy container" - run: | - docker pull mosajjal/pproxy:latest - docker run -d -it --name=proxy --network acme --rm -p 8080:8080 mosajjal/pproxy:latest -vv & - - - name: "[ PREPARE ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "[ PREPARE ] Build docker-compose (apache2_wsgi)" - working-directory: examples/Docker/ - run: | - sudo mkdir -p data - docker-compose up -d - docker-compose logs - - - name: "Test http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "[ PREPARE ] setup certifier ca_handler for socks proxy usage" - run: | - sudo cp examples/ca_handler/certifier_ca_handler.py examples/Docker/data/ca_handler.py - sudo cp .github/openssl_ca_handler.py_acme_srv_default_handler.cfg examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "api_host: ${{ secrets.NCM_API_HOST }}" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: ${{ secrets.NCM_API_USER }}" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: ${{ secrets.NCM_API_PASSWORD }}" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: ${{ secrets.NCM_CA_NAME }}" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: ${{ secrets.NCM_CA_BUNDLE }}" >> examples/Docker/data/acme_srv.cfg - sudo sed -i "s/debug: True/debug: True\nproxy_server_list: {\"ncm.nclm.eu\$\": \"socks5:\/\/proxy.acme:8080\"}/g" examples/Docker/data/acme_srv.cfg - cd examples/Docker/ - docker-compose restart - docker-compose logs - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ ENROLL ] via certifier ca_handler" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --standalone --debug 3 --output-insecure --force - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - - name: "[ REVOKE ] via certifier ca_handler" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --revoke -d acme-sh.acme --standalone --debug 3 --output-insecure - - - name: "[ CHECK ] proxy logs" - run: | - docker logs proxy | grep socks5 | grep -- "->" - docker stop proxy - docker run -d -it --name=proxy --network acme --rm -p 8080:8080 mosajjal/pproxy:latest -vv & - - - name: "[ PREPARE ] setup certifier ca_handler for http proxy usage" - run: | - sudo cp examples/ca_handler/certifier_ca_handler.py examples/Docker/data/ca_handler.py - sudo cp .github/openssl_ca_handler.py_acme_srv_default_handler.cfg examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "api_host: ${{ secrets.NCM_API_HOST }}" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: ${{ secrets.NCM_API_USER }}" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: ${{ secrets.NCM_API_PASSWORD }}" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: ${{ secrets.NCM_CA_NAME }}" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: ${{ secrets.NCM_CA_BUNDLE }}" >> examples/Docker/data/acme_srv.cfg - sudo sed -i "s/debug: True/debug: True\nproxy_server_list: {\"ncm.nclm.eu\$\": \"http:\/\/proxy.acme:8080\"}/g" examples/Docker/data/acme_srv.cfg - cd examples/Docker/ - docker-compose restart - docker-compose logs - - - name: "[ ENROLL ] via certifier ca_handler" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --standalone --debug 3 --output-insecure --force - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - - name: "[ REVOKE ] via certifier ca_handler" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --revoke -d acme-sh.acme --standalone --debug 3 --output-insecure - - - name: "[ CHECK ] proxy logs" - run: | - docker logs proxy | grep http | grep -- "->" - docker stop proxy - docker run -d -it --name=proxy --network acme --rm -p 8080:8080 mosajjal/pproxy:latest -vv & - - - name: "[ PREPARE ] setup nclm ca_handler for socks proxy usage" - run: | - sudo cp examples/ca_handler/nclm_ca_handler.py examples/Docker/data/ca_handler.py - sudo cp .github/openssl_ca_handler.py_acme_srv_default_handler.cfg examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "api_host: ${{ secrets.NCLM_API_HOST }}" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: ${{ secrets.NCLM_API_USER }}" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: ${{ secrets.NCLM_API_PASSWORD }}" >> examples/Docker/data/acme_srv.cfg - sudo echo "tsg_name: ${{ secrets.NCLM_TSG_NAME }}" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: ${{ secrets.NCLM_CA_NAME }}" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_id_list: [${{ secrets.NCLM_CA_ID_LIST }}]" >> examples/Docker/data/acme_srv.cfg - sudo sed -i "s/debug: True/debug: True\nproxy_server_list: {\"nclm.eu\$\": \"socks5:\/\/proxy.acme:8080\"}/g" examples/Docker/data/acme_srv.cfg - cd examples/Docker/ - docker-compose restart - docker-compose logs - - - name: "[ ENROLL ] via nclm ca_handler" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --standalone --debug 3 --output-insecure --force - # openssl verify -CAfile acme.sh/acme-sh.acme/ca.cer acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - - name: "[ CHECK ] proxy logs" - run: | - docker logs proxy | grep socks5 | grep -- "->" - docker stop proxy - docker run -d -it --name=proxy --network acme --rm -p 8080:8080 mosajjal/pproxy:latest -vv & - - - name: "[ PREPARE ] setup nclm ca_handler for http proxy usage" - run: | - sudo cp examples/ca_handler/nclm_ca_handler.py examples/Docker/data/ca_handler.py - sudo cp .github/openssl_ca_handler.py_acme_srv_default_handler.cfg examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "api_host: ${{ secrets.NCLM_API_HOST }}" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: ${{ secrets.NCLM_API_USER }}" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: ${{ secrets.NCLM_API_PASSWORD }}" >> examples/Docker/data/acme_srv.cfg - sudo echo "tsg_name: ${{ secrets.NCLM_TSG_NAME }}" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: ${{ secrets.NCLM_CA_NAME }}" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_id_list: [${{ secrets.NCLM_CA_ID_LIST }}]" >> examples/Docker/data/acme_srv.cfg - sudo sed -i "s/debug: True/debug: True\nproxy_server_list: {\"nclm.eu\$\": \"http:\/\/proxy.acme:8080\"}/g" examples/Docker/data/acme_srv.cfg - cd examples/Docker/ - docker-compose restart - docker-compose logs - - - name: "[ ENROLL ] via nclm ca_handler" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --standalone --debug 3 --output-insecure --force - # openssl verify -CAfile acme.sh/acme-sh.acme/ca.cer acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - - name: "[ CHECK ] proxy logs" - run: | - docker logs proxy | grep http | grep -- "->" - docker stop proxy - docker run -d -it --name=proxy --network acme --rm -p 8080:8080 mosajjal/pproxy:latest -vv & - - - name: "[ stop ] proxy container" - run: | - docker stop proxy - - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: proxy.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - - - proxy_tests_rpm: - name: "proxy_tests_rpm" - runs-on: ubuntu-latest - steps: - - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: Retrieve Version from version.py - run: | - echo TAG_NAME=$(cat acme_srv/version.py | grep -i __version__ | head -n 1 | sed 's/__version__ = //g' | sed s/\'//g) >> $GITHUB_ENV - - run: echo "Latest tag is ${{ env.TAG_NAME }}" - - - name: update version number in spec file - run: | - # sudo sed -i "s/Source0:.*/Source0: %{name}-%{version}.tar.gz/g" examples/install_scripts/rpm/acme2certifier.spec - sudo sed -i "s/__version__/${{ env.TAG_NAME }}/g" examples/install_scripts/rpm/acme2certifier.spec - cat examples/install_scripts/rpm/acme2certifier.spec - - - name: build RPM package - id: rpm - uses: grindsa/rpmbuild@alma9 - with: - spec_file: "examples/install_scripts/rpm/acme2certifier.spec" - - - run: echo "path is ${{ steps.rpm.outputs.rpm_dir_path }}" - - - name: "[ PREPARE ] setup environment for alma installation" - run: | - docker network create acme - sudo mkdir -p data - sudo chmod -R 777 data - sudo cp ${{ steps.rpm.outputs.rpm_dir_path }}noarch/acme2certifier-${{ env.TAG_NAME }}-1.0.noarch.rpm data - # sudo cp examples/install_scripts/rpm/*.rpm data - sudo cp examples/Docker/almalinux-systemd/rpm_tester.sh data - - - name: "Retrieve rpms from SBOM repo" - run: | - git clone https://$GH_SBOM_USER:$GH_SBOM_TOKEN@github.com/$GH_SBOM_USER/sbom /tmp/sbom - cp /tmp/sbom/rpm-repo/RPMs/*ntlm*.rpm data - env: - GH_SBOM_USER: ${{ secrets.GH_SBOM_USER }} - GH_SBOM_TOKEN: ${{ secrets.GH_SBOM_TOKEN }} - - - name: "[ PREPARE ] proxy container" - run: | - docker pull mosajjal/pproxy:latest - docker run -d -it --name=proxy --network acme --rm -p 8080:8080 mosajjal/pproxy:latest -vv & - - - name: "[ PREPARE ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: Retrieve proxy-ip - run: | - echo PROXY_IP=$(docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' proxy) >> $GITHUB_ENV - - run: echo "Latest tag is ${{ env.PROXY_IP }}" - - - name: "[ PREPARE ] prepare acme_srv.cfg with certifier_ca_handler and socks proxy usage" - run: | - mkdir -p data/acme_ca - sudo cp test/ca/certsrv_ca_certs.pem data/acme_ca/ca_certs.pem - sudo touch data/acme_srv.cfg - sudo chmod 777 data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> data/acme_srv.cfg - sudo sed -i "s/debug: True/debug: True\nproxy_server_list: {\"ncm.nclm.eu\$\": \"socks5:\/\/proxy.acme:8080\"}/g" data/acme_srv.cfg - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "[ PREPARE ] Almalinux instance" - run: | - cat examples/Docker/almalinux-systemd/Dockerfile | docker build -t almalinux-systemd -f - . --no-cache - docker run -d -id --privileged --network acme --name=acme-srv -v "$(pwd)/data":/tmp/acme2certifier almalinux-systemd - - - name: "[ RUN ] Execute install scipt" - run: | - docker exec acme-srv sh /tmp/acme2certifier/rpm_tester.sh - - - name: "Test if http://acme-srv/directory is accessible" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ ENROLL ] acme.sh - http challenge validation" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme -d acme-sh. --standalone --debug 3 --output-insecure --force - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - - name: "[ CHECK ] proxy logs" - run: | - docker logs proxy | grep socks5 | grep -- "->" - docker stop proxy - docker run -d -it --name=proxy --network acme --rm -p 8080:8080 mosajjal/pproxy:latest -vv & - - - name: "[ ENROLL ] acme.sh - alpn challenge validation" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --alpn -d acme-sh. --alpn --standalone --debug 3 --output-insecure --force - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - - name: "[ CHECK ] proxy logs" - run: | - docker logs proxy | grep socks5 | grep -- "->" - docker stop proxy - docker run -d -it --name=proxy --network acme --rm -p 8080:8080 mosajjal/pproxy:latest -vv & - - - name: "[ REVOKE ] via certifier ca_handler" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --revoke -d acme-sh.acme --standalone --debug 3 --output-insecure - - - name: "[ CHECK ] proxy logs" - run: | - docker logs proxy | grep socks5 | grep -- "->" - docker stop proxy - docker run -d -it --name=proxy --network acme --rm -p 8080:8080 mosajjal/pproxy:latest -vv & - - - name: "[ PREPARE ] prepare acme_srv.cfg with certifier_ca_handler and http proxy usage" - run: | - mkdir -p data/acme_ca - sudo cp test/ca/certsrv_ca_certs.pem data/acme_ca/ca_certs.pem - sudo touch data/acme_srv.cfg - sudo chmod 777 data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> data/acme_srv.cfg - sudo sed -i "s/debug: True/debug: True\nproxy_server_list: {\"ncm.nclm.eu\$\": \"http:\/\/proxy.acme:8080\"}/g" data/acme_srv.cfg - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "[ PREPARE ] reconfigure a2c " - run: | - docker exec acme-srv sh /tmp/acme2certifier/rpm_tester.sh restart - - - name: "Test if http://acme-srv/directory is accessible" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "[ ENROLL ] acme.sh - http challenge validation" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme -d acme-sh. --standalone --debug 3 --output-insecure --force - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - - name: "[ CHECK ] proxy logs" - run: | - docker logs proxy | grep http | grep -- "->" - docker stop proxy - docker run -d -it --name=proxy --network acme --rm -p 8080:8080 mosajjal/pproxy:latest -vv & - - - name: "[ ENROLL ] acme.sh - alpn challenge validation" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --alpn -d acme-sh. --alpn --standalone --debug 3 --output-insecure --force - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - - name: "[ CHECK ] proxy logs" - run: | - docker logs proxy | grep http | grep -- "->" - docker stop proxy - docker run -d -it --name=proxy --network acme --rm -p 8080:8080 mosajjal/pproxy:latest -vv & - - - name: "[ REVOKE ] via certifier ca_handler" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --revoke -d acme-sh.acme --standalone --debug 3 --output-insecure - - - name: "[ CHECK ] proxy logs" - run: | - docker logs proxy | grep http | grep -- "->" - docker stop proxy - docker run -d -it --name=proxy --network acme --rm -p 8080:8080 mosajjal/pproxy:latest -vv & - - - name: "[ PREPARE ] setup using nclm_ca_handler" - run: | - - - name: "[ PREPARE ] prepare acme_srv.cfg with nclm_ca_handler and socks proxy usage" - run: | - mkdir -p data/acme_ca - sudo cp test/ca/certsrv_ca_certs.pem data/acme_ca/ca_certs.pem - sudo touch data/acme_srv.cfg - sudo chmod 777 data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/nclm_ca_handler.py" >> data/acme_srv.cfg - sudo echo "api_host: $NCLM_API_HOST" >> data/acme_srv.cfg - sudo echo "api_user: $NCLM_API_USER" >> data/acme_srv.cfg - sudo echo "api_password: $NCLM_API_PASSWORD" >> data/acme_srv.cfg - sudo echo "tsg_name: $NCLM_TSG_NAME" >> data/acme_srv.cfg - sudo echo "ca_name: $NCLM_CA_NAME" >> data/acme_srv.cfg - sudo echo "ca_id_list: [$NCLM_CA_ID_LIST]" >> data/acme_srv.cfg - sudo sed -i "s/revocation_reason_check_disable: False/revocation_reason_check_disable: False\nenrollment_timeout: 30/g" data/acme_srv.cfg - sudo sed -i "s/debug: True/debug: True\nproxy_server_list: {\"nclm.eu\$\": \"socks5:\/\/proxy.acme:8080\"}/g" data/acme_srv.cfg - env: - NCLM_API_HOST: ${{ secrets.NCLM_API_HOST }} - NCLM_API_USER: ${{ secrets.NCLM_API_USER }} - NCLM_API_PASSWORD: ${{ secrets.NCLM_API_PASSWORD }} - NCLM_TSG_NAME: ${{ secrets.NCLM_TSG_NAME }} - NCLM_CA_NAME: ${{ secrets.NCLM_CA_NAME }} - NCLM_CA_ID_LIST: ${{ secrets.NCLM_CA_ID_LIST }} - - - name: "[ PREPARE ] reconfigure a2c " - run: | - docker exec acme-srv sh /tmp/acme2certifier/rpm_tester.sh restart - - - name: "[ ENROLL ] via nclm_ca_handler" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --standalone --debug 3 --output-insecure --force & - - - name: "[ CHECK ] proxy logs" - run: | - docker logs proxy | grep socks5 | grep -- "->" - docker stop proxy - docker run -d -it --name=proxy --network acme --rm -p 8080:8080 mosajjal/pproxy:latest -vv & - - - name: "[ PREPARE ] prepare acme_srv.cfg with nclm_ca_handler and http proxy usage" - run: | - mkdir -p data/acme_ca - sudo cp test/ca/certsrv_ca_certs.pem data/acme_ca/ca_certs.pem - sudo touch data/acme_srv.cfg - sudo chmod 777 data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/nclm_ca_handler.py" >> data/acme_srv.cfg - sudo echo "api_host: $NCLM_API_HOST" >> data/acme_srv.cfg - sudo echo "api_user: $NCLM_API_USER" >> data/acme_srv.cfg - sudo echo "api_password: $NCLM_API_PASSWORD" >> data/acme_srv.cfg - sudo echo "tsg_name: $NCLM_TSG_NAME" >> data/acme_srv.cfg - sudo echo "ca_name: $NCLM_CA_NAME" >> data/acme_srv.cfg - sudo echo "ca_id_list: [$NCLM_CA_ID_LIST]" >> data/acme_srv.cfg - sudo sed -i "s/revocation_reason_check_disable: False/revocation_reason_check_disable: False\nenrollment_timeout: 30/g" data/acme_srv.cfg - sudo sed -i "s/debug: True/debug: True\nproxy_server_list: {\"nclm.eu\$\": \"http:\/\/proxy.acme:8080\"}/g" data/acme_srv.cfg - env: - NCLM_API_HOST: ${{ secrets.NCLM_API_HOST }} - NCLM_API_USER: ${{ secrets.NCLM_API_USER }} - NCLM_API_PASSWORD: ${{ secrets.NCLM_API_PASSWORD }} - NCLM_TSG_NAME: ${{ secrets.NCLM_TSG_NAME }} - NCLM_CA_NAME: ${{ secrets.NCLM_CA_NAME }} - NCLM_CA_ID_LIST: ${{ secrets.NCLM_CA_ID_LIST }} - - - name: "[ PREPARE ] reconfigure a2c " - run: | - docker exec acme-srv sh /tmp/acme2certifier/rpm_tester.sh restart - - - name: "[ ENROLL ] via nclm_ca_handler" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --standalone --debug 3 --output-insecure --force & - - - name: "[ CHECK ] proxy logs" - run: | - docker logs proxy | grep http | grep -- "->" - docker stop proxy - docker run -d -it --name=proxy --network acme --rm -p 8080:8080 mosajjal/pproxy:latest -vv & - - - name: "[ stop ] proxy container" - run: | - docker stop proxy - - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - docker exec acme-srv tar cvfz /tmp/acme2certifier/a2c.tgz /opt/acme2certifier - sudo cp -rp data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp acme-sh/ ${{ github.workspace }}/artifact/acme-sh/ - docker exec acme-srv cat /var/log/messages > ${{ github.workspace }}/artifact/acme-srv.log - docker logs proxy > ${{ github.workspace }}/artifact/proxy.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz data proxy.log acme-srv.log acme-sh - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: proxy-rpm.tar.gz - path: ${{ github.workspace }}/artifact/upload/ \ No newline at end of file diff --git a/.github/workflows/push_images_to_dockerhub.yml b/.github/workflows/push_images_to_dockerhub.yml deleted file mode 100644 index 7b3b9caa..00000000 --- a/.github/workflows/push_images_to_dockerhub.yml +++ /dev/null @@ -1,319 +0,0 @@ -name: Push images to dockerhub and ghcr.io -on: - push: - branches: - - "master" - schedule: - # * is a special character in YAML so you have to quote this string - - cron: '0 4 * * 6' -jobs: - - #update_docker_hub_description: - # runs-on: ubuntu-latest - # steps: - # - uses: actions/checkout@v3 - # - name: Docker Hub Description - # uses: peter-evans/dockerhub-description@v2 - # env: - # DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USER }} - # DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }} - # DOCKERHUB_REPOSITORY: grindsa/acme2certifier - - - build_and_upload_images_to_hub: - name: Push images to dockerhub and github - runs-on: ubuntu-latest - steps: - - name: "Get current version" - uses: oprypin/find-latest-tag@v1 - with: - repository: ${{ github.repository }} # The repository to scan. - releases-only: true # We know that all relevant tags have a GitHub release for them. - id: acme2certifier_ver # The step ID to refer to later. - - - name: Checkout code - uses: actions/checkout@v3 - - - name: "Retrieve Version from version.py" - run: | - echo APP_NAME=$(echo ${{ github.repository }} | awk -F / '{print $2}') >> $GITHUB_ENV - echo TAG_NAME=$(cat acme_srv/version.py | grep -i __version__ | head -n 1 | sed 's/__version__ = //g' | sed s/\'//g) >> $GITHUB_ENV - - - run: echo "Repo is at version ${{ steps.acme2certifier_ver.outputs.tag }}" - - run: echo "APP tag is ${{ env.APP_NAME }}" - - run: echo "Latest tag is ${{ env.TAG_NAME }}" - - - name: "Create images" - run: | - cat examples/Docker/apache2/wsgi/Dockerfile | docker build -t grindsa/acme2certifier:apache2-wsgi -t grindsa/acme2certifier:${{ env.TAG_NAME }}-apache2-wsgi -t ghcr.io/grindsa/acme2certifier:apache2-wsgi -t ghcr.io/grindsa/acme2certifier:${{ env.TAG_NAME }}-apache2-wsgi -f - . --no-cache - cat examples/Docker/apache2/django/Dockerfile | docker build -t grindsa/acme2certifier:apache2-django -t grindsa/acme2certifier:${{ env.TAG_NAME }}-apache2-django -t ghcr.io/grindsa/acme2certifier:apache2-django -t ghcr.io/grindsa/acme2certifier:${{ env.TAG_NAME }}-apache2-django -f - . --no-cache - cat examples/Docker/nginx/wsgi/Dockerfile | docker build -t grindsa/acme2certifier:nginx-wsgi -t grindsa/acme2certifier:${{ env.TAG_NAME }}-nginx-wsgi -t ghcr.io/grindsa/acme2certifier:nginx-wsgi -t ghcr.io/grindsa/acme2certifier:${{ env.TAG_NAME }}-nginx-wsgi -f - . --no-cache - cat examples/Docker/nginx/django/Dockerfile | docker build -t grindsa/acme2certifier:nginx-django -t grindsa/acme2certifier:${{ env.TAG_NAME }}-nginx-django -t ghcr.io/grindsa/acme2certifier:nginx-django -t ghcr.io/grindsa/acme2certifier:${{ env.TAG_NAME }}-nginx-django -f - . --no-cache - - - name: "upload images to hub.docker.com" - run: | - docker login -u ${{ secrets.DOCKERHUB_USER }} -p ${{ secrets.DOCKERHUB_TOKEN }} - docker push -a grindsa/acme2certifier - - - name: "upload images to ghcr.io" - run: | - docker login ghcr.io -u ${{ secrets.GHCR_USER }} -p ${{ secrets.GHCR_TOKEN }} - docker push -a ghcr.io/grindsa/acme2certifier - - - name: "Install syft" - run: | - sudo curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin - - - name: "Retrieve SBOM repo" - run: | - git clone https://$GH_SBOM_USER:$GH_SBOM_TOKEN@github.com/$GH_SBOM_USER/sbom /tmp/sbom - env: - GH_SBOM_USER: ${{ secrets.GH_SBOM_USER }} - GH_SBOM_TOKEN: ${{ secrets.GH_SBOM_TOKEN }} - - - name: "Generate SBOMs for a2c images " - run: | - mkdir -p /tmp/sbom/sbom/acme2certifier - syft grindsa/acme2certifier:apache2-wsgi > /tmp/sbom/sbom/acme2certifier/acme2certifier-apache2-wsgi_sbom.txt - syft grindsa/acme2certifier:apache2-wsgi -o json > /tmp/sbom/sbom/acme2certifier/acme2certifier_apache2-wsgi_sbom.json - syft grindsa/acme2certifier:apache2-django > /tmp/sbom/sbom/acme2certifier/acme2certifier-apache2-django_sbom.txt - syft grindsa/acme2certifier:apache2-django -o json > /tmp/sbom/sbom/acme2certifier/acme2certifier_apache2-django_sbom.json - syft grindsa/acme2certifier:nginx-wsgi > /tmp/sbom/sbom/acme2certifier/acme2certifier-nginx-wsgi_sbom.txt - syft grindsa/acme2certifier:nginx-wsgi -o json > /tmp/sbom/sbom/acme2certifier/acme2certifier_nginx-wsgi_sbom.json - syft grindsa/acme2certifier:nginx-django > /tmp/sbom/sbom/acme2certifier/acme2certifier-nginx-django_sbom.txt - syft grindsa/acme2certifier:nginx-django -o json > /tmp/sbom/sbom/acme2certifier/acme2certifier_nginx-django_sbom.json - - - name: "Upload Changes" - run: | - cd /tmp/sbom - git config --global user.email "grindelsack@gmail.com" - git config --global user.name "SBOM Generator" - git add sbom/acme2certifier/ - git commit -a -m "SBOM update" - git push - - - name: "delete images from local repository" - run: | - docker rmi $(docker images grindsa/acme2certifier -q) --no-prune --force - - apache2_wsgi: - name: Test acme2certifier:apache2-wsgi image - needs: [build_and_upload_images_to_hub] - runs-on: ubuntu-latest - steps: - - - name: Checkout code - uses: actions/checkout@v3 - - - name: "[ PREPARE ] setup openssl ca_handler" - run: | - docker network create acme - sudo mkdir -p examples/Docker/data - sudo cp examples/ca_handler/openssl_ca_handler.py examples/Docker/data/ca_handler.py - sudo mkdir -p examples/Docker/data/acme_ca/certs - sudo cp test/ca/sub-ca-key.pem test/ca/sub-ca-crl.pem test/ca/sub-ca-cert.pem test/ca/root-ca-cert.pem examples/Docker/data/acme_ca/ - sudo cp .github/openssl_ca_handler.py_acme_srv_default_handler.cfg examples/Docker/data/acme_srv.cfg - - - name: "[ PREPARE ] apache2 django container" - run: | - docker run -d -p 80:80 --rm -id --network acme --name=acme-srv -v "$(pwd)/examples/Docker/data":/var/www/acme2certifier/volume/ grindsa/acme2certifier:apache2-wsgi - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ ENROLL ] via openssl ca_handler" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --standalone --debug 3 --output-insecure --force - openssl verify -CAfile examples/Docker/data/acme_ca/root-ca-cert.pem -untrusted examples/Docker/data/acme_ca/sub-ca-cert.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - - name: "[ DEACTIVATE ] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --deactivate-account --debug 2 --output-insecure - - - name: "[ * ] collecting test data" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp acme-sh/ ${{ github.workspace }}/artifact/acme-sh/ - cd examples/Docker - docker logs acme-srv > ${{ github.workspace }}/artifact/docker.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker.log data acme-sh - - - name: "[ * ] uploading artifacts" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: apache_wsgi.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - - test_apache2_django: - name: Test acme2certifier:apache2-django image - needs: [build_and_upload_images_to_hub] - runs-on: ubuntu-latest - steps: - - - name: Checkout code - uses: actions/checkout@v3 - - - name: "[ PREPARE ] setup openssl ca_handler and django config" - run: | - docker network create acme - sudo mkdir -p examples/Docker/data - sudo cp examples/ca_handler/openssl_ca_handler.py examples/Docker/data/ca_handler.py - sudo mkdir -p examples/Docker/data/acme_ca/certs - sudo cp test/ca/sub-ca-key.pem test/ca/sub-ca-crl.pem test/ca/sub-ca-cert.pem test/ca/root-ca-cert.pem examples/Docker/data/acme_ca/ - sudo cp .github/openssl_ca_handler.py_acme_srv_default_handler.cfg examples/Docker/data/acme_srv.cfg - sudo cp .github/django_settings.py examples/Docker/data/settings.py - - - name: "[ PREPARE ] apache2 wsgi container" - run: | - docker run -d -p 80:80 --rm -id --network acme --name=acme-srv -v "$(pwd)/examples/Docker/data":/var/www/acme2certifier/volume/ grindsa/acme2certifier:apache2-django - - - name: "[ PREPARE ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 5s - - - name: "[ PREPARE ] django update" - run: | - docker exec acme-srv python3 /var/www/acme2certifier/tools/django_update.py - sudo chmod a+w examples/Docker/data/db.sqlite3 - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ ENROLL ] via openssl ca_handler" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --standalone --debug 3 --output-insecure --force - openssl verify -CAfile examples/Docker/data/acme_ca/root-ca-cert.pem -untrusted examples/Docker/data/acme_ca/sub-ca-cert.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - - name: "[ DEACTIVATE ] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --deactivate-account --debug 2 --output-insecure - - - name: "[ * ] collecting test data" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp acme-sh/ ${{ github.workspace }}/artifact/acme-sh/ - cd examples/Docker - docker logs acme-srv > ${{ github.workspace }}/artifact/docker.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker.log data acme-sh - - - name: "[ * ] uploading artifacts" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: apache_django.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - - nginx_wsgi: - name: Test acme2certifier:nginx-wsgi image - needs: [build_and_upload_images_to_hub] - runs-on: ubuntu-latest - steps: - - - name: Checkout code - uses: actions/checkout@v3 - - - name: "[ PREPARE ] setup openssl ca_handler" - run: | - docker network create acme - sudo mkdir -p examples/Docker/data - sudo cp examples/ca_handler/openssl_ca_handler.py examples/Docker/data/ca_handler.py - sudo mkdir -p examples/Docker/data/acme_ca/certs - sudo cp test/ca/sub-ca-key.pem test/ca/sub-ca-crl.pem test/ca/sub-ca-cert.pem test/ca/root-ca-cert.pem examples/Docker/data/acme_ca/ - sudo cp .github/openssl_ca_handler.py_acme_srv_default_handler.cfg examples/Docker/data/acme_srv.cfg - - - name: "[ PREPARE ] nginx wsgi container" - run: | - docker run -d -p 80:80 --rm -id --network acme --name=acme-srv -v "$(pwd)/examples/Docker/data":/var/www/acme2certifier/volume/ grindsa/acme2certifier:nginx-wsgi - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ ENROLL ] via openssl ca_handler" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --standalone --debug 3 --output-insecure --force - openssl verify -CAfile examples/Docker/data/acme_ca/root-ca-cert.pem -untrusted examples/Docker/data/acme_ca/sub-ca-cert.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - - name: "[ DEACTIVATE ] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --deactivate-account --debug 2 --output-insecure - - - name: "[ * ] collecting test data" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp acme-sh/ ${{ github.workspace }}/artifact/acme-sh/ - cd examples/Docker - docker logs acme-srv > ${{ github.workspace }}/artifact/docker.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker.log data acme-sh - - - name: "[ * ] uploading artifacts" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: nginx_wsgi.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - - test_nginx_django: - name: Test acme2certifier:nginx-django image - needs: [build_and_upload_images_to_hub] - runs-on: ubuntu-latest - steps: - - - name: Checkout code - uses: actions/checkout@v3 - - - name: "[ PREPARE ] setup openssl ca_handler and django config" - run: | - docker network create acme - sudo mkdir -p examples/Docker/data - sudo cp examples/ca_handler/openssl_ca_handler.py examples/Docker/data/ca_handler.py - sudo mkdir -p examples/Docker/data/acme_ca/certs - sudo cp test/ca/sub-ca-key.pem test/ca/sub-ca-crl.pem test/ca/sub-ca-cert.pem test/ca/root-ca-cert.pem examples/Docker/data/acme_ca/ - sudo cp .github/openssl_ca_handler.py_acme_srv_default_handler.cfg examples/Docker/data/acme_srv.cfg - sudo cp .github/django_settings.py examples/Docker/data/settings.py - - - name: "[ PREPARE ] nginx django container" - run: | - docker run -d -p 80:80 --rm -id --network acme --name=acme-srv -v "$(pwd)/examples/Docker/data":/var/www/acme2certifier/volume/ grindsa/acme2certifier:nginx-django - # docker exec acme-srv python3 /var/www/acme2certifier/tools/django_update.py - # sudo chmod a+w examples/Docker/data/db.sqlite3 - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ ENROLL ] via openssl ca_handler" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --standalone --debug 3 --output-insecure --force - openssl verify -CAfile examples/Docker/data/acme_ca/root-ca-cert.pem -untrusted examples/Docker/data/acme_ca/sub-ca-cert.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - - name: "[ DEACTIVATE ] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --deactivate-account --debug 2 --output-insecure - - - name: "[ * ] collecting test data" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp acme-sh/ ${{ github.workspace }}/artifact/acme-sh/ - cd examples/Docker - docker logs acme-srv > ${{ github.workspace }}/artifact/docker.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker.log data acme-sh - - - name: "[ * ] uploading artifacts" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: nginx_django.tar.gz - path: ${{ github.workspace }}/artifact/upload/ diff --git a/.github/workflows/push_rpm.yml b/.github/workflows/push_rpm.yml index f3934de4..9e04959e 100644 --- a/.github/workflows/push_rpm.yml +++ b/.github/workflows/push_rpm.yml @@ -22,6 +22,20 @@ jobs: - run: echo "APP tag is ${{ env.APP_NAME }}" - run: echo "Latest tag is ${{ env.TAG_NAME }}" + - name: Retrieve dbversion numbers from version.py and fixture.xml + run: | + echo DB_VERSION=$(cat acme_srv/version.py | grep -i __dbversion__ | head -n 1 | sed 's/__dbversion__ = //g' | sed s/\'//g) >> $GITHUB_ENV + echo FIXTURE_VERSION=$(awk '/name: dbversion/{getline; print $2}' examples/django/acme_srv/fixture/status.yaml | tr -d "'") >> $GITHUB_ENV + + - run: echo "db verion is ${{ env.DB_VERSION }}" + - run: echo "fixture verion is ${{ env.FIXTURE_VERSION }}" + + - name: Check fixture version + if: env.DB_VERSION != env.FIXTURE_VERSION + run: | + echo "Fixture version is not equal to db version" + exit 1 + - name: "[ PREPARE ] update version number in spec file" run: | sudo sed -i "s/__version__/${{ env.TAG_NAME }}/g" examples/install_scripts/rpm/acme2certifier.spec diff --git a/.github/workflows/python-test.yml b/.github/workflows/python-test.yml deleted file mode 100644 index 8cd772bc..00000000 --- a/.github/workflows/python-test.yml +++ /dev/null @@ -1,78 +0,0 @@ -# workflow to run the acme2certifier unittest suite - -name: Python Tests - -on: - push: - pull_request: - branches: [ devel ] - schedule: - # * is a special character in YAML so you have to quote this string - - cron: '0 2 * * 6' -jobs: - unittest: - runs-on: ubuntu-latest - strategy: - matrix: - python_version: ['3.x', '3.12', '3.11', '3.10', '3.9', '3.8'] - name: Python Unittest (${{ matrix.python_version }}) - steps: - - uses: actions/checkout@v3 - - name: Set up Python ${{ matrix.python_version }} - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python_version }} - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install pytest - if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - - name: cp - run: | - cp examples/ca_handler/skeleton_ca_handler.py acme_srv/ca_handler.py - cp examples/acme_srv.cfg acme_srv/ - - name: Python test - run: | - pytest - pylint: - runs-on: ubuntu-latest - strategy: - matrix: - python_version: [3.x, 3.8] - name: Pylint test (${{ matrix.python_version }}) - steps: - - uses: actions/checkout@v3 - - name: Set up Python ${{ matrix.python_version }} - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python_version }} - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install pylint pylint-exit - if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - - name: cp - run: | - cp examples/ca_handler/skeleton_ca_handler.py acme_srv/ca_handler.py - cp examples/db_handler/wsgi_handler.py acme_srv/db_handler.py - cp examples/acme_srv.cfg acme_srv/ - - name: "Pylint folder: acme" - run: | - pylint --rcfile=".github/pylintrc" acme_srv/ || pylint-exit $? - - name: "Pylint folder: tools" - run: | - pylint --rcfile=".github/pylintrc" tools/*.py || pylint-exit $? - - name: "Pylint folder: examples/db_handler" - run: | - pylint --rcfile=".github/pylintrc" examples/db_handler/*.py || pylint-exit $? - - name: "Pylint folder: examples/ca_handler" - run: | - pylint --rcfile=".github/pylintrc" examples/ca_handler/*.py || pylint-exit $? - - - name: "Linting with pycodestyle" - run: | - pip install pycodestyle - cp .github/pycodestyle ~/.config/pycodestyle - pycodestyle --show-source examples/. - pycodestyle --show-source acme_srv/. - pycodestyle --show-source tools/. diff --git a/.github/workflows/tnauth-test.yml b/.github/workflows/tnauth-test.yml deleted file mode 100644 index 7443791a..00000000 --- a/.github/workflows/tnauth-test.yml +++ /dev/null @@ -1,184 +0,0 @@ -name: Tnauth Tests - -on: - push: - pull_request: - branches: [ devel ] - schedule: - # * is a special character in YAML so you have to quote this string - - cron: '0 2 * * 6' - -jobs: - tnauth_tests: - name: "tnauth_tests" - runs-on: ubuntu-latest - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "[ PREPARE ] Build docker-compose (apache2_wsgi)" - working-directory: examples/Docker/ - run: | - sudo mkdir -p data - docker network create acme - docker-compose up -d - docker-compose logs - - - name: "Test http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - sudo sed -i "s/tnauthlist_support: False/tnauthlist_support: True/g" examples/Docker/data/acme_srv.cfg - cd examples/Docker/ - docker-compose restart - docker-compose logs - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "[ CURL ] install curl and socat and test connction" - run: | - sudo apt-get install -y curl socat - curl -f http://localhost:22280 - - - name: "[ ACME.SH ] install acme.sh" - run: | - mkdir /tmp/acme_sh - curl -kL https://github.com/grindsa/acme.sh/archive/tnauth_list_support.tar.gz | tar xz -C /tmp/acme_sh --strip-components=1 - - - name: "[ ACME.SH ] enroll certificate using tnauth identifier" - run: | - cd /tmp/acme_sh - /tmp/acme_sh/acme.sh --server http://127.0.0.1:22280 --accountemail grindsa@tnauth.acme --issue -d cert.acme.local --tnauth 123456 --spctoken 1234 --standalone --force --debug 2 - ls -la - - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: tnauth.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - - - tnauth_rpm_tests: - name: "tnauth_rpm_tests" - runs-on: ubuntu-latest - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: Retrieve Version from version.py - run: | - echo TAG_NAME=$(cat acme_srv/version.py | grep -i __version__ | head -n 1 | sed 's/__version__ = //g' | sed s/\'//g) >> $GITHUB_ENV - - run: echo "Latest tag is ${{ env.TAG_NAME }}" - - - name: update version number in spec file - run: | - # sudo sed -i "s/Source0:.*/Source0: %{name}-%{version}.tar.gz/g" examples/install_scripts/rpm/acme2certifier.spec - sudo sed -i "s/__version__/${{ env.TAG_NAME }}/g" examples/install_scripts/rpm/acme2certifier.spec - cat examples/install_scripts/rpm/acme2certifier.spec - - - name: build RPM package - id: rpm - uses: grindsa/rpmbuild@alma9 - with: - spec_file: "examples/install_scripts/rpm/acme2certifier.spec" - - - run: echo "path is ${{ steps.rpm.outputs.rpm_dir_path }}" - - - name: "[ PREPARE ] setup environment for alma installation" - run: | - docker network create acme - sudo mkdir -p data - sudo chmod -R 777 data - sudo cp ${{ steps.rpm.outputs.rpm_dir_path }}noarch/acme2certifier-${{ env.TAG_NAME }}-1.0.noarch.rpm data - sudo cp examples/Docker/almalinux-systemd/rpm_tester.sh data - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - mkdir -p data/acme_ca - sudo cp test/ca/certsrv_ca_certs.pem data/acme_ca/ca_certs.pem - sudo touch data/acme_srv.cfg - sudo chmod 777 data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > data/acme_srv.cfg - sudo echo "handler_file: /opt/acme2certifier/examples/ca_handler/certifier_ca_handler.py" >> data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> data/acme_srv.cfg - sudo echo "profile_id: 101" >> data/acme_srv.cfg - sudo sed -i "s/tnauthlist_support: False/tnauthlist_support: True/g" data/acme_srv.cfg - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "[ PREPARE ] Almalinux instance" - run: | - cat examples/Docker/almalinux-systemd/Dockerfile | docker build -t almalinux-systemd -f - . --no-cache - docker run -d -id --privileged --network acme -p 22280:80 --name=acme-srv -v "$(pwd)/data":/tmp/acme2certifier almalinux-systemd - - - name: "[ RUN ] Execute install scipt" - run: | - docker exec acme-srv sh /tmp/acme2certifier/rpm_tester.sh - - - name: "Test http://acme-srv/directory is accessible" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "[ CURL ] install curl and socat and test connction" - run: | - sudo apt-get install -y curl socat - curl -f http://localhost:22280 - - - name: "[ ACME.SH ] install acme.sh" - run: | - mkdir /tmp/acme_sh - curl -kL https://github.com/grindsa/acme.sh/archive/tnauth_list_support.tar.gz | tar xz -C /tmp/acme_sh --strip-components=1 - - - name: "[ ACME.SH ] enroll certificate using tnauth identifier" - run: | - cd /tmp/acme_sh - /tmp/acme_sh/acme.sh --server http://127.0.0.1:22280 --accountemail grindsa@tnauth.acme --issue -d cert.acme.local --tnauth 123456 --spctoken 1234 --standalone --force --debug 2 - - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - docker exec acme-srv tar cvfz /tmp/acme2certifier/a2c.tgz /opt/acme2certifier - sudo cp -rp data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp /tmp/acme_sh/ ${{ github.workspace }}/artifact/acme_sh/ - docker exec acme-srv cat /var/log/messages > ${{ github.workspace }}/artifact/acme-srv.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz data acme-srv.log acme_sh - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: tnauth-rpm.tar.gz - path: ${{ github.workspace }}/artifact/upload/ diff --git a/.github/workflows/traffic-application-test.yml b/.github/workflows/traffic-application-test.yml deleted file mode 100644 index c826b92f..00000000 --- a/.github/workflows/traffic-application-test.yml +++ /dev/null @@ -1,102 +0,0 @@ -name: Application Tests - traefik - -on: - push: - pull_request: - branches: [ devel ] - schedule: - # * is a special character in YAML so you have to quote this string - - cron: '0 2 * * 6' - -jobs: - - traefik_apache2_wsgi: - name: "traefik_apache2_wsgi" - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - challenge_type: [tlschallenge=true, httpchallenge.entrypoint=web] - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "get runner information" - run: | - echo RUNNER_IP=$(ip addr show eth0 | grep -i "inet " | cut -d ' ' -f 6 | cut -d '/' -f 1) >> $GITHUB_ENV - echo RUNNER_HOSTNAME=$(hostname -f) >> $GITHUB_ENV - - - run: echo "runner IP is ${{ env.RUNNER_IP }}" - - run: echo "runner hostname is ${{ env.RUNNER_HOSTNAME }}" - - - name: "Build docker-compose (apache2_wsgi)" - working-directory: examples/Docker/ - run: | - sudo mkdir -p data - docker network create acme - docker-compose up -d - docker-compose logs - - - name: "Test http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo cp test/ca/certsrv_ca_certs.pem examples/Docker/data/ca_certs.pem - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - cd examples/Docker/ - docker-compose restart - docker-compose logs - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "setup and instanciate traefik" - run: | - mkdir traefik - sudo cp .github/traefik-matrix.yml traefik/docker-compose.yml - sudo sed -i "s/whoami.acme/${{ env.RUNNER_HOSTNAME }}/g" traefik/docker-compose.yml - sudo sed -i "s/CHALLENGE_TYPE/${{ matrix.challenge_type }}/g" traefik/docker-compose.yml - cd traefik - docker-compose up -d - - - name: "Sleep for 30s" - uses: juliangruber/sleep-action@v1 - with: - time: 30s - - - name: "check for certificate" - working-directory: traefik - run: | - sudo cat letsencrypt/acme.json | jq -r '.a2c | .Certificates | . [] | .certificate ' | base64 -d | awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' - openssl verify -CAfile cert-3.pem -untrusted cert-2.pem cert-1.pem - - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - docker logs traefik > traefik/traefik.log - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp traefik/ ${{ github.workspace }}/artifact/traefik/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data traefik - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: traffic-${{ matrix.challenge_type }}.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - diff --git a/.github/workflows/upgrade_tests..yml b/.github/workflows/upgrade_tests..yml deleted file mode 100644 index 8975ace0..00000000 --- a/.github/workflows/upgrade_tests..yml +++ /dev/null @@ -1,1399 +0,0 @@ -name: Upgrade Tests - -on: - push: - pull_request: - branches: [ devel ] - schedule: - # * is a special character in YAML so you have to quote this string - - cron: '0 2 * * 6' - -jobs: - - wsgi_upgrade_apache2: - name: "wsgi_upgrade_apache2" - runs-on: ubuntu-latest - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "[ PREPARE ] prepare environment" - working-directory: examples/Docker/ - run: | - docker network create acme - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo mkdir -p examples/Docker/data - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - sudo cp .github/acme2certifier.pem examples/Docker/data/acme2certifier.pem - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "[ PREPARE ] install a2c 0.19.3" - run: | - docker run -d -p 80:80 -p 443:443 --rm -id --network acme --name=acme-srv -v "$(pwd)/examples/Docker/data":/var/www/acme2certifier/volume/ grindsa/acme2certifier:0.19.3-apache2-wsgi - docker logs acme-srv - - - name: "[ PREPARE ] Sleep for 5s" - uses: juliangruber/sleep-action@v1 - with: - time: 5s - - - name: "Test if http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "Test if https://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - sudo mkdir -p "$(pwd)/examples/Docker/data/acme-sh" - docker run --rm -id -v "$(pwd)/examples/Docker/data/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ ENROLL ] register via http" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --debug 2 - - - name: "[ ENROLL ] register via https" - run: | - docker exec -i acme-sh acme.sh --server https://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --insecure --debug 2 - - - name: "[ ENROLL] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --debug --output-insecure - - - name: "[ REGISTER] certbot" - run: | - sudo mkdir -p "$(pwd)/examples/Docker/data/certbot" - docker run -i --rm --name certbot --network acme -v "$(pwd)/examples/Docker/data/certbot":/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email - - - name: "[ ENROLL ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v "$(pwd)/examples/Docker/data/certbot":/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot - sudo chmod 777 examples/Docker/data/certbot/archive/certbot/chain1.pem - sudo cp examples/Docker/data/certbot/archive/certbot/chain1.pem chain1.pem - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < chain1.pem - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem examples/Docker/data/certbot/live/certbot/cert.pem - - - name: "[ PREPARE ] Upgrade to latest a2c build" - working-directory: examples/Docker/ - run: | - docker stop acme-srv - sudo chmod -R 777 data - docker-compose up -d - docker-compose logs - - - name: "[ PREPARE ] Sleep for 5s" - uses: juliangruber/sleep-action@v1 - with: - time: 5s - - - name: "Test if http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "Test if https://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory - - - name: "[ ENROLL ] register via http" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --debug 2 - - - name: "[ ENROLL ] register via https" - run: | - docker exec -i acme-sh acme.sh --server https://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --insecure --debug 2 - - - name: "[ ENROLL] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --debug --output-insecure - - - name: "[ REGISTER] certbot" - run: | - sudo mkdir -p "$(pwd)/examples/Docker/data/certbot2" - docker run -i --rm --name certbot --network acme -v "$(pwd)/examples/Docker/data/certbot2":/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email - - - name: "[ ENROLL ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v "$(pwd)/examples/Docker/data/certbot":/etc/letsencrypt/ certbot/certbot certonly --force-renew --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot - sudo chmod 777 examples/Docker/data/certbot/archive/certbot/chain1.pem - sudo cp examples/Docker/data/certbot/archive/certbot/chain1.pem chain1.pem - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < chain1.pem - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem examples/Docker/data/certbot/live/certbot/cert.pem - - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - docker logs acme2certifier_acme-srv_1 - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: apache2-wsgi-upgrade.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - - wsgi_upgrade_nginx: - name: "wsgi_upgrade_nginx" - runs-on: ubuntu-latest - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "[ PREPARE ] prepare environment" - working-directory: examples/Docker/ - run: | - docker network create acme - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo mkdir -p examples/Docker/data - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - sudo cp .github/acme2certifier_cert.pem examples/Docker/data/acme2certifier_cert.pem - sudo cp .github/acme2certifier_key.pem examples/Docker/data/acme2certifier_key.pem - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "[ PREPARE ] install a2c 0.19.3" - run: | - docker run -d -p 80:80 -p 443:443 --rm -id --network acme --name=acme-srv -v "$(pwd)/examples/Docker/data":/var/www/acme2certifier/volume/ grindsa/acme2certifier:0.19.3-nginx-wsgi - docker logs acme-srv - - - name: "[ PREPARE ] Sleep for 5s" - uses: juliangruber/sleep-action@v1 - with: - time: 5s - - - name: "Test if http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "Test if https://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - sudo mkdir -p "$(pwd)/examples/Docker/data/acme-sh" - docker run --rm -id -v "$(pwd)/examples/Docker/data/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ ENROLL ] register via http" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --debug 2 - - - name: "[ ENROLL ] register via https" - run: | - docker exec -i acme-sh acme.sh --server https://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --insecure --debug 2 - - - name: "[ ENROLL] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --debug --output-insecure - - - name: "[ REGISTER] certbot" - run: | - sudo mkdir -p "$(pwd)/examples/Docker/data/certbot" - docker run -i --rm --name certbot --network acme -v "$(pwd)/examples/Docker/data/certbot":/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email - - - name: "[ ENROLL ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v "$(pwd)/examples/Docker/data/certbot":/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot - sudo chmod 777 examples/Docker/data/certbot/archive/certbot/chain1.pem - sudo cp examples/Docker/data/certbot/archive/certbot/chain1.pem chain1.pem - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < chain1.pem - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem examples/Docker/data/certbot/live/certbot/cert.pem - - - name: "[ PREPARE ] Upgrade to latest a2c build" - working-directory: examples/Docker/ - run: | - docker stop acme-srv - sudo chmod -R 777 data - sed -i "s/apache2/nginx/g" .env - docker-compose up -d - docker-compose logs - - - name: "[ PREPARE ] Sleep for 5s" - uses: juliangruber/sleep-action@v1 - with: - time: 5s - - - name: "Test if http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "Test if https://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory - - - name: "[ ENROLL ] register via http" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --debug 2 - - - name: "[ ENROLL ] register via https" - run: | - docker exec -i acme-sh acme.sh --server https://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --insecure --debug 2 - - - name: "[ ENROLL] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --debug --output-insecure - - - name: "[ REGISTER] certbot" - run: | - sudo mkdir -p "$(pwd)/examples/Docker/data/certbot2" - docker run -i --rm --name certbot --network acme -v "$(pwd)/examples/Docker/data/certbot2":/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email - - - name: "[ ENROLL ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v "$(pwd)/examples/Docker/data/certbot":/etc/letsencrypt/ certbot/certbot certonly --force-renew --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot - sudo chmod 777 examples/Docker/data/certbot/archive/certbot/chain1.pem - sudo cp examples/Docker/data/certbot/archive/certbot/chain1.pem chain1.pem - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < chain1.pem - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem examples/Docker/data/certbot/live/certbot/cert.pem - - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - docker logs acme2certifier_acme-srv_1 - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: nginx-wsgi-upgrade.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - - - django_upgrade_apache2: - name: "django_upgrade_apache2" - runs-on: ubuntu-latest - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "[ PREPARE ] prepare environment" - working-directory: examples/Docker/ - run: | - docker network create acme - sudo mkdir -p data/mysql - - - name: "[ PREPARE ] install mariadb" - working-directory: examples/Docker/ - run: | - # docker run --name mariadbsrv --network acme -v $PWD/data/mysql:/var/lib/mysql -e MARIADB_ROOT_PASSWORD=foobar -d mariadb - docker run --name mariadbsrv --network acme -e MARIADB_ROOT_PASSWORD=foobar -d mariadb - - - name: "[ PREPARE ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "[ PREPARE ] configure mariadb" - working-directory: examples/Docker/ - run: | - docker exec mariadbsrv mariadb -u root --password=foobar -e"CREATE DATABASE acme2certifier CHARACTER SET UTF8;" - docker exec mariadbsrv mariadb -u root --password=foobar -e"GRANT ALL PRIVILEGES ON acme2certifier.* TO 'acme2certifier'@'%' IDENTIFIED BY '1mmSvDFl';" - docker exec mariadbsrv mariadb -u root --password=foobar -e"FLUSH PRIVILEGES;" - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo mkdir -p examples/Docker/data - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - sudo cp .github/django_settings_mariadb.py examples/Docker/data/settings.py - sudo chmod 777 examples/Docker/data/settings.py - sudo sed -i "s/ 'acme_srv'/ 'acme'/g" examples/Docker/data/settings.py - sudo cp .github/acme2certifier.pem examples/Docker/data/acme2certifier.pem - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "[ PREPARE ] install a2c 0.19.3" - run: | - docker run -d -p 80:80 -p 443:443 --rm -id --network acme --name=acme-srv -v "$(pwd)/examples/Docker/data":/var/www/acme2certifier/volume/ grindsa/acme2certifier:0.19.3-apache2-django - docker logs acme-srv - - - name: "[ PREPARE ] Sleep for 5s" - uses: juliangruber/sleep-action@v1 - with: - time: 5s - - - name: "Test if http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "Test if https://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - sudo mkdir -p "$(pwd)/examples/Docker/data/acme-sh" - docker run --rm -id -v "$(pwd)/examples/Docker/data/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ ENROLL ] register via http" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --debug 2 - - - name: "[ ENROLL ] register via https" - run: | - docker exec -i acme-sh acme.sh --server https://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --insecure --debug 2 - - - name: "[ ENROLL] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --debug --output-insecure - - - name: "[ REGISTER] certbot" - run: | - sudo mkdir -p "$(pwd)/examples/Docker/data/certbot" - docker run -i --rm --name certbot --network acme -v "$(pwd)/examples/Docker/data/certbot":/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email - - - name: "[ ENROLL ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v "$(pwd)/examples/Docker/data/certbot":/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot - sudo chmod 777 examples/Docker/data/certbot/archive/certbot/chain1.pem - sudo cp examples/Docker/data/certbot/archive/certbot/chain1.pem chain1.pem - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < chain1.pem - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem examples/Docker/data/certbot/live/certbot/cert.pem - - - name: "[ PREPARE ] Upgrade to latest a2c build" - working-directory: examples/Docker/ - run: | - docker stop acme-srv - sudo chmod -R 777 data - sed -i "s/wsgi/django/g" .env - docker-compose up -d - docker-compose logs - - - name: "[ PREPARE ] Sleep for 5s" - uses: juliangruber/sleep-action@v1 - with: - time: 5s - - - name: "Test if http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "Test if https://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory - - - name: "[ ENROLL ] register via http" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --debug 2 - - - name: "[ ENROLL ] register via https" - run: | - docker exec -i acme-sh acme.sh --server https://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --insecure --debug 2 - - - name: "[ ENROLL] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --debug --output-insecure - - - name: "[ REGISTER] certbot" - run: | - sudo mkdir -p "$(pwd)/examples/Docker/data/certbot2" - docker run -i --rm --name certbot --network acme -v "$(pwd)/examples/Docker/data/certbot2":/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email - - - name: "[ ENROLL ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v "$(pwd)/examples/Docker/data/certbot":/etc/letsencrypt/ certbot/certbot certonly --force-renew --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot - sudo chmod 777 examples/Docker/data/certbot/archive/certbot/chain1.pem - sudo cp examples/Docker/data/certbot/archive/certbot/chain1.pem chain1.pem - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < chain1.pem - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem examples/Docker/data/certbot/live/certbot/cert.pem - - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - docker logs acme2certifier_acme-srv_1 - docker exec mariadbsrv mysqldump -u root --password=foobar acme2certifier > /tmp/acme2certifer.sql - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - sudo cp /tmp/acme2certifer.sql ${{ github.workspace }}/artifact/data/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: apache2-django-upgrade.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - - django_upgrade_nginx: - name: "django_upgrade_nginx" - runs-on: ubuntu-latest - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "[ PREPARE ] prepare environment" - working-directory: examples/Docker/ - run: | - docker network create acme - sudo mkdir -p data/mysql - - - name: "[ PREPARE ] install mariadb" - working-directory: examples/Docker/ - run: | - # docker run --name mariadbsrv --network acme -v $PWD/data/mysql:/var/lib/mysql -e MARIADB_ROOT_PASSWORD=foobar -d mariadb - docker run --name mariadbsrv --network acme -e MARIADB_ROOT_PASSWORD=foobar -d mariadb - - - name: "[ PREPARE ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "[ PREPARE ] configure mariadb" - working-directory: examples/Docker/ - run: | - docker exec mariadbsrv mariadb -u root --password=foobar -e"CREATE DATABASE acme2certifier CHARACTER SET UTF8;" - docker exec mariadbsrv mariadb -u root --password=foobar -e"GRANT ALL PRIVILEGES ON acme2certifier.* TO 'acme2certifier'@'%' IDENTIFIED BY '1mmSvDFl';" - docker exec mariadbsrv mariadb -u root --password=foobar -e"FLUSH PRIVILEGES;" - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo mkdir -p examples/Docker/data - sudo touch examples/Docker/data/acme_srv.cfg - sudo chmod 777 examples/Docker/data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > examples/Docker/data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> examples/Docker/data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> examples/Docker/data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> examples/Docker/data/acme_srv.cfg - sudo cp .github/django_settings_mariadb.py examples/Docker/data/settings.py - sudo chmod 777 examples/Docker/data/settings.py - sudo sed -i "s/ 'acme_srv'/ 'acme'/g" examples/Docker/data/settings.py - sudo cp .github/acme2certifier_cert.pem examples/Docker/data/acme2certifier_cert.pem - sudo cp .github/acme2certifier_key.pem examples/Docker/data/acme2certifier_key.pem - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "[ PREPARE ] install a2c 0.19.3" - run: | - docker run -d -p 80:80 -p 443:443 --rm -id --network acme --name=acme-srv -v "$(pwd)/examples/Docker/data":/var/www/acme2certifier/volume/ grindsa/acme2certifier:0.19.3-nginx-django - docker logs acme-srv - - - name: "[ PREPARE ] Sleep for 5s" - uses: juliangruber/sleep-action@v1 - with: - time: 5s - - - name: "Test if http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "Test if https://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - sudo mkdir -p "$(pwd)/examples/Docker/data/acme-sh" - docker run --rm -id -v "$(pwd)/examples/Docker/data/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ ENROLL ] register via http" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --debug 2 - - - name: "[ ENROLL ] register via https" - run: | - docker exec -i acme-sh acme.sh --server https://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --insecure --debug 2 - - - name: "[ ENROLL] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --debug --output-insecure - - - name: "[ REGISTER] certbot" - run: | - sudo mkdir -p "$(pwd)/examples/Docker/data/certbot" - docker run -i --rm --name certbot --network acme -v "$(pwd)/examples/Docker/data/certbot":/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email - - - name: "[ ENROLL ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v "$(pwd)/examples/Docker/data/certbot":/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot - sudo chmod 777 examples/Docker/data/certbot/archive/certbot/chain1.pem - sudo cp examples/Docker/data/certbot/archive/certbot/chain1.pem chain1.pem - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < chain1.pem - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem examples/Docker/data/certbot/live/certbot/cert.pem - - - name: "[ PREPARE ] Upgrade to latest a2c build" - working-directory: examples/Docker/ - run: | - docker stop acme-srv - sudo chmod -R 777 data - sed -i "s/wsgi/django/g" .env - sed -i "s/apache2/nginx/g" .env - docker-compose up -d - docker-compose logs - - - name: "[ PREPARE ] Sleep for 5s" - uses: juliangruber/sleep-action@v1 - with: - time: 5s - - - name: "Test if http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "Test if https://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory - - - name: "[ ENROLL ] register via http" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --debug 2 - - - name: "[ ENROLL ] register via https" - run: | - docker exec -i acme-sh acme.sh --server https://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --insecure --debug 2 - - - name: "[ ENROLL] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --debug --output-insecure - - - name: "[ REGISTER] certbot" - run: | - sudo mkdir -p "$(pwd)/examples/Docker/data/certbot2" - docker run -i --rm --name certbot --network acme -v "$(pwd)/examples/Docker/data/certbot2":/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email - - - name: "[ ENROLL ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v "$(pwd)/examples/Docker/data/certbot":/etc/letsencrypt/ certbot/certbot certonly --force-renew --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot - sudo chmod 777 examples/Docker/data/certbot/archive/certbot/chain1.pem - sudo cp examples/Docker/data/certbot/archive/certbot/chain1.pem chain1.pem - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < chain1.pem - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem examples/Docker/data/certbot/live/certbot/cert.pem - - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - docker logs acme2certifier_acme-srv_1 - docker exec mariadbsrv mysqldump -u root --password=foobar acme2certifier > /tmp/acme2certifer.sql - mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - sudo cp /tmp/acme2certifer.sql ${{ github.workspace }}/artifact/data/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: nginx-django-upgrade.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - - rpm_wsgi_upgrade_nginx: - name: "rpm_wsgi_upgrade_nginx" - runs-on: ubuntu-latest - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: Retrieve Version from version.py - run: | - echo TAG_NAME=$(cat acme_srv/version.py | grep -i __version__ | head -n 1 | sed 's/__version__ = //g' | sed s/\'//g) >> $GITHUB_ENV - - run: echo "Latest tag is ${{ env.TAG_NAME }}" - - - name: update version number in spec file and path in nginx ssl config - run: | - sudo sed -i "s/__version__/${{ env.TAG_NAME }}/g" examples/install_scripts/rpm/acme2certifier.spec - sudo sed -i "s/\/var\/www\/acme2certifier\/volume/\/etc\/nginx/g" examples/nginx/nginx_acme_srv_ssl.conf - git config --global user.email "grindelsack@gmail.com" - git config --global user.name "rpm update" - git add examples/nginx - git commit -a -m "rpm update" - - - name: build RPM package - id: rpm - uses: grindsa/rpmbuild@alma9 - with: - spec_file: "examples/install_scripts/rpm/acme2certifier.spec" - - - run: echo "path is ${{ steps.rpm.outputs.rpm_dir_path }}" - - - name: "[ PREPARE ] setup environment for alma installation" - run: | - docker network create acme - sudo mkdir -p data/volume - sudo mkdir -p data/acme2certifier - sudo mkdir -p data/nginx/conf.d - sudo chmod -R 777 data - sudo cp examples/Docker/almalinux-systemd/rpm_tester.sh data - wget -P data/ https://github.com/grindsa/acme2certifier/releases/download/0.23.2/acme2certifier-0.23.2-1.0.noarch.rpm - sudo cp examples/Docker/almalinux-systemd/rpm_tester.sh data - sudo cp .github/acme2certifier_cert.pem data/nginx/acme2certifier_cert.pem - sudo cp .github/acme2certifier_key.pem data/nginx/acme2certifier_key.pem - sudo cp examples/nginx/nginx_acme_srv_ssl.conf data/nginx/conf.d - sudo sed -i "s/\/var\/www\/acme2certifier\/volume/\/etc\/nginx/g" data/nginx/conf.d/nginx_acme_srv_ssl.conf - - - name: "Retrieve rpms from SBOM repo" - run: | - git clone https://$GH_SBOM_USER:$GH_SBOM_TOKEN@github.com/$GH_SBOM_USER/sbom /tmp/sbom - cp /tmp/sbom/rpm-repo/RPMs/*.rpm data - env: - GH_SBOM_USER: ${{ secrets.GH_SBOM_USER }} - GH_SBOM_TOKEN: ${{ secrets.GH_SBOM_TOKEN }} - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - sudo mkdir acme-sh - mkdir -p data/acme_ca - sudo cp test/ca/certsrv_ca_certs.pem data/acme_ca/ca_certs.pem - sudo touch data/acme_srv.cfg - sudo chmod 777 data/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> data/acme_srv.cfg - sudo echo "profile_id: 101" >> data/acme_srv.cfg - sudo sed -i "s/examples\/ca_handler/\/opt\/acme2certifier\/examples\/ca_handler/g" data/acme_srv.cfg - sudo sed -i "s/volume\/acme_ca/\/opt\/acme2certifier\/volume\/acme_ca/g" data/acme_srv.cfg - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "[ PREPARE ] Almalinux instance" - run: | - cat examples/Docker/almalinux-systemd/Dockerfile | docker build -t almalinux-systemd -f - . --no-cache - docker run -d -id --privileged --network acme -p 22280:80 --name=acme-srv -v "$(pwd)/data":/tmp/acme2certifier almalinux-systemd - - - name: "[ RUN ] Execute install scipt" - run: | - docker exec acme-srv sh /tmp/acme2certifier/rpm_tester.sh - sudo docker cp data/nginx acme-srv:/etc - sudo docker cp data/volume/ acme-srv:/opt/acme2certifier/ - docker exec acme-srv chmod -R 777 /opt/acme2certifier/volume - - - name: "Test http://acme-srv/directory is accessible" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "[ CURL ] install curl and socat and test connction" - run: | - sudo apt-get install -y curl socat - curl -f http://localhost:22280 - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ ENROLL ] register via http" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --debug 2 - - - name: "[ ENROLL] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --alpn --standalone --debug 3 --insecure --output-insecure --force - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - - name: "[ REGISTER] certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email - - - name: "[ ENROLL ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot - sudo chmod 777 certbot/archive/certbot/chain1.pem - sudo cp certbot/archive/certbot/chain1.pem chain1.pem - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < chain1.pem - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem - - - name: "Update acme2certifier" - run: | - docker cp ${{ steps.rpm.outputs.rpm_dir_path }}noarch/acme2certifier-${{ env.TAG_NAME }}-1.0.noarch.rpm acme-srv:/tmp - # docker exec acme-srv rpm -Uvh /tmp/acme2certifier-${{ env.TAG_NAME }}-1.0.noarch.rpm - docker exec acme-srv yum -y localinstall /tmp/acme2certifier-${{ env.TAG_NAME }}-1.0.noarch.rpm - docker cp data/acme_srv.cfg acme-srv:/opt/acme2certifier/acme_srv - docker exec -w /opt/acme2certifier acme-srv python3 tools/db_update.py - docker restart acme-srv - docker stop acme-sh - sudo rm -rf $PWD/certbot/* - sudo rm -rf $PWD/acme-sh/* - - - name: "[ PREPARE ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "Test http://acme-srv/directory is accessible" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ ENROLL ] register via http" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --debug 2 - - - name: "[ ENROLL] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --alpn --standalone --debug 3 --insecure --output-insecure --force - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - - name: "[ REGISTER] certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email - - - name: "[ ENROLL ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem - - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - docker exec acme-srv tar cvfz /tmp/acme2certifier/a2c.tgz /opt/acme2certifier - docker exec acme-srv tar cvfz /tmp/acme2certifier/nginx.tgz /etc/nginx - sudo cp -rp data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp acme-sh/ ${{ github.workspace }}/artifact/acme-sh/ - docker exec acme-srv cat /var/log/messages > ${{ github.workspace }}/artifact/acme-srv.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz data acme-srv.log acme-sh - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: rpm_wsgi_upgrade_nginx.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - - rpm_django_upgrade_nginx_mariadb: - name: "rpm_django_upgrade_nginx_mariadb" - runs-on: ubuntu-latest - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: Retrieve Version from version.py - run: | - echo TAG_NAME=$(cat acme_srv/version.py | grep -i __version__ | head -n 1 | sed 's/__version__ = //g' | sed s/\'//g) >> $GITHUB_ENV - - run: echo "Latest tag is ${{ env.TAG_NAME }}" - - - name: update version number in spec file and path in nginx ssl config - run: | - sudo sed -i "s/__version__/${{ env.TAG_NAME }}/g" examples/install_scripts/rpm/acme2certifier.spec - sudo sed -i "s/\/var\/www\/acme2certifier\/volume/\/etc\/nginx/g" examples/nginx/nginx_acme_srv_ssl.conf - git config --global user.email "grindelsack@gmail.com" - git config --global user.name "rpm update" - git add examples/nginx - git commit -a -m "rpm update" - - - name: build RPM package - id: rpm - uses: grindsa/rpmbuild@alma9 - with: - spec_file: "examples/install_scripts/rpm/acme2certifier.spec" - - - run: echo "path is ${{ steps.rpm.outputs.rpm_dir_path }}" - - - name: "[ PREPARE ] setup environment for alma installation" - run: | - sudo mkdir acme-sh - docker network create acme - sudo mkdir -p data/volume - sudo mkdir -p data/acme2certifier - sudo mkdir -p data/nginx/conf.d - sudo chmod -R 777 data - wget -P data/ https://github.com/grindsa/acme2certifier/releases/download/0.23.2/acme2certifier-0.23.2-1.0.noarch.rpm - sudo cp examples/Docker/almalinux-systemd/rpm_tester.sh data - sudo cp examples/Docker/almalinux-systemd/django_tester.sh data - sudo cp .github/acme2certifier_cert.pem data/nginx/acme2certifier_cert.pem - sudo cp .github/acme2certifier_key.pem data/nginx/acme2certifier_key.pem - sudo cp .github/django_settings_mariadb.py data/acme2certifier/settings.py - # sudo sed -i "s/\/var\/www\//\/opt\//g" data/acme2certifier/settings.py - sudo sed -i "s/USE_I18N = True/USE_I18N = False/g" data/acme2certifier/settings.py - sudo cp examples/nginx/nginx_acme_srv_ssl.conf data/nginx/conf.d - sudo sed -i "s/\/var\/www\/acme2certifier\/volume/\/etc\/nginx/g" data/nginx/conf.d/nginx_acme_srv_ssl.conf - - - name: "[ PREPARE ] install mariadb" - working-directory: examples/Docker/ - run: | - # docker run --name mariadbsrv --network acme -v $PWD/data/mysql:/var/lib/mysql -e MARIADB_ROOT_PASSWORD=foobar -d mariadb - docker run --name mariadbsrv --network acme -e MARIADB_ROOT_PASSWORD=foobar -d mariadb - - - name: "[ PREPARE ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "[ PREPARE ] configure mariadb" - working-directory: examples/Docker/ - run: | - docker exec mariadbsrv mariadb -u root --password=foobar -e"CREATE DATABASE acme2certifier CHARACTER SET UTF8;" - docker exec mariadbsrv mariadb -u root --password=foobar -e"GRANT ALL PRIVILEGES ON acme2certifier.* TO 'acme2certifier'@'%' IDENTIFIED BY '1mmSvDFl';" - docker exec mariadbsrv mariadb -u root --password=foobar -e"FLUSH PRIVILEGES;" - - - name: "Retrieve rpms from SBOM repo" - run: | - git clone https://$GH_SBOM_USER:$GH_SBOM_TOKEN@github.com/$GH_SBOM_USER/sbom /tmp/sbom - cp /tmp/sbom/rpm-repo/RPMs/*.rpm data - env: - GH_SBOM_USER: ${{ secrets.GH_SBOM_USER }} - GH_SBOM_TOKEN: ${{ secrets.GH_SBOM_TOKEN }} - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - mkdir -p data/acme_ca - sudo cp test/ca/certsrv_ca_certs.pem data/acme_ca/ca_certs.pem - sudo touch data/volume/acme_srv.cfg - sudo chmod 777 data/volume/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > data/volume/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> data/volume/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> data/volume/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> data/volume/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> data/volume/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> data/volume/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> data/volume/acme_srv.cfg - sudo echo "profile_id: 101" >> data/volume/acme_srv.cfg - # sudo sed -i "s/examples\/ca_handler/\/opt\/acme2certifier\/examples\/ca_handler/g" data/volume/acme_srv.cfg - # sudo sed -i "s/volume\/acme_ca/\/opt\/acme2certifier\/volume\/acme_ca/g" data/volume/acme_srv.cfg - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "[ PREPARE ] Almalinux instance" - run: | - cat examples/Docker/almalinux-systemd/Dockerfile | docker build -t almalinux-systemd -f - . --no-cache - docker run -d -id --privileged --network acme -p 22280:80 --name=acme-srv -v "$(pwd)/data":/tmp/acme2certifier almalinux-systemd - - - name: "[ RUN ] Execute install scipt" - run: | - docker exec acme-srv sh /tmp/acme2certifier/django_tester.sh - - - name: "Test http://acme-srv/directory is accessible" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "Test if https://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory - - - name: "[ CURL ] install curl and socat and test connction" - run: | - sudo apt-get install -y curl socat - curl -f http://localhost:22280 - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ ENROLL ] register via http" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --debug 2 - - - name: "[ ENROLL] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --alpn --standalone --debug 3 --insecure --output-insecure --force - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - - name: "[ REGISTER] certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email - - - name: "[ ENROLL ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem - - - name: "Update acme2certifier" - run: | - docker cp ${{ steps.rpm.outputs.rpm_dir_path }}noarch/acme2certifier-${{ env.TAG_NAME }}-1.0.noarch.rpm acme-srv:/tmp - # docker exec acme-srv rpm -Uvh /tmp/acme2certifier-${{ env.TAG_NAME }}-1.0.noarch.rpm - docker exec acme-srv yum -y localinstall /tmp/acme2certifier-${{ env.TAG_NAME }}-1.0.noarch.rpm - docker cp data/volume/acme_srv.cfg acme-srv:/opt/acme2certifier/acme_srv - docker exec -w /opt/acme2certifier acme-srv cp examples/django/acme_srv/*.py acme_srv/ - docker exec -w /opt/acme2certifier acme-srv python3 tools/django_update.py - docker restart acme-srv - docker stop acme-sh - sudo rm -rf $PWD/certbot/* - sudo rm -rf $PWD/acme-sh/* - - - name: "[ PREPARE ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "Test http://acme-srv/directory is accessible" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ ENROLL ] register via http" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --debug 2 - - - name: "[ ENROLL] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --alpn --standalone --debug 3 --insecure --output-insecure --force - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - - name: "[ REGISTER] certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email - - - name: "[ ENROLL ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem - - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - docker exec acme-srv tar cvfz /tmp/acme2certifier/a2c.tgz /opt/acme2certifier - docker exec acme-srv tar cvfz /tmp/acme2certifier/nginx.tgz /etc/nginx - sudo cp -rp data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp acme-sh/ ${{ github.workspace }}/artifact/acme-sh/ - sudo cp -rp certbot/ ${{ github.workspace }}/artifact/certbot/ - docker exec acme-srv cat /var/log/messages > ${{ github.workspace }}/artifact/acme-srv.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz data acme-srv.log acme-sh certbot - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: rpm_django_upgrade_nginx_mariadb.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - - rpm_django_upgrade_nginx_sqlite: - name: "rpm_django_upgrade_nginx_sqlite" - runs-on: ubuntu-latest - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: Retrieve Version from version.py - run: | - echo TAG_NAME=$(cat acme_srv/version.py | grep -i __version__ | head -n 1 | sed 's/__version__ = //g' | sed s/\'//g) >> $GITHUB_ENV - - run: echo "Latest tag is ${{ env.TAG_NAME }}" - - - name: update version number in spec file and path in nginx ssl config - run: | - sudo sed -i "s/__version__/${{ env.TAG_NAME }}/g" examples/install_scripts/rpm/acme2certifier.spec - sudo sed -i "s/\/var\/www\/acme2certifier\/volume/\/etc\/nginx/g" examples/nginx/nginx_acme_srv_ssl.conf - git config --global user.email "grindelsack@gmail.com" - git config --global user.name "rpm update" - git add examples/nginx - git commit -a -m "rpm update" - - - name: build RPM package - id: rpm - uses: grindsa/rpmbuild@alma9 - with: - spec_file: "examples/install_scripts/rpm/acme2certifier.spec" - - - run: echo "path is ${{ steps.rpm.outputs.rpm_dir_path }}" - - - name: "[ PREPARE ] setup environment for alma installation" - run: | - sudo mkdir acme-sh - docker network create acme - sudo mkdir -p data/volume - sudo mkdir -p data/acme2certifier - sudo mkdir -p data/nginx/conf.d - sudo chmod -R 777 data - wget -P data/ https://github.com/grindsa/acme2certifier/releases/download/0.23.2/acme2certifier-0.23.2-1.0.noarch.rpm - sudo cp examples/Docker/almalinux-systemd/rpm_tester.sh data - sudo cp examples/Docker/almalinux-systemd/django_tester.sh data - sudo cp .github/acme2certifier_cert.pem data/nginx/acme2certifier_cert.pem - sudo cp .github/acme2certifier_key.pem data/nginx/acme2certifier_key.pem - sudo cp .github/django_settings.py data/acme2certifier/settings.py - sudo sed -i "s/\/var\/www\//\/opt\//g" data/acme2certifier/settings.py - sudo sed -i "s/USE_I18N = True/USE_I18N = False/g" data/acme2certifier/settings.py - sudo cp examples/nginx/nginx_acme_srv_ssl.conf data/nginx/conf.d - sudo sed -i "s/\/var\/www\/acme2certifier\/volume/\/etc\/nginx/g" data/nginx/conf.d/nginx_acme_srv_ssl.conf - - - name: "Retrieve rpms from SBOM repo" - run: | - git clone https://$GH_SBOM_USER:$GH_SBOM_TOKEN@github.com/$GH_SBOM_USER/sbom /tmp/sbom - cp /tmp/sbom/rpm-repo/RPMs/*.rpm data - env: - GH_SBOM_USER: ${{ secrets.GH_SBOM_USER }} - GH_SBOM_TOKEN: ${{ secrets.GH_SBOM_TOKEN }} - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - mkdir -p data/acme_ca - sudo cp test/ca/certsrv_ca_certs.pem data/acme_ca/ca_certs.pem - sudo touch data/volume/acme_srv.cfg - sudo chmod 777 data/volume/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > data/volume/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> data/volume/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> data/volume/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> data/volume/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> data/volume/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> data/volume/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> data/volume/acme_srv.cfg - sudo echo "profile_id: 101" >> data/volume/acme_srv.cfg - # sudo sed -i "s/examples\/ca_handler/\/opt\/acme2certifier\/examples\/ca_handler/g" data/volume/acme_srv.cfg - # sudo sed -i "s/volume\/acme_ca/\/opt\/acme2certifier\/volume\/acme_ca/g" data/volume/acme_srv.cfg - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "[ PREPARE ] Almalinux instance" - run: | - cat examples/Docker/almalinux-systemd/Dockerfile | docker build -t almalinux-systemd -f - . --no-cache - docker run -d -id --privileged --network acme -p 22280:80 --name=acme-srv -v "$(pwd)/data":/tmp/acme2certifier almalinux-systemd - - - name: "[ RUN ] Execute install scipt" - run: | - docker exec acme-srv sh /tmp/acme2certifier/django_tester.sh - - - name: "Test http://acme-srv/directory is accessible" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "Test if https://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory - - - name: "[ CURL ] install curl and socat and test connction" - run: | - sudo apt-get install -y curl socat - curl -f http://localhost:22280 - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ ENROLL ] register via http" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --debug 2 - - - name: "[ ENROLL] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --alpn --standalone --debug 3 --insecure --output-insecure --force - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - - name: "[ REGISTER] certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email - - - name: "[ ENROLL ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem - - - name: "Update acme2certifier" - run: | - docker cp ${{ steps.rpm.outputs.rpm_dir_path }}noarch/acme2certifier-${{ env.TAG_NAME }}-1.0.noarch.rpm acme-srv:/tmp - # docker exec acme-srv rpm -Uvh /tmp/acme2certifier-${{ env.TAG_NAME }}-1.0.noarch.rpm - docker exec acme-srv yum -y localinstall /tmp/acme2certifier-${{ env.TAG_NAME }}-1.0.noarch.rpm - docker cp data/volume/acme_srv.cfg acme-srv:/opt/acme2certifier/acme_srv - docker exec -w /opt/acme2certifier acme-srv cp examples/django/acme_srv/*.py acme_srv/ - docker exec -w /opt/acme2certifier acme-srv python3 tools/django_update.py - docker restart acme-srv - docker stop acme-sh - sudo rm -rf $PWD/certbot/* - sudo rm -rf $PWD/acme-sh/* - - - name: "[ PREPARE ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "Test http://acme-srv/directory is accessible" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ ENROLL ] register via http" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --debug 2 - - - name: "[ ENROLL] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --alpn --standalone --debug 3 --insecure --output-insecure --force - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - - name: "[ REGISTER] certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email - - - name: "[ ENROLL ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem - - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - docker exec acme-srv tar cvfz /tmp/acme2certifier/a2c.tgz /opt/acme2certifier - docker exec acme-srv tar cvfz /tmp/acme2certifier/nginx.tgz /etc/nginx - sudo cp -rp data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp acme-sh/ ${{ github.workspace }}/artifact/acme-sh/ - sudo cp -rp certbot/ ${{ github.workspace }}/artifact/certbot/ - docker exec acme-srv cat /var/log/messages > ${{ github.workspace }}/artifact/acme-srv.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz data acme-srv.log acme-sh certbot - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: rpm_django_upgrade_nginx_sqlite.tar.gz - path: ${{ github.workspace }}/artifact/upload/ - - rpm_django_upgrade_nginx_psql: - name: "rpm_django_upgrade_nginx_psql" - runs-on: ubuntu-latest - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: Retrieve Version from version.py - run: | - echo TAG_NAME=$(cat acme_srv/version.py | grep -i __version__ | head -n 1 | sed 's/__version__ = //g' | sed s/\'//g) >> $GITHUB_ENV - - run: echo "Latest tag is ${{ env.TAG_NAME }}" - - - name: update version number in spec file and path in nginx ssl config - run: | - sudo sed -i "s/__version__/${{ env.TAG_NAME }}/g" examples/install_scripts/rpm/acme2certifier.spec - sudo sed -i "s/\/var\/www\/acme2certifier\/volume/\/etc\/nginx/g" examples/nginx/nginx_acme_srv_ssl.conf - git config --global user.email "grindelsack@gmail.com" - git config --global user.name "rpm update" - git add examples/nginx - git commit -a -m "rpm update" - - - name: build RPM package - id: rpm - uses: grindsa/rpmbuild@alma9 - with: - spec_file: "examples/install_scripts/rpm/acme2certifier.spec" - - - run: echo "path is ${{ steps.rpm.outputs.rpm_dir_path }}" - - - name: "[ PREPARE ] setup environment for alma installation" - run: | - docker network create acme - sudo mkdir -p data/volume - sudo mkdir -p data/acme2certifier - sudo mkdir -p data/nginx/conf.d - sudo chmod -R 777 data - wget -P data/ https://github.com/grindsa/acme2certifier/releases/download/0.23.2/acme2certifier-0.23.2-1.0.noarch.rpm - sudo cp examples/Docker/almalinux-systemd/rpm_tester.sh data - sudo cp examples/Docker/almalinux-systemd/django_tester.sh data - sudo cp .github/acme2certifier_cert.pem data/nginx/acme2certifier_cert.pem - sudo cp .github/acme2certifier_key.pem data/nginx/acme2certifier_key.pem - sudo cp .github/django_settings_psql.py data/acme2certifier/settings.py - # sudo sed -i "s/\/var\/www\//\/opt\//g" data/acme2certifier/settings.py - sudo sed -i "s/USE_I18N = True/USE_I18N = False/g" data/acme2certifier/settings.py - sudo cp examples/nginx/nginx_acme_srv_ssl.conf data/nginx/conf.d - sudo sed -i "s/\/var\/www\/acme2certifier\/volume/\/etc\/nginx/g" data/nginx/conf.d/nginx_acme_srv_ssl.conf - - - name: "[ PREPARE ] postgres environment" - run: | - sudo mkdir -p /tmp/data/pgsql - sudo cp .github/a2c.psql /tmp/data/pgsql/a2c.psql - sudo cp .github/pgpass /tmp//data/pgsql/pgpass - sudo chmod 600 /tmp/data/pgsql/pgpass - - - name: "[ PREPARE ] install postgres" - working-directory: /tmp - run: | - docker run --name postgresdbsrv --network acme -e POSTGRES_PASSWORD=foobar -d postgres - - - name: "[ PREPARE ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "[ PREPARE ] configure postgres" - working-directory: /tmp - run: | - docker run -v "$(pwd)/data/pgsql/a2c.psql":/tmp/a2c.psql -v "$(pwd)/data/pgsql/pgpass:/root/.pgpass" --rm --network acme postgres psql -U postgres -h postgresdbsrv -f /tmp/a2c.psql - - - name: "[ PREPARE ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "Retrieve rpms from SBOM repo" - run: | - git clone https://$GH_SBOM_USER:$GH_SBOM_TOKEN@github.com/$GH_SBOM_USER/sbom /tmp/sbom - cp /tmp/sbom/rpm-repo/RPMs/*.rpm data - env: - GH_SBOM_USER: ${{ secrets.GH_SBOM_USER }} - GH_SBOM_TOKEN: ${{ secrets.GH_SBOM_TOKEN }} - - - name: "[ PREPARE ] setup a2c with certifier_ca_handler" - run: | - mkdir -p data/acme_ca - sudo cp test/ca/certsrv_ca_certs.pem data/acme_ca/ca_certs.pem - sudo touch data/volume/acme_srv.cfg - sudo chmod 777 data/volume/acme_srv.cfg - sudo head -n -8 .github/openssl_ca_handler.py_acme_srv_default_handler.cfg > data/volume/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> data/volume/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> data/volume/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> data/volume/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> data/volume/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> data/volume/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> data/volume/acme_srv.cfg - sudo echo "profile_id: 101" >> data/volume/acme_srv.cfg - # sudo sed -i "s/examples\/ca_handler/\/opt\/acme2certifier\/examples\/ca_handler/g" data/volume/acme_srv.cfg - # sudo sed -i "s/volume\/acme_ca/\/opt\/acme2certifier\/volume\/acme_ca/g" data/volume/acme_srv.cfg - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "[ PREPARE ] Almalinux instance" - run: | - cat examples/Docker/almalinux-systemd/Dockerfile | docker build -t almalinux-systemd -f - . --no-cache - docker run -d -id --privileged --network acme -p 22280:80 --name=acme-srv -v "$(pwd)/data":/tmp/acme2certifier almalinux-systemd - - - name: "[ RUN ] Execute install scipt" - run: | - docker exec acme-srv sh /tmp/acme2certifier/django_tester.sh - - - name: "Test http://acme-srv/directory is accessible" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "Test if https://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl --insecure -f https://acme-srv/directory - - - name: "[ CURL ] install curl and socat and test connction" - run: | - sudo apt-get install -y curl socat - curl -f http://localhost:22280 - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ ENROLL ] register via http" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --debug 2 - - - name: "[ ENROLL] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --alpn --standalone --debug 3 --insecure --output-insecure --force - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - - name: "[ REGISTER] certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email - - - name: "[ ENROLL ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem - - - name: "Update acme2certifier" - run: | - docker cp ${{ steps.rpm.outputs.rpm_dir_path }}noarch/acme2certifier-${{ env.TAG_NAME }}-1.0.noarch.rpm acme-srv:/tmp/acme2certifier - # docker exec acme-srv rpm -Uvh /tmp/acme2certifier/acme2certifier-${{ env.TAG_NAME }}-1.0.noarch.rpm - docker exec acme-srv yum -y localinstall /tmp/acme2certifier/acme2certifier-${{ env.TAG_NAME }}-1.0.noarch.rpm - docker cp data/volume/acme_srv.cfg acme-srv:/opt/acme2certifier/acme_srv - docker exec -w /opt/acme2certifier acme-srv cp examples/django/acme_srv/*.py acme_srv/ - docker exec -w /opt/acme2certifier acme-srv python3 tools/django_update.py - docker restart acme-srv - docker stop acme-sh - sudo rm -rf $PWD/certbot/* - sudo rm -rf $PWD/acme-sh/* - - - name: "[ PREPARE ] Sleep for 10s" - uses: juliangruber/sleep-action@v1 - with: - time: 10s - - - name: "Test http://acme-srv/directory is accessible" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon - - - name: "[ ENROLL ] register via http" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --register-account --accountemail 'acme-sh@example.com' --accountkeylength ec-256 --debug 2 - - - name: "[ ENROLL] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --alpn --standalone --debug 3 --insecure --output-insecure --force - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - - name: "[ REGISTER] certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot register --agree-tos -m 'certbot@example.com' --server http://acme-srv --no-eff-email - - - name: "[ ENROLL ] HTTP-01 single domain certbot" - run: | - docker run -i --rm --name certbot --network acme -v $PWD/certbot:/etc/letsencrypt/ certbot/certbot certonly --server http://acme-srv --standalone --preferred-challenges http -d certbot.acme --cert-name certbot - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem certbot/live/certbot/cert.pem - - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - mkdir -p ${{ github.workspace }}/artifact/upload - docker exec acme-srv tar cvfz /tmp/acme2certifier/a2c.tgz /opt/acme2certifier - docker exec acme-srv tar cvfz /tmp/acme2certifier/nginx.tgz /etc/nginx - sudo cp -rp data/ ${{ github.workspace }}/artifact/data/ - sudo cp -rp acme-sh/ ${{ github.workspace }}/artifact/acme-sh/ - sudo cp -rp certbot/ ${{ github.workspace }}/artifact/certbot/ - docker exec acme-srv cat /var/log/messages > ${{ github.workspace }}/artifact/acme-srv.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz data acme-srv.log acme-sh certbot - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: rpm_django_upgrade_nginx_psql.tar.gz - path: ${{ github.workspace }}/artifact/upload/ \ No newline at end of file diff --git a/.github/workflows/winacme-application-test.yml b/.github/workflows/winacme-application-test.yml deleted file mode 100644 index 28c5862d..00000000 --- a/.github/workflows/winacme-application-test.yml +++ /dev/null @@ -1,165 +0,0 @@ -name: Application Tests - win-acme - -on: - push: - pull_request: - branches: [ devel ] - schedule: - # * is a special character in YAML so you have to quote this string - - cron: '0 2 * * 6' - -jobs: - - win_acme: - name: "win_acme" - runs-on: windows-latest - - steps: - - name: "checkout GIT" - uses: actions/checkout@v3 - - - name: "[ PREPARE ] get RunnerIP" - run: | - Get-NetIPAddress -AddressFamily IPv4 - # $runner_ip=(Get-NetIPAddress -AddressFamily IPv4 -InterfaceAlias 'Ethernet').IPAddress - $runner_ip=(Get-NetIPAddress -AddressFamily IPv4 -InterfaceAlias 'vEthernet (nat)').IPAddress - echo RUNNER_IP=$runner_ip >> $env:GITHUB_ENV - - - name: "[ PREPARE ] echo RunnerIP" - run: echo $env:RUNNER_IP - - - name: "[ PREPARE ] Create DNS entries " - run: | - Invoke-RestMethod -ContentType "application/json" -Method PUT -Uri ${{ secrets.CF_DYNAMOP_URL }} -Headers @{Authorization="Bearer ${{ secrets.CF_TOKEN }}"} -UseBasicParsing -Body '{"type":"A","name":"${{ secrets.CF_WINACME1_NAME }}","content":"${{ env.RUNNER_IP }}","ttl":120,"proxied":false}' - - - name: "[ PREPARE ] Build local acme2certifier environment" - run: | - python -m pip install --upgrade pip - pip install -r requirements.txt - pip install django==3.2 - pip install django-sslserver - pip install pyyaml - cp examples/db_handler/django_handler.py acme_srv/db_handler.py - cp examples/django/* .\ -Recurse -Force - (Get-Content .github/django_settings.py) -replace '/var/www/acme2certifier/volume/db.sqlite3', 'volume/db.sqlite3' | Set-Content acme2certifier/settings.py - (Get-Content acme2certifier/settings.py) -replace 'django.contrib.staticfiles', 'sslserver' | Set-Content acme2certifier/settings.py - cat acme2certifier/settings.py - cp examples/ca_handler/certifier_ca_handler.py acme2certifier/ca_handler.py - # cp .github/openssl_ca_handler.py_acme_srv_choosen_handler.cfg acme_srv/acme_srv.cfg - gc -head 21 .github/openssl_ca_handler.py_acme_srv_choosen_handler.cfg > acme_srv/acme_srv.cfg - echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> acme_srv/acme_srv.cfg - echo "api_host: $env:NCM_API_HOST" >> acme_srv/acme_srv.cfg - echo "api_user: $env:NCM_API_USER" >> acme_srv/acme_srv.cfg - echo "api_password: $env:NCM_API_PASSWORD" >> acme_srv/acme_srv.cfg - echo "ca_name: $env:NCM_CA_NAME" >> acme_srv/acme_srv.cfg - echo "ca_bundle: $env:NCM_CA_BUNDLE" >> acme_srv/acme_srv.cfg - cp .github/acme2certifier_cert.pem acme2certifier/acme2certifier_cert.pem - cp .github/acme2certifier_key.pem acme2certifier/acme2certifier_key.pem - mkdir .\volume/acme_ca/certs - cp test/ca/*.pem volume/acme_ca/ - certutil -addstore -enterprise -f -v root volume\acme_ca\root-ca-cert.pem - certutil -addstore -enterprise -f -v root volume\acme_ca\sub-ca-cert.pem - env: - NCM_API_HOST: ${{ secrets.NCM_API_HOST }} - NCM_API_USER: ${{ secrets.NCM_API_USER }} - NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} - NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "[ PREPARE ] configure server" - run: | - python manage.py makemigrations - python manage.py migrate - python manage.py loaddata acme_srv/fixture/status.yaml - - - name: "[ PREPARE ] try to get up the server" - run: | - Start-Process powershell {python .\manage.py runserver 0.0.0.0:8080 3>&1 2>&1 > volume\redirection.log} - - name: "[ PREPARE ] Sleep for 5s" - uses: juliangruber/sleep-action@v1 - with: - time: 5s - - - name: "[ TEST ] Test if directory ressource is accessable" - run: | - get-Process python - Invoke-RestMethod -Uri http://127.0.0.1:8080/directory -NoProxy -TimeoutSec 5 - [System.Net.Dns]::GetHostByName('localhost').HostName - ([System.Net.Dns]::GetHostByName(($env:computerName))).Hostname - - - name: "[ PREPARE ] Download win-acme" - run: | - Invoke-RestMethod -Uri https://github.com/win-acme/win-acme/releases/download/v2.2.6.1571/win-acme.v2.2.6.1571.x64.trimmed.zip -OutFile win-acme.zip - Expand-Archive .\win-acme.zip - mkdir win-acme\certs - dir win-acme\* - - - name: "[ ENROLL ] Enroll certificate via win-acme" - run: | - .\win-acme\wacs.exe --baseuri http://127.0.0.1:8080 --emailaddress=grindsa@bar.local --pemfilespath win-acme\certs --source manual --host ${{ secrets.CF_WINACME1_NAME }},${{ secrets.CF_WINACME2_NAME }} --store pemfiles --force - - - name: "[ PREPARE ] try to get up the sslserver" - run: | - Start-Process powershell {python .\manage.py runsslserver 0.0.0.0:443 --certificate acme2certifier/acme2certifier_cert.pem --key acme2certifier/acme2certifier_key.pem 3>&1 2>&1 > volume\redirection_ssl.log} - - - name: "[ PREPARE ] Sleep for 5s" - uses: juliangruber/sleep-action@v1 - with: - time: 5s - - - name: "[ TEST ] Test if directory ressource is accessable" - run: | - get-Process python - Invoke-RestMethod -SkipCertificateCheck -Uri https://localhost -NoProxy -TimeoutSec 5 - [System.Net.Dns]::GetHostByName('localhost').HostName - ([System.Net.Dns]::GetHostByName(($env:computerName))).Hostname - - - name: "[ PREPARE ] Install and configure Posh-ACME" - run: | - Install-Module -Name Posh-ACME -Scope CurrentUser -Force - - - name: "Create account via Posh-ACME" - run: | - set-PAServer -DirectoryUrl https://localhost/directory -SkipCertificateCheck - $DebugPreference = 'Continue' - New-PAAccount -Contact 'foo@bar.local' - $ACC_1 = (Get-PAAccount | Out-String -Stream | Select-String -Pattern "valid") - echo ACC1=$ACC_1 >> $env:GITHUB_ENV - Export-PAAccountKEy -OutputFile foo.key - echo $env:ACC_1 - - - name: "Recreate account via Posh-ACME" - run: | - $DebugPreference = 'Continue' - Get-PAAccount | Remove-PAAccount -Force - Get-PAAccount - New-PAAccount -Contact 'win4@bar.local' -AcceptTOS -OnlyReturnExisting -KeyFile foo.key - Get-PAAccount -Refresh - $ACC_2 = (Get-PAAccount | Out-String -Stream | Select-String -Pattern "valid") - echo ACC2=$ACC_2 >> $env:GITHUB_ENV - echo $env:ACC_2 - - - name: "Rollover account key" - run: | - $DebugPreference = 'Continue' - Set-PAAccount -KeyRollover - - - name: "[ ENROLL ] Enroll Certificate via Posh-ACME" - # if: $env:ACC_1 == env.ACC_2 - run: | - $DebugPreference = 'Continue' - New-PACertificate ${{ secrets.CF_WINACME1_NAME }} -Plugin WebSelfHost -PluginArgs @{} -Force - - - name: "[ * ] collecting test logs" - if: ${{ failure() }} - run: | - mkdir ${{ github.workspace }}\artifact\upload - cp volume ${{ github.workspace }}\artifact\upload/ -Recurse -Force - cp acme_srv\acme_srv.cfg ${{ github.workspace }}\artifact\upload - - - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 - if: ${{ failure() }} - with: - name: win-acme.tar.gz - path: ${{ github.workspace }}/artifact/upload/ diff --git a/.github/workflows/wsgi_handler-test.yml b/.github/workflows/wsgi_handler-test.yml index 695f65d1..fff1e755 100644 --- a/.github/workflows/wsgi_handler-test.yml +++ b/.github/workflows/wsgi_handler-test.yml @@ -3,7 +3,7 @@ name: WSGI handler tests on: push: pull_request: - branches: [ devel, db_file_customization ] + branches: [ devel] schedule: # * is a special character in YAML so you have to quote this string - cron: '0 2 * * 6' @@ -12,55 +12,52 @@ jobs: a2_cust_db_file: name: "a2_cust_db_file" runs-on: ubuntu-latest + strategy: + fail-fast: false + max-parallel: 1 + matrix: + websrv: ['apache2', 'nginx'] steps: - name: "checkout GIT" - uses: actions/checkout@v3 + uses: actions/checkout@v4 - - name: "[ PREPARE ] Build docker-compose (apache2_wsgi)" - working-directory: examples/Docker/ - run: | - sudo mkdir -p data - docker network create acme - sudo touch data/acme_srv.cfg - sudo chmod 777 data/acme_srv.cfg - sudo head -n -8 ../../.github/openssl_ca_handler.py_acme_srv_default_handler.cfg > data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> data/acme_srv.cfg - sudo echo "[DBhandler]" >> data/acme_srv.cfg - sudo echo "dbfile: volume/a2c.db" >> data/acme_srv.cfg - sudo echo "[Directory]" >> data/acme_srv.cfg - sudo echo "url_prefix: /foo" >> data/acme_srv.cfg - docker-compose up -d - docker-compose logs - env: + - name: "Build container" + uses: ./.github/actions/container_prep + with: + DB_HANDLER: wsgi + WEB_SRV: ${{ matrix.websrv }} + + - name: "Prepare acme_srv.cfg with certifier_ca_handler" + uses: ./.github/actions/wf_specific/certifier_ca_handler/certifier_setup_no_profile + with: + WCCE_SSH_ACCESS_KEY: ${{ secrets.WCCE_SSH_ACCESS_KEY }} + WCCE_SSH_KNOWN_HOSTS: ${{ secrets.WCCE_SSH_KNOWN_HOSTS }} + WCCE_SSH_USER: ${{ secrets.WCCE_SSH_USER }} + WCCE_SSH_HOST: ${{ secrets.WCCE_SSH_HOST }} + WCCE_SSH_PORT: ${{ secrets.WCCE_SSH_PORT }} NCM_API_HOST: ${{ secrets.NCM_API_HOST }} NCM_API_USER: ${{ secrets.NCM_API_USER }} NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} - NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - - name: "Test http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "[ PREPARE ] prepare acme.sh container" - run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon + DATA_PATH: examples/Docker/data - - name: "[ ENROLL ] acme.sh" + - name: "Restart a2c" run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --standalone --debug 3 --output-insecure --force - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - - name: "[ ENROLL ] lego" - run: | - mkdir lego - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --http run - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + sudo echo "[DBhandler]" >> examples/Docker/data/acme_srv.cfg + sudo echo "dbfile: volume/a2c.db" >> examples/Docker/data/acme_srv.cfg + sudo echo "[Directory]" >> examples/Docker/data/acme_srv.cfg + sudo echo "url_prefix: /foo" >> examples/Docker/data/acme_srv.cfg + cd examples/Docker/ + docker-compose restart + + - name: "Test enrollment" + uses: ./.github/actions/acme_clients + + - name: "Check container configuration" + uses: ./.github/actions/container_check + with: + DB_HANDLER: wsgi + WEB_SRV: ${{ matrix.websrv }} - name: "[ * ] collecting test logs" if: ${{ failure() }} @@ -72,40 +69,51 @@ jobs: sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: ${{ failure() }} with: - name: a2_custdb.tar.gz + name: a2_custdb.${{ matrix.websrv }}.tar.gz path: ${{ github.workspace }}/artifact/upload/ - nginx_cust_db_file: - name: "nginx_cust__db_file" + rpm_cust_db_file: + name: "rpm_cust_db_file" runs-on: ubuntu-latest + strategy: + fail-fast: false + max-parallel: 1 + matrix: + rhversion: [8, 9] steps: - name: "checkout GIT" - uses: actions/checkout@v3 + uses: actions/checkout@v4 - - name: "[ PREPARE ] Build docker-compose (nginx_wsgi)" - working-directory: examples/Docker/ + - name: "Prepare Alma environment" + uses: ./.github/actions/rpm_prep + with: + GH_SBOM_USER: ${{ secrets.GH_SBOM_USER }} + GH_SBOM_TOKEN: ${{ secrets.GH_SBOM_TOKEN }} + RH_VERSION: ${{ matrix.rhversion }} + + - name: "Prepare acme_srv.cfg with certifier_ca_handler" + uses: ./.github/actions/wf_specific/certifier_ca_handler/certifier_setup_no_profile + with: + WCCE_SSH_ACCESS_KEY: ${{ secrets.WCCE_SSH_ACCESS_KEY }} + WCCE_SSH_KNOWN_HOSTS: ${{ secrets.WCCE_SSH_KNOWN_HOSTS }} + WCCE_SSH_USER: ${{ secrets.WCCE_SSH_USER }} + WCCE_SSH_HOST: ${{ secrets.WCCE_SSH_HOST }} + WCCE_SSH_PORT: ${{ secrets.WCCE_SSH_PORT }} + NCM_API_HOST: ${{ secrets.NCM_API_HOST }} + NCM_API_USER: ${{ secrets.NCM_API_USER }} + NCM_API_PASSWORD: ${{ secrets.NCM_API_PASSWORD }} + NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} + DATA_PATH: data + + - name: "Prepare acme_srv.cfg with openssl_ca_handler" run: | - sed -i "s/apache2/nginx/g" .env - sudo mkdir -p data - docker network create acme - sudo touch data/acme_srv.cfg - sudo chmod 777 data/acme_srv.cfg - sudo head -n -8 ../../.github/openssl_ca_handler.py_acme_srv_default_handler.cfg > data/acme_srv.cfg - sudo echo "handler_file: examples/ca_handler/certifier_ca_handler.py" >> data/acme_srv.cfg - sudo echo "api_host: $NCM_API_HOST" >> data/acme_srv.cfg - sudo echo "api_user: $NCM_API_USER" >> data/acme_srv.cfg - sudo echo "api_password: $NCM_API_PASSWORD" >> data/acme_srv.cfg - sudo echo "ca_name: $NCM_CA_NAME" >> data/acme_srv.cfg - sudo echo "ca_bundle: $NCM_CA_BUNDLE" >> data/acme_srv.cfg sudo echo "[DBhandler]" >> data/acme_srv.cfg - sudo echo "dbfile: volume/a2c.db" >> data/acme_srv.cfg + sudo echo "dbfile: /opt/acme2certifier/volume/a2c.db" >> data/acme_srv.cfg sudo echo "[Directory]" >> data/acme_srv.cfg sudo echo "url_prefix: /foo" >> data/acme_srv.cfg - docker-compose up -d - docker-compose logs sleep 5 env: NCM_API_HOST: ${{ secrets.NCM_API_HOST }} @@ -114,37 +122,29 @@ jobs: NCM_CA_NAME: ${{ secrets.NCM_CA_NAME }} NCM_CA_BUNDLE: ${{ secrets.NCM_CA_BUNDLE }} - - name: "Test http://acme-srv/directory is accessable" - run: docker run -i --rm --network acme curlimages/curl -f http://acme-srv/directory - - - name: "[ PREPARE ] prepare acme.sh container" + - name: "Execute install scipt" run: | - docker run --rm -id -v "$(pwd)/acme-sh":/acme.sh --network acme --name=acme-sh neilpang/acme.sh:latest daemon + docker exec acme-srv sh /tmp/acme2certifier/rpm_tester.sh - - name: "[ ENROLL ] acme.sh" - run: | - docker exec -i acme-sh acme.sh --server http://acme-srv --accountemail 'acme-sh@example.com' --issue -d acme-sh.acme --standalone --debug 3 --output-insecure --force - awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > "cert-" c ".pem"}' < acme-sh/acme-sh.acme_ecc/ca.cer - openssl verify -CAfile cert-2.pem -untrusted cert-1.pem acme-sh/acme-sh.acme_ecc/acme-sh.acme.cer - - - name: "[ ENROLL ] lego" - run: | - mkdir lego - docker run -i -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://acme-srv -a --email "lego@example.com" -d lego.acme --http run - sudo openssl verify -CAfile cert-2.pem -untrusted cert-1.pem lego/certificates/lego.acme.crt + - name: "Test enrollment" + uses: ./.github/actions/acme_clients - name: "[ * ] collecting test logs" if: ${{ failure() }} run: | mkdir -p ${{ github.workspace }}/artifact/upload - sudo cp -rp examples/Docker/data/ ${{ github.workspace }}/artifact/data/ - cd examples/Docker - docker-compose logs > ${{ github.workspace }}/artifact/docker-compose.log - sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz docker-compose.log data + docker exec acme-srv tar cvfz /tmp/acme2certifier/a2c.tgz /opt/acme2certifier + sudo cp -rp data/ ${{ github.workspace }}/artifact/data/ + sudo cp -rp acme-sh/ ${{ github.workspace }}/artifact/acme-sh/ + sudo rm ${{ github.workspace }}/artifact/data/*.rpm + docker exec acme-srv cat /etc/nginx/nginx.conf.orig > ${{ github.workspace }}/artifact/data/nginx.conf.orig + docker exec acme-srv cat /etc/nginx/nginx.conf > ${{ github.workspace }}/artifact/data/nginx.conf + docker exec acme-srv cat /var/log/messages > ${{ github.workspace }}/artifact/acme-srv.log + sudo tar -C ${{ github.workspace }}/artifact/ -cvzf ${{ github.workspace }}/artifact/upload/artifact.tar.gz data acme-srv.log acme-sh - name: "[ * ] uploading artificates" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: ${{ failure() }} with: - name: nginx_cust_db.tar.gz + name: rpm_cust_db_file-rh${{ matrix.rhversion }}.tar.gz path: ${{ github.workspace }}/artifact/upload/ diff --git a/.gitignore b/.gitignore index da25b0d5..dfad8fb0 100644 --- a/.gitignore +++ b/.gitignore @@ -143,6 +143,7 @@ acme_srv/ejbca/* acme_srv/ssl/* acme_srv/cn_dump/* acme_srv/fixture +acme_srv/entrust/* *.dll acme_srv/cmp/WindowsCMPOpenSSL/openssl.exe acme_srv/migrations.old diff --git a/CHANGES.md b/CHANGES.md index cf161358..b98397e6 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -5,6 +5,108 @@ This is a high-level summary of the most important changes. For a full list of changes, see the [git commit log](https://github.com/grindsa/acme2certifier/commits) and pick the appropriate release branch. +# Changes in 0.36 + +**Features and Improvements**: + +- refactored [NCLM ca handler](docs/nclm.md) using the external REST-API +- [ca handler](docs/digicert.md) using the [DigiCert CertCentral API](https://dev.digicert.com/en/certcentral-apis.html) +- [ca handler](docs/entrust.md) using the Entrust ECS Enterprise APIl +- [EAB Profiling support](docs/eab_profiling.md) in Microsoft CA handlers +- [#187](https://github.com/grindsa/acme2certifier/pull/187) url option for mscertsrv ca handler +- subject profiling feature +- [strip down python-impacket module](https://github.com/grindsa/acme2certifier/blob/master/docs/mswcce.md#local-installation) in docker images +- [strip down impacket RPM package](https://github.com/grindsa/sbom/tree/main/rpm-repo/RPMs/rhel9) +- YAML config file format supported in [EAB-Profiling feature](docs/eab_profiling.md) +- Upgrade Container images to Ubuntu 24.04 + +**Bugfixes**: + +- openssl-ca-handler: basicConstraints extension will not be marked as critical anymore +- openssl-ca-handler: subjectkeyidentifier extension will not be marked as critical anymore +- fall-back option to python-openssl for Redhat deployments +- detect and handle django installations on Debian/Ubunto systems +- automated schema updates in case of RPM updates + +# Changes in 0.35 + +**Features and Improvements**: + +- [#153](https://github.com/grindsa/acme2certifier/issues/153) Kerberos support in [mscertsrv_handler](docs/mscertsrv.md) +- allowed_domainlist checking in [mswcce_handler](docs/mswcce.md) +- `timeout` parameter in [ms-wcce_handler](docs/mswcce.md) to specify an enrollment timeout +- new [tool to validate eab-files](docs/eab_profiling.md#profile-verification) +- [#165](https://github.com/grindsa/acme2certifier/issues/165) [EAB profiling](docs/eab_profiling.md#enrollment-profiling-via-external-account-binding) for ejbca_handler +- [#166](https://github.com/grindsa/acme2certifier/issues/166) [EAB profiling](docs/acme_ca.md#eab-profiling) for acme_ca_handler +- documentation for active/active setup on [Alma9](docs/a2c-alma-loadbalancing.md) and [Ubuntu 22.04](docs/a2c-ubuntu-loadbalancing.md) +- [#165](https://github.com/grindsa/acme2certifier/issues/165) documentaion of [external database support](docs/external_database_support.md) via django_handler + +**Bugfixes**: + +- `acme_srv.cfg` will be preserved in case of RPM updates +- apache2_wsgi docker image will be tagged with `latest` +- [#166](https://github.com/grindsa/acme2certifier/issues/166) workaround for failed account lookups on smallstep-ca + +# Changes in 0.34 + +**Features and Improvements**: + +- [Enrollment profiling via external account binding](docs/eab_profiling.md) +- [#144](https://github.com/grindsa/acme2certifier/issues/144) configuration option to supress product name +- [#143](https://github.com/grindsa/acme2certifier/issues/143) template name as part of the user-agent field in wcce/wes handler +- configuration option to limit the number of identifiers in a single order request +- `burst` parameter in example nginx.conf to ratelimit incoming requests +- [container images for arm64 plattforms](https://hub.docker.com/layers/grindsa/acme2certifier/apache2-wsgi/images/sha256-9092e98ad23fa94dfb17534333a9306ec447b274c2e4b5bbaee0b8bc41c6becc?context=repo) +- regression tests on arm64 plattforms + +**Bugfixes**: + +- [#147](https://github.com/grindsa/acme2certifier/pull/147) correct content-type for problem+json message +- updated [eab-example files](https://github.com/grindsa/acme2certifier/tree/master/examples/eab_handler) as hmac must be longer than 256bits +- identifier sanitizing + +# Changes in 0.33.3 + +**Features and Improvements**: + +- some smaller modifications run flawless on Redhat8 and derivates +- Workflows to test rpm-deployment on RHEL8 and RHEL9 + +# Changes in 0.33.2 + +**Upgrade notes**: + +- database scheme gets updated. Please run either + - `tools/db_update.py` when using the wsgi_handler or + - `tools/django_update.py` in case you are using the django_handler + +**Bugfixes**: + +- [134](https://github.com/grindsa/acme2certifier/issues/134) - acme_srv_housekeeping" -> value too long for "name" field +- [135](https://github.com/grindsa/acme2certifier/issues/134) - acme_srv_housekeeping dbversion ist set back to 0.23.1 after container restart + +# Changes in 0.33.1 + +**Bugfixes**: + +- [132](https://github.com/grindsa/acme2certifier/issues/132) - returning serial numbers in hex-format with leading zero + +# Changes in 0.33 + +**Upgrade notes**: + +- database scheme gets updated. Please run either + - `tools/db_update.py` when using the wsgi_handler or + - `tools/django_update.py` in case you are using the django_handler + +**Features and Improvements**: + +- Support [draft-ietf-acme-ari-02](https://datatracker.ietf.org/doc/draft-ietf-acme-ari/02): Renewal Information (ARI) Extension +- First version of [Insta ASA CA handler](docs/asa.md) +- [winacme renewal-info workaround](https://github.com/grindsa/acme2certifier/issues/127) +- better logging to ease troubleshootnig of eab +- code refactoring to improve [f-string handling](https://pylint.pycqa.org/en/latest/user_guide/messages/convention/consider-using-f-string.html) + # Changes in 0.32 **Features and Improvements**: @@ -56,7 +158,7 @@ and pick the appropriate release branch. **Features and Improvements**: - Support [RFC 8738](https://www.rfc-editor.org/rfc/rfc8738.html): Certificates for IP addresses -- Support [draft-ietf-acme-ari-01](https://datatracker.ietf.org/doc/draft-ietf-acme-ari/): Renewal Information (ARI) Extension +- Support [draft-ietf-acme-ari-01](https://datatracker.ietf.org/doc/draft-ietf-acme-ari/01): Renewal Information (ARI) Extension - Interoperability testing with [Caddy](https://caddyserver.com/docs/automatic-https) as part of regular regression # Changes in 0.28 @@ -288,7 +390,7 @@ and pick the appropriate release branch. **Features**: - [Generic ACME protocol handler](docs/acme_ca.md) -- CA handler for [acme2dfn](https://github.com/pfisterer/acme2dfn) (external; ACME proxy for the [German research network's SOAP API](https://blog.pki.dfn.de/tag/soap-api/)) +- CA handler for [acme2dfn](https://github.com/pfisterer/acme2dfn) - wsgi_db_handler: allow DB file path configuration - allow setting config file location via environment variable diff --git a/README.md b/README.md index 9e3dc46f..56c19812 100644 --- a/README.md +++ b/README.md @@ -14,30 +14,33 @@ [![Reliability Rating](https://sonarcloud.io/api/project_badges/measure?project=grindsa_acme2certifier&metric=reliability_rating)](https://sonarcloud.io/summary/overall?id=grindsa_acme2certifier&branch=min) [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=grindsa_acme2certifier&metric=alert_status)](https://sonarcloud.io/summary/overall?id=grindsa_acme2certifier&branch=min) -acme2certifier is development project to create an ACME protocol proxy. Main -intention is to provide ACME services on CA servers which do not support this -protocol yet. It consists of two libraries: +acme2certifier is development project to create an ACME protocol proxy. Main intention is to provide ACME services on CA servers which do not support this protocol yet. It consists of two libraries: - acme_srv/*.py - a bunch of classes implementing ACME server functionality based on [rfc8555](https://tools.ietf.org/html/rfc8555) - ca_handler.py - interface towards CA server. The intention of this library is to be modular that an [adaption to other CA servers](docs/ca_handler.md) should be straight forward. As of today the following handlers are available: - - [NetGuard Certificate Manager/Insta Certifier](docs/certifier.md) - - [NetGuard Certificate Lifecycle Manager](docs/nclm.md) - - [EJBCA](docs/ejbca.md) - - [OpenXPKI](docs/openxpki.md) - - [Microsoft Certificate Enrollment Web Services](docs/mscertsrv.md) - - [Microsoft Windows Client Certificate Enrollment Protocol (MS-WCCE) via RPC/DCOM](docs/mswcce.md) - - [Generic ACME protocol handler supporting Letsencrypt, BuyPass.com and ZeroSSL](docs/acme_ca.md) - - [Generic EST protocol handler](docs/est.md) - - [Generic CMPv2 protocol handler](docs/cmp.md) - - [Openssl](docs/openssl.md) - - [XCA](docs/xca.md) - - [acme2dfn](https://github.com/pfisterer/acme2dfn) (external; ACME proxy for the [German research network's PKI](https://www.pki.dfn.de/ueberblick-dfn-pki/) - -For more up-to-date information and further documentation, please visit the -project's home page at: [https://github.com/grindsa/acme2certifier](https://github.com/grindsa/acme2certifier) + +| E - Certificte Enrollment, R - Certificte Revocation, P - [EAB Profiling](docs/eab_profiling.md) |E|R|P| +| :-------- | - | - | - | +| [DigiCert® CertCentral](docs/digicert.md) | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| [Entrust ECS Enterprise](docs/entrust.md) | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| [EJBCA](docs/ejbca.md) | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| [Generic ACME protocol handler supporting Letsencrypt, BuyPass.com and ZeroSSL](docs/acme_ca.md) | :x: | :x: | :white_check_mark: | +| [Generic CMPv2 protocol handler](docs/cmp.md) | :white_check_mark: | :x: | :x: | +| [Generic EST protocol handler](docs/est.md) | :white_check_mark: | :x: | :x: | +| [Insta ActiveCMS](docs/asa.md) | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| [Microsoft Certificate Enrollment Web Services](docs/mscertsrv.md) | :white_check_mark: | :x: | :white_check_mark: | +| [Microsoft Windows Client Certificate Enrollment Protocol (MS-WCCE) via RPC/DCOM](docs/mswcce.md) | :white_check_mark: | :x: | :white_check_mark: | +| [NetGuard Certificate Lifecycle Manager](docs/nclm.md) | :white_check_mark: | :white_check_mark: | :x: | +| [NetGuard Certificate Manager/Insta Certifier](docs/certifier.md) | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| [Openssl](docs/openssl.md) | :white_check_mark: | :white_check_mark: | :x: | +| [OpenXPKI](docs/openxpki.md) | :white_check_mark: | :white_check_mark: | :x: | +| [XCA](docs/xca.md) | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| [acme2dfn](https://github.com/pfisterer/acme2dfn) (external; ACME proxy for the [German research network's PKI](https://www.pki.dfn.de/ueberblick-dfn-pki/)| :white_check_mark: | :x: | :x: | + +For more up-to-date information and further documentation, please visit the project's home page at: [https://github.com/grindsa/acme2certifier](https://github.com/grindsa/acme2certifier) ## ChangeLog @@ -57,21 +60,18 @@ Following acme-clients are used for regular testing of server functionality - [Posh-ACME](https://github.com/rmbolger/Posh-ACME) - [win-acme](https://www.win-acme.com/) -Other clients are on my list for later testing. In case you are bored, feel -free to test other ACME clients and raise [issues](https://github.com/grindsa/acme2certifier/issues/new) -if something does not work as expected. +Other clients are on my list for later testing. In case you are bored, feel free to test other ACME clients and raise [issues](https://github.com/grindsa/acme2certifier/issues/new) if something does not work as expected. [Command-line parameters used for testing](docs/acme-clients.md) -I am not a professional developer. Keep this in mind while laughing about my -code and don’t forget to send patches. +I am not a professional developer. Keep this in mind while laughing about my code and don’t forget to send patches. ## Features - ACME v2 [RFC 8555](https://www.rfc-editor.org/rfc/rfc8555.html) compliant server implementation including - Support [RFC 8737](https://www.rfc-editor.org/rfc/rfc8737.html): TLS Application‑Layer Protocol Negotiation (ALPN) Challenge Extension - Support [RFC 8738](https://www.rfc-editor.org/rfc/rfc8738.html): Certificates for IP addresses - - Support [draft-ietf-acme-ari-01](https://datatracker.ietf.org/doc/draft-ietf-acme-ari/): Renewal Information (ARI) Extension + - Support [draft-ietf-acme-ari-02](https://datatracker.ietf.org/doc/draft-ietf-acme-ari/02/) and [draft-ietf-acme-ari-01](https://datatracker.ietf.org/doc/draft-ietf-acme-ari/01/): Renewal Information (ARI) Extension - Support [TNAuthList identifiers](https://datatracker.ietf.org/doc/html/draft-ietf-acme-authority-token-tnauthlist-13): [TNAuthList profile](docs/tnauthlist.md) of ACME Authority Token - Support [tkauth-01](https://datatracker.ietf.org/doc/html/draft-ietf-acme-authority-token-09) ACME Challenges Using an Authority Token - [Certificate polling](docs/poll.md) and [Call backs](docs/trigger.md) from CA servers. These calls are not standardized but important to use acme2certifier together with classical enterprise CA @@ -87,12 +87,9 @@ Additional functionality will be added over time. If you are badly missing a cer ## Installation -The proxy can run either as plain wsgi-script on either apache or nginx or as -django project. Running acme2certifier as django project allows to use other -database backends than SQLite. +The proxy can run either as plain wsgi-script on either apache or nginx or as django project. Running acme2certifier as django project allows to use other database backends than SQLite. -The fastest and most convenient way to install acme2certifier is to use docker -containers. There are ready made images available at [dockerhub](https://hub.docker.com/r/grindsa/acme2certifier) and [ghcr.io](https://github.com/grindsa?tab=packages&ecosystem=container) as well as [instructions to build your own container](examples/Docker/). In addition rpm packages for AlmaLinux/CentOS Stream/Redhat EL 9 and deb packages for Ubuntu 22.04 will be provided with every release. +The fastest and most convenient way to install acme2certifier is to use docker containers. There are ready made images available at [dockerhub](https://hub.docker.com/r/grindsa/acme2certifier) and [ghcr.io](https://github.com/grindsa?tab=packages&ecosystem=container) as well as [instructions to build your own container](examples/Docker/). In addition rpm packages for AlmaLinux/CentOS Stream/Redhat EL 9 and deb packages for Ubuntu 22.04 will be provided with every release. - [acme2certifier in Github container repository](https://github.com/grindsa?tab=packages&ecosystem=container) - [acme2certifier repository at hub.docker.com](https://hub.docker.com/r/grindsa/acme2certifier) @@ -109,15 +106,11 @@ containers. There are ready made images available at [dockerhub](https://hub.do ## Contributing -Please read [CONTRIBUTING.md](docs/CONTRIBUTING.md) for details on my code of -conduct, and the process for submitting pull requests. -Please note that I have a life besides programming. Thus, expect a delay -in answering. +Please read [CONTRIBUTING.md](docs/CONTRIBUTING.md) for details on my code of conduct, and the process for submitting pull requests. Please note that I have a life besides programming. Thus, expect a delay in answering. ## Versioning -I use [SemVer](http://semver.org/) for versioning. For the versions available, -see the [tags on this repository](https://github.com/grindsa/dkb-robo/tags). +I use [SemVer](http://semver.org/) for versioning. For the versions available, see the [tags on this repository](https://github.com/grindsa/dkb-robo/tags). ## License diff --git a/SECURITY.md b/SECURITY.md index 3ba9ed39..3f6ed588 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -6,9 +6,9 @@ | Version | Supported | | ------- | ------------------ | -| 0.32.x | :white_check_mark: | -| 0.31.x | :white_check_mark: | -| < 0.31 | :x: | +| 0.36.x | :white_check_mark: | +| 0.35.x | :white_check_mark: | +| < 0.35 | :x: | ## Reporting a Vulnerability diff --git a/acme_srv/account.py b/acme_srv/account.py index e8542b8b..713d6fe2 100644 --- a/acme_srv/account.py +++ b/acme_srv/account.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- -# pylint: disable=C0209 """ Account class """ from __future__ import print_function import json @@ -58,7 +57,7 @@ def _account_lookup(self, jwk: Dict[str, str]) -> Tuple[int, str, Dict[str, str] try: result = self.dbstore.account_lookup('jwk', json.dumps(jwk)) except Exception as err_: - self.logger.critical('acme2certifier database error in Account._account_lookup(): {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Account._account_lookup(): %s', err_) result = None if result: @@ -72,21 +71,21 @@ def _account_lookup(self, jwk: Dict[str, str]) -> Tuple[int, str, Dict[str, str] message = self.err_msg_dic['accountdoesnotexist'] detail = None - self.logger.debug('Account._acount_lookup() ended with:{0}'.format(code)) + self.logger.debug('Account._acount_lookup() ended with: %s', code) return (code, message, detail) def _account_add_check(self, account_name: str, data_dic: Dict[str, str]) -> Tuple[int, str, str]: """ perform database operation """ - self.logger.debug('Account.account._account_add_check({0})'.format(account_name)) + self.logger.debug('Account.account._account_add_check(%s)', account_name) try: (db_name, new) = self.dbstore.account_add(data_dic) except Exception as err_: - self.logger.critical('Account.account._add(): Database error: {0}'.format(err_)) + self.logger.critical('Account.account._add(): Database error: %s', err_) db_name = None new = False - self.logger.debug('got account_name:{0} new:{1}'.format(db_name, new)) + self.logger.debug('got account_name: %s new: %s', db_name, new) if new: code = 201 @@ -96,7 +95,7 @@ def _account_add_check(self, account_name: str, data_dic: Dict[str, str]) -> Tup message = db_name detail = None - self.logger.debug('Account.account._account_add_check() ended with: {0}'.format(account_name)) + self.logger.debug('Account.account._account_add_check() ended with: %s', account_name) return (code, message, detail) def _account_eab_add(self, payload: Dict[str, str], data_dic: Dict[str, str]) -> Dict[str, str]: @@ -106,7 +105,7 @@ def _account_eab_add(self, payload: Dict[str, str], data_dic: Dict[str, str]) -> if payload and 'externalaccountbinding' in payload and payload['externalaccountbinding']: if 'protected' in payload['externalaccountbinding']: eab_kid = self._eab_kid_get(payload['externalaccountbinding']['protected']) - self.logger.info('add eab_kid: {0} to data_dic'.format(eab_kid)) + self.logger.info('add eab_kid: %s to data_dic', eab_kid) if eab_kid: data_dic['eab_kid'] = eab_kid @@ -115,7 +114,7 @@ def _account_eab_add(self, payload: Dict[str, str], data_dic: Dict[str, str]) -> def _account_add(self, account_name: str, content: Dict[str, str], contact: List[str], payload: Dict[str, str]): """ prepare db insert and call DBstore helper """ - self.logger.debug('Account.account._account_add({0})'.format(account_name)) + self.logger.debug('Account.account._account_add(%s)', account_name) # ecc_only check if self.ecc_only and not content['alg'].startswith('ES'): @@ -137,7 +136,7 @@ def _account_add(self, account_name: str, content: Dict[str, str], contact: List # check code to be returned (code, message, detail) = self._account_add_check(account_name, data_dic) - self.logger.debug('Account.account._account_add() ended with: {0}'.format(account_name)) + self.logger.debug('Account.account._account_add() ended with: %s', account_name) return (code, message, detail) def _add(self, content: Dict[str, str], payload: Dict[str, str], contact: List[str]): @@ -161,7 +160,7 @@ def _add(self, content: Dict[str, str], payload: Dict[str, str], contact: List[s message = self.err_msg_dic['malformed'] detail = 'incomplete protected payload' - self.logger.debug('Account.account._add() ended with:{0}'.format(code)) + self.logger.debug('Account.account._add() ended with: %s', code) return (code, message, detail) def _contact_check(self, content: Dict[str, str]) -> Tuple[int, str, str]: @@ -182,7 +181,7 @@ def _contact_check(self, content: Dict[str, str]) -> Tuple[int, str, str]: message = self.err_msg_dic['invalidcontact'] detail = 'no contacts specified' - self.logger.debug('Account._contact_check() ended with:{0}'.format(code)) + self.logger.debug('Account._contact_check() ended with: %s', code) return (code, message, detail) def _contact_list_build(self, payload: Dict[str, str]) -> List[str]: @@ -206,7 +205,7 @@ def _contacts_update(self, aname: str, payload: Dict[str, str]) -> Tuple[int, st try: result = self.dbstore.account_update(data_dic) except Exception as err_: - self.logger.critical('acme2certifier database error in Account._contacts_update(): {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Account._contacts_update(): %s', err_) result = None if result: @@ -220,11 +219,11 @@ def _contacts_update(self, aname: str, payload: Dict[str, str]) -> Tuple[int, st def _delete(self, aname: str) -> Tuple[int, str, str]: """ delete account """ - self.logger.debug('Account._delete({0})'.format(aname)) + self.logger.debug('Account._delete(%s)', aname) try: result = self.dbstore.account_delete(aname) except Exception as err_: - self.logger.critical('acme2certifier database error in Account._delete(): {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Account._delete(): %s', err_) result = None if result: @@ -236,12 +235,12 @@ def _delete(self, aname: str) -> Tuple[int, str, str]: message = self.err_msg_dic['accountdoesnotexist'] detail = 'deletion failed' - self.logger.debug('Account._delete() ended with:{0}'.format(code)) + self.logger.debug('Account._delete() ended with: %s', code) return (code, message, detail) def _eab_jwk_compare(self, protected: Dict[str, str], payload: Dict[str, str]) -> bool: """ compare jwk from outer header with jwk in eab playload """ - self.logger.debug('_eab_jwk_compare()') + self.logger.debug('Account._eab_jwk_compare()') result = False if 'jwk' in protected: # convert outer jwk into string for better comparison @@ -253,12 +252,12 @@ def _eab_jwk_compare(self, protected: Dict[str, str], payload: Dict[str, str]) - if jwk_outer == jwk_inner: result = True - self.logger.debug('_eab_jwk_compare() ended with: {0}'.format(result)) + self.logger.debug('_eab_jwk_compare() ended with: %s', result) return result def _eab_kid_get(self, protected: str) -> str: """ get key identifier for eab validation """ - self.logger.debug('_eab_kid_get()') + self.logger.debug('Account._eab_kid_get()') # load protected into json format protected_dic = json.loads(b64decode_pad(self.logger, protected)) # extract kid @@ -267,12 +266,12 @@ def _eab_kid_get(self, protected: str) -> str: else: eab_key_id = None - self.logger.debug('_eab_kid_get() ended with: {0}'.format(eab_key_id)) + self.logger.debug('Account._eab_kid_get() ended with: %s', eab_key_id) return eab_key_id def _eab_verify(self, payload: Dict[str, str]) -> Tuple[int, str, str]: """" check for external account binding """ - self.logger.debug('_eab_check()') + self.logger.debug('Account._eab_verify()') # get key identifier eab_kid = self._eab_kid_get(payload['externalaccountbinding']['protected']) @@ -293,18 +292,18 @@ def _eab_verify(self, payload: Dict[str, str]) -> Tuple[int, str, str]: code = 403 message = self.err_msg_dic['unauthorized'] detail = 'eab signature verification failed' - self.logger.error('Account._eab_check() returned error: {0}'.format(error)) + self.logger.error('Account._eab_check() returned error: %s', error) else: code = 403 message = self.err_msg_dic['unauthorized'] detail = 'eab kid lookup failed' - self.logger.debug('_eab_check() ended with: {0}'.format(code)) + self.logger.debug('Account._eab_verify() ended with: %s', code) return (code, message, detail) def _eab_check(self, protected: Dict[str, str], payload: Dict[str, str]) -> Tuple[int, str, str]: """" check for external account binding """ - self.logger.debug('_eab_check()') + self.logger.debug('Account._eab_check()') if self.eab_handler and protected and payload and 'externalaccountbinding' in payload and payload['externalaccountbinding']: # compare JWK from protected (outer) header if jwk included in payload of external account binding @@ -323,7 +322,7 @@ def _eab_check(self, protected: Dict[str, str], payload: Dict[str, str]) -> Tupl message = self.err_msg_dic['externalaccountrequired'] detail = 'external account binding required' - self.logger.debug('Account._eab_check() ended with:{0}'.format(code)) + self.logger.debug('Account._eab_check() ended with: %s', code) return (code, message, detail) def _eab_signature_verify(self, content: Dict[str, str], mac_key: str) -> Tuple[bool, str]: @@ -337,7 +336,8 @@ def _eab_signature_verify(self, content: Dict[str, str], mac_key: str) -> Tuple[ else: sig_check = False error = None - self.logger.debug('Account._eab_signature_verify() ended with: {0}'.format(sig_check)) + + self.logger.debug('Account._eab_signature_verify() ended with: %s: %s', sig_check, error) return (sig_check, error) def _header_url_compare(self, outer_protected: Dict[str, str], inner_protected: Dict[str, str]) -> Tuple[int, str, str]: @@ -358,7 +358,7 @@ def _header_url_compare(self, outer_protected: Dict[str, str], inner_protected: message = self.err_msg_dic['malformed'] detail = 'url parameter differ in inner and outer jws' - self.logger.debug('Account._header_url_compare() ended with: {0}'.format(code)) + self.logger.debug('Account._header_url_compare() ended with: %s', code) return (code, message, detail) def _info(self, account_obj: Dict[str, str]) -> Dict[str, str]: @@ -374,7 +374,7 @@ def _info(self, account_obj: Dict[str, str]) -> Dict[str, str]: if 'eab_kid' in account_obj and account_obj['eab_kid']: response_dic['eab_kid'] = account_obj['eab_kid'] - self.logger.debug('Account._info() returns: {0}'.format(json.dumps(response_dic))) + self.logger.debug('Account._info() returns: %s', json.dumps(response_dic)) return response_dic def _inner_jws_check(self, outer_protected: Dict[str, str], inner_protected: Dict[str, str]) -> Tuple[int, str, str]: @@ -395,7 +395,7 @@ def _inner_jws_check(self, outer_protected: Dict[str, str], inner_protected: Dic message = self.err_msg_dic['malformed'] detail = 'inner jws is missing jwk' - self.logger.debug('Account._inner_jws_check() ended with: {0}:{1}'.format(code, detail)) + self.logger.debug('Account._inner_jws_check() ended with: %s:%s', code, detail) return (code, message, detail) def _inner_payload_check(self, aname: str, outer_protected: Dict[str, str], inner_payload: Dict[str, str]) -> Tuple[int, str, str]: @@ -425,12 +425,12 @@ def _inner_payload_check(self, aname: str, outer_protected: Dict[str, str], inne message = self.err_msg_dic['malformed'] detail = 'kid is missing in outer header' - self.logger.debug('Account._inner_payload_check() ended with: {0}:{1}'.format(code, detail)) + self.logger.debug('Account._inner_payload_check() ended with: %s:%s', code, detail) return (code, message, detail) def _key_change_validate(self, aname: str, outer_protected: Dict[str, str], inner_protected: Dict[str, str], inner_payload: Dict[str, str]): """ validate key_change before exectution """ - self.logger.debug('Account._key_change_validate({0})'.format(aname)) + self.logger.debug('Account._key_change_validate(%s)', aname) if 'jwk' in inner_protected: # check if we already have the key stored in DB key_exists = self._lookup(json.dumps(inner_protected['jwk']), 'jwk') @@ -448,12 +448,12 @@ def _key_change_validate(self, aname: str, outer_protected: Dict[str, str], inne message = self.err_msg_dic['malformed'] detail = 'inner jws is missing jwk' - self.logger.debug('Account._key_change_validate() ended with: {0}:{1}'.format(code, detail)) + self.logger.debug('Account._key_change_validate() ended with: %s:%s', code, detail) return (code, message, detail) def _key_rollover(self, aname: str, protected: Dict[str, str], inner_protected: Dict[str, str], inner_payload: Dict[str, str]) -> Tuple[int, str, str]: """ key update after key change """ - self.logger.debug('Account._key_rollover({0})'.format(aname)) + self.logger.debug('Account._key_rollover(%s)', aname) (code, message, detail) = self._key_change_validate(aname, protected, inner_protected, inner_payload) if code == 200: @@ -461,7 +461,7 @@ def _key_rollover(self, aname: str, protected: Dict[str, str], inner_protected: try: result = self.dbstore.account_update(data_dic) except Exception as err_: - self.logger.critical('acme2certifier database error in Account._key_change(): {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Account._key_change(): %s', err_) result = None if result: code = 200 @@ -472,12 +472,12 @@ def _key_rollover(self, aname: str, protected: Dict[str, str], inner_protected: message = self.err_msg_dic['serverinternal'] detail = 'key rollover failed' - self.logger.debug('Account._key_rollover() ended with: {0}'.format(code)) + self.logger.debug('Account._key_rollover() ended with: %s', code) return (code, message, detail) def _key_change(self, aname: str, payload: Dict[str, str], protected: Dict[str, str]) -> Tuple[int, str, str]: """ key change for a given account """ - self.logger.debug('Account._key_change({0})'.format(aname)) + self.logger.debug('Account._key_change(%s)', aname) if 'url' in protected: if 'key-change' in protected['url']: @@ -495,7 +495,7 @@ def _key_change(self, aname: str, payload: Dict[str, str], protected: Dict[str, message = self.err_msg_dic['malformed'] detail = 'malformed request' - self.logger.debug('Account._key_change() ended with: {0}'.format(code)) + self.logger.debug('Account._key_change() ended with: %s', code) return (code, message, detail) def _keys_adjust(self, pub_key: Dict[str, str], old_key: Dict[str, str]) -> Tuple[Dict[str, str], Dict[str, str]]: @@ -514,13 +514,13 @@ def _keys_adjust(self, pub_key: Dict[str, str], old_key: Dict[str, str]) -> Tupl def _key_compare(self, aname: str, old_key: Dict[str, str]) -> Tuple[int, str, str]: """ compare key with the one stored in database """ - self.logger.debug('Account._key_compare({0})'.format(aname)) + self.logger.debug('Account._key_compare(%s)', aname) # load current public key from database try: pub_key = self.dbstore.jwk_load(aname) except Exception as err_: - self.logger.critical('acme2certifier database error in Account._key_compare(): {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Account._key_compare(): %s', err_) pub_key = None if old_key and pub_key: @@ -540,7 +540,7 @@ def _key_compare(self, aname: str, old_key: Dict[str, str]) -> Tuple[int, str, s message = self.err_msg_dic['unauthorized'] detail = 'wrong public key' - self.logger.debug('Account._key_compare() ended with: {0}'.format(code)) + self.logger.debug('Account._key_compare() ended with: %s', code) return (code, message, detail) def _config_load(self): @@ -577,11 +577,11 @@ def _config_load(self): def _lookup(self, value: str, field: str = 'name') -> Dict[str, str]: """ lookup account """ - self.logger.debug('Account._lookup({0}:{1})'.format(field, value)) + self.logger.debug('Account._lookup(%s:%s)', field, value) try: result = self.dbstore.account_lookup(field, value) except Exception as err_: - self.logger.critical('acme2certifier database error in Account._lookup(): {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Account._lookup(): %s', err_) result = None return result @@ -618,11 +618,11 @@ def _onlyreturnexisting(self, protected: Dict[str, str], payload: Dict[str, str] message = self.err_msg_dic['serverinternal'] detail = 'onlyReturnExisting without payload' - self.logger.debug('Account.onlyreturnexisting() ended with:{0}'.format(code)) + self.logger.debug('Account.onlyreturnexisting() ended with: %s', code) return (code, message, detail) def _parse_deactivation(self, account_name: str, payload: Dict[str, str]) -> Tuple[int, str, str]: - self.logger.debug('Account._parse_deactivation({0})'.format(account_name)) + self.logger.debug('Account._parse_deactivation(%s)', account_name) data = None # account deactivation if payload['status'].lower() == 'deactivated': @@ -639,7 +639,7 @@ def _parse_deactivation(self, account_name: str, payload: Dict[str, str]) -> Tup def _parse_contacts_update(self, account_name: str, payload: Dict[str, str]) -> Tuple[int, str, str, Dict[str, str]]: """ update contacts """ - self.logger.debug('Account._parse_contacts_update({0})'.format(account_name)) + self.logger.debug('Account._parse_contacts_update(%s)', account_name) data = None (code, message, detail) = self._contacts_update(account_name, payload) if code == 200: @@ -655,7 +655,7 @@ def _parse_contacts_update(self, account_name: str, payload: Dict[str, str]) -> def _parse_query(self, account_name: str) -> Dict[str, str]: """ update contacts """ - self.logger.debug('Account._parse_query({0})'.format(account_name)) + self.logger.debug('Account._parse_query(%s)', account_name) # this is a query for account information account_obj = self._lookup(account_name) @@ -672,7 +672,7 @@ def _tos_check(self, content: Dict[str, str]) -> Tuple[int, str, str]: """ check terms of service """ self.logger.debug('Account._tos_check()') if 'termsofserviceagreed' in content: - self.logger.debug('tos:{0}'.format(content['termsofserviceagreed'])) + self.logger.debug('tos:%s', content['termsofserviceagreed']) if content['termsofserviceagreed']: code = 200 message = None @@ -687,7 +687,7 @@ def _tos_check(self, content: Dict[str, str]) -> Tuple[int, str, str]: message = self.err_msg_dic['useractionrequired'] detail = 'tosfalse' - self.logger.debug('Account._tos_check() ended with:{0}'.format(code)) + self.logger.debug('Account._tos_check() ended with:%s', code) return (code, message, detail) def _new(self, code: int, payload: Dict[str, str], protected: Dict[str, str]) -> Tuple[int, str, str]: @@ -717,7 +717,7 @@ def _new(self, code: int, payload: Dict[str, str], protected: Dict[str, str]) -> # add new account (code, message, detail) = self._add(protected, payload, contact_list) - self.logger.debug('Account._new() ended with: {0}'.format(code)) + self.logger.debug('Account._new() ended with: %s', code) return (code, message, detail) def new(self, content: Dict[str, str]) -> Dict[str, str]: @@ -735,7 +735,7 @@ def new(self, content: Dict[str, str]) -> Dict[str, str]: if code == 201: response_dic['data'] = { 'status': 'valid', - 'orders': '{0}{1}{2}/orders'.format(self.server_name, self.path_dic['acct_path'], message), + 'orders': f'{self.server_name}{self.path_dic["acct_path"]}{message}/orders' } if 'contact' in payload: response_dic['data']['contact'] = payload['contact'] @@ -743,7 +743,7 @@ def new(self, content: Dict[str, str]) -> Dict[str, str]: response_dic['data'] = detail response_dic['header'] = {} - response_dic['header']['Location'] = '{0}{1}{2}'.format(self.server_name, self.path_dic['acct_path'], message) + response_dic['header']['Location'] = f'{self.server_name}{self.path_dic["acct_path"]}{message}' # add exernal account binding if self.eab_check and 'externalaccountbinding' in payload: @@ -757,7 +757,7 @@ def new(self, content: Dict[str, str]) -> Dict[str, str]: status_dic = {'code': code, 'type': message, 'detail': detail} response_dic = self.message.prepare_response(response_dic, status_dic) - self.logger.debug('Account.new() returns: {0}'.format(json.dumps(response_dic))) + self.logger.debug('Account.new() returns: %s', json.dumps(response_dic)) return response_dic def parse(self, content: Dict[str, str]) -> Dict[str, str]: @@ -795,5 +795,5 @@ def parse(self, content: Dict[str, str]) -> Dict[str, str]: status_dic = {'code': code, 'type': message, 'detail': detail} response_dic = self.message.prepare_response(response_dic, status_dic) - self.logger.debug('Account.account_parse() returns: {0}'.format(json.dumps(response_dic))) + self.logger.debug('Account.account_parse() returns: %s', json.dumps(response_dic)) return response_dic diff --git a/acme_srv/acmechallenge.py b/acme_srv/acmechallenge.py index 5d2a1802..f3176e45 100644 --- a/acme_srv/acmechallenge.py +++ b/acme_srv/acmechallenge.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- """ acmechallenge class """ -# pylint: disable=C0209 from __future__ import print_function from acme_srv.db_handler import DBstore @@ -28,10 +27,10 @@ def lookup(self, path_info: str) -> str: key_authorization = None if path_info: token = path_info.replace('/.well-known/acme-challenge/', '') - self.logger.info('Acmechallenge.lookup() token: {0}'.format(token)) + self.logger.info('Acmechallenge.lookup() token: %s', token) challenge_dic = self.dbstore.cahandler_lookup('name', token) if challenge_dic and 'value1' in challenge_dic: key_authorization = challenge_dic['value1'] - self.logger.debug('Acmechallenge.lookup() ended with: {0}'.format(key_authorization)) + self.logger.debug('Acmechallenge.lookup() ended with: %s', key_authorization) return key_authorization diff --git a/acme_srv/authorization.py b/acme_srv/authorization.py index 1737d7e9..50ec44bf 100644 --- a/acme_srv/authorization.py +++ b/acme_srv/authorization.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- """ Order class """ -# pylint: disable=C0209, R0913 +# pylint: disable=R0913 from __future__ import print_function import json from typing import List, Tuple, Dict @@ -40,12 +40,12 @@ def _expiry_update(self, authz_name: str, token: str, expires: int): try: self.dbstore.authorization_update({'name': authz_name, 'token': token, 'expires': expires}) except Exception as err_: - self.logger.error('acme2certifier database error in Authorization._expiry_update({0}) update: {1}'.format(authz_name, err_)) + self.logger.error('acme2certifier database error in Authorization._expiry_update(%s) update: %s', authz_name, err_) self.logger.debug('Authorization._expiry_update() ended') def _authz_lookup(self, authz_name: str, vlist: List[str] = None) -> Dict[str, str]: - self.logger.debug('Authorization._authz_lookup({0})'.format(authz_name)) + self.logger.debug('Authorization._authz_lookup(%s)', authz_name) # lookup authorization based on name try: @@ -54,7 +54,7 @@ def _authz_lookup(self, authz_name: str, vlist: List[str] = None) -> Dict[str, s else: authz = self.dbstore.authorization_lookup('name', authz_name) except Exception as err_: - self.logger.critical('acme2certifier database error in Authorization._authz_lookup({0}) lookup: {1}'.format(authz_name, err_)) + self.logger.critical('acme2certifier database error in Authorization._authz_lookup(%s) lookup: %s', authz_name, err_) authz = None self.logger.debug('Authorization._authz_lookup() ended') @@ -62,7 +62,7 @@ def _authz_lookup(self, authz_name: str, vlist: List[str] = None) -> Dict[str, s def _challengeset_get(self, authz_info_dic: Dict[str, str], authz_name: str, token: str, tnauth: bool, expires: int) -> Dict[str, str]: """ get challenge set """ - self.logger.debug('Authorization._challengeset_get({0})'.format(authz_name)) + self.logger.debug('Authorization._challengeset_get(%s)', authz_name) with Challenge(self.debug, self.server_name, self.logger, expires) as challenge: # get challenge data (either existing or new ones) @@ -109,8 +109,8 @@ def _authz_info(self, url: str) -> Dict[str, str]: """ return authzs information """ self.logger.debug('Authorization._authz_info()') - authz_name = string_sanitize(self.logger, url.replace('{0}{1}'.format(self.server_name, self.path_dic['authz_path']), '')) - self.logger.debug('Authorization._authz_info({0})'.format(authz_name)) + authz_name = string_sanitize(self.logger, url.replace(f'{self.server_name}{self.path_dic["authz_path"]}', '')) + self.logger.debug('Authorization._authz_info(%s)', authz_name) expires = uts_now() + self.validity token = generate_random_string(self.logger, 32) @@ -136,7 +136,7 @@ def _authz_info(self, url: str) -> Dict[str, str]: # get challenge-set authz_info_dic['challenges'] = self._challengeset_get(authz_info_dic, authz_name, token, tnauth, expires) - self.logger.debug('Authorization._authz_info() returns: {0}'.format(json.dumps(authz_info_dic))) + self.logger.debug('Authorization._authz_info() returns: %s', json.dumps(authz_info_dic)) return authz_info_dic def _config_load(self): @@ -150,23 +150,23 @@ def _config_load(self): try: self.validity = int(config_dic['Authorization']['validity']) except Exception: - self.logger.warning('Authorization._config_load(): failed to parse validity: {0}'.format(config_dic['Authorization']['validity'])) + self.logger.warning('Authorization._config_load(): failed to parse validity: %s', config_dic['Authorization']['validity']) if 'Directory' in config_dic and 'url_prefix' in config_dic['Directory']: self.path_dic = {k: config_dic['Directory']['url_prefix'] + v for k, v in self.path_dic.items()} self.logger.debug('Authorization._config_load() ended.') def invalidate(self, timestamp: int = None) -> Tuple[List[str], List[str]]: """ invalidate authorizations """ - self.logger.debug('Authorization.invalidate({0})'.format(timestamp)) + self.logger.debug('Authorization.invalidate(%s)', timestamp) if not timestamp: timestamp = uts_now() - self.logger.debug('Authorization.invalidate(): set timestamp to {0}'.format(timestamp)) + self.logger.debug('Authorization.invalidate(): set timestamp to %s', timestamp) field_list = ['id', 'name', 'expires', 'value', 'created_at', 'token', 'status__id', 'status__name', 'order__id', 'order__name'] try: authz_list = self.dbstore.authorizations_expired_search('expires', timestamp, vlist=field_list, operant='<=') except Exception as err_: - self.logger.critical('acme2certifier database error in Authorization.invalidate(): {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Authorization.invalidate(): %s', err_) authz_list = [] output_list = [] @@ -181,9 +181,9 @@ def invalidate(self, timestamp: int = None) -> Tuple[List[str], List[str]]: try: self.dbstore.authorization_update(data_dic) except Exception as err_: - self.logger.critical('acme2certifier database error in Authorization.invalidate(): {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Authorization.invalidate(): %s', err_) - self.logger.debug('Authorization.invalidate() ended: {0} authorizations identified'.format(len(output_list))) + self.logger.debug('Authorization.invalidate() ended: %s authorizations identified', len(output_list)) return (field_list, output_list) def new_get(self, url: str) -> Dict[str, str]: @@ -224,5 +224,5 @@ def new_post(self, content: str) -> Dict[str, str]: status_dic = {'code': code, 'type': message, 'detail': detail} response_dic = self.message.prepare_response(response_dic, status_dic) - self.logger.debug('Authorization.new_post() returns: {0}'.format(json.dumps(response_dic))) + self.logger.debug('Authorization.new_post() returns: %s', json.dumps(response_dic)) return response_dic diff --git a/acme_srv/certificate.py b/acme_srv/certificate.py index 644a8055..6e4d5c32 100644 --- a/acme_srv/certificate.py +++ b/acme_srv/certificate.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- -# pylint: disable=c0209, r0902, r0912, r0913, r0915 +# pylint: disable=r0902, r0912, r0913, r0915 """ certificate class """ from __future__ import print_function import json from typing import List, Tuple, Dict -from acme_srv.helper import b64_url_recode, generate_random_string, cert_san_get, cert_extensions_get, hooks_load, uts_now, uts_to_date_utc, date_to_uts_utc, load_config, csr_san_get, csr_extensions_get, cert_dates_get, ca_handler_load, error_dic_get, string_sanitize, pembundle_to_list, certid_asn1_get +from acme_srv.helper import b64_url_recode, generate_random_string, cert_cn_get, cert_san_get, cert_extensions_get, hooks_load, uts_now, uts_to_date_utc, date_to_uts_utc, load_config, csr_san_get, csr_extensions_get, cert_dates_get, ca_handler_load, error_dic_get, string_sanitize, pembundle_to_list, certid_asn1_get, cert_serial_get, cert_aki_get from acme_srv.db_handler import DBstore from acme_srv.message import Message from acme_srv.threadwithreturnvalue import ThreadWithReturnValue @@ -30,6 +30,7 @@ def __init__(self, debug: bool = False, srv_name: str = None, logger=None): self.tnauthlist_support = False self.cert_reusage_timeframe = 0 self.enrollment_timeout = 5 + self.cn2san_add = False def __enter__(self): """ Makes ACMEHandler a Context Manager """ @@ -41,12 +42,13 @@ def __exit__(self, *args): def _account_check(self, account_name: str, certificate: str) -> Dict[str, str]: """ check account """ - self.logger.debug('Certificate.issuer_check()') + self.logger.debug('Certificate._account_check()') try: result = self.dbstore.certificate_account_check(account_name, b64_url_recode(self.logger, certificate)) except Exception as err_: - self.logger.critical('acme2certifier database error in Certificate._account_check(): {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Certificate._account_check(): %s', err_) result = None + self.logger.debug('Certificate._account_check() ended with: %s', result) return result def _authz_check(self, identifier_dic: Dict[str, str], certificate: str) -> List[str]: @@ -67,16 +69,22 @@ def _authz_check(self, identifier_dic: Dict[str, str], certificate: str) -> List except Exception as err_: # enough to set identifier_list as empty list identifier_status = [] - self.logger.warning('Certificate._authorization_check() error while loading parsing certifcate. Error: {0}'.format(err_)) + self.logger.warning('Certificate._authorization_check() error while loading parsing certifcate. Error: %s', err_) else: try: # get sans san_list = cert_san_get(self.logger, certificate) + if self.cn2san_add: + # add common name to SANs + cert_cn = cert_cn_get(self.logger, certificate) + if not san_list and cert_cn: + san_list.append(f'DNS:{cert_cn}') + identifier_status = self._identifer_status_list(identifiers, san_list) except Exception as err_: # enough to set identifier_list as empty list identifier_status = [] - self.logger.warning('Certificate._authorization_check() error while loading parsing certifcate. Error: {0}'.format(err_)) + self.logger.warning('Certificate._authorization_check() error while loading parsing certifcate. Error: %s', err_) self.logger.debug('Certificate._authz_check() ended') return identifier_status @@ -92,7 +100,7 @@ def _authorization_check(self, order_name: str, certificate: str) -> bool: try: identifier_dic = self.dbstore.order_lookup('name', order_name, ['identifiers']) except Exception as err_: - self.logger.critical('acme2certifier database error in Certificate._authorization_check(): {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Certificate._authorization_check(): %s', err_) identifier_dic = {} if identifier_dic and 'identifiers' in identifier_dic: @@ -103,17 +111,17 @@ def _authorization_check(self, order_name: str, certificate: str) -> bool: if identifier_status and False not in identifier_status: result = True - self.logger.debug('Certificate._authorization_check() ended with {0}'.format(result)) + self.logger.debug('Certificate._authorization_check() ended with %s', result) return result def _cert_reusage_check(self, csr: str) -> Tuple[None, str, str, str]: """ check if an existing certificate an be reused """ - self.logger.debug('Certificate._cert_reusage_check({0})'.format(self.cert_reusage_timeframe)) + self.logger.debug('Certificate._cert_reusage_check(%s)', self.cert_reusage_timeframe) try: result_dic = self.dbstore.certificates_search('csr', csr, ('cert', 'cert_raw', 'expire_uts', 'issue_uts', 'created_at', 'id')) except Exception as err_: - self.logger.critical('acme2certifier database error in Certificate._cert_reusage_check(): {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Certificate._cert_reusage_check(): %s', err_) result_dic = None cert = None @@ -127,7 +135,7 @@ def _cert_reusage_check(self, csr: str) -> Tuple[None, str, str, str]: try: uts_create = date_to_uts_utc(certificate['created_at']) except Exception as _err: - self.logger.error('acme2certifier date_to_uts_utc() error in Certificate._cert_reusage_check(): id:{0}/created_at:{1}'.format(certificate['id'], certificate['created_at'])) + self.logger.error('acme2certifier date_to_uts_utc() error in Certificate._cert_reusage_check(): id:%s/created_at:%s', certificate['id'], certificate['created_at']) uts_create = 0 # check if there certificates within reusage timeframe @@ -136,10 +144,10 @@ def _cert_reusage_check(self, csr: str) -> Tuple[None, str, str, str]: if uts <= certificate['expire_uts']: cert = certificate['cert'] cert_raw = certificate['cert_raw'] - message = 'reused certificate from id: {0}'.format(certificate['id']) + message = f'reused certificate from id: {certificate["id"]}' break - self.logger.debug('Certificate._cert_reusage_check() ended with {0}'.format(message)) + self.logger.debug('Certificate._cert_reusage_check() ended with {%s', message) return (None, cert, cert_raw, message) def _config_hooks_load(self, config_dic: Dict[str, str]): @@ -153,7 +161,7 @@ def _config_hooks_load(self, config_dic: Dict[str, str]): # store handler in variable self.hooks = hooks_module.Hooks(self.logger) except Exception as err: - self.logger.critical('Certificate._config_load(): Hooks could not be loaded: {0}'.format(err)) + self.logger.critical('Certificate._config_load(): Hooks could not be loaded: %s', err) self.ignore_pre_hook_failure = config_dic.getboolean('Hooks', 'ignore_pre_hook_failure', fallback=False) self.ignore_post_hook_failure = config_dic.getboolean('Hooks', 'ignore_post_hook_failure', fallback=True) @@ -170,12 +178,12 @@ def _config_parameters_load(self, config_dic: Dict[str, str]): try: self.cert_reusage_timeframe = int(config_dic['Certificate']['cert_reusage_timeframe']) except Exception as err_: - self.logger.error('acme2certifier Certificate._config_load() cert_reusage_timout parsing error: {0}'.format(err_)) + self.logger.error('acme2certifier Certificate._config_load() cert_reusage_timout parsing error: %s', err_) if 'enrollment_timeout' in config_dic['Certificate']: try: self.enrollment_timeout = int(config_dic['Certificate']['enrollment_timeout']) except Exception as err_: - self.logger.error('acme2certifier Certificate._config_load() enrollment_timeout parsing error: {0}'.format(err_)) + self.logger.error('acme2certifier Certificate._config_load() enrollment_timeout parsing error: %s', err_) if 'Directory' in config_dic and 'url_prefix' in config_dic['Directory']: self.path_dic = {k: config_dic['Directory']['url_prefix'] + v for k, v in self.path_dic.items()} @@ -189,6 +197,10 @@ def _config_load(self): if 'Order' in config_dic: self.tnauthlist_support = config_dic.getboolean('Order', 'tnauthlist_support', fallback=False) + if 'CAhandler' in config_dic and config_dic.get('CAhandler', 'handler_file', fallback=None) == 'examples/ca_handler/asa_ca_handler.py': + self.cn2san_add = True + self.logger.debug('Certificate._config_load(): cn2san_add enabled') + # load ca_handler according to configuration ca_handler_module = ca_handler_load(self.logger, config_dic) @@ -204,7 +216,7 @@ def _config_load(self): # load parametrs self._config_parameters_load(config_dic) - self.logger.debug('ca_handler: {0}'.format(ca_handler_module)) + self.logger.debug('ca_handler: %s', ca_handler_module) self.logger.debug('Certificate._config_load() ended.') def _identifiers_load(self, identifier_dic: Dict[str, str], csr: str) -> List[str]: @@ -225,7 +237,7 @@ def _identifiers_load(self, identifier_dic: Dict[str, str], csr: str) -> List[st identifier_status = self._identifer_tnauth_list(identifier_dic, tnauthlist) except Exception as err_: identifier_status = [] - self.logger.warning('Certificate._csr_check() error while parsing csr.\nerror: {0}'.format(err_)) + self.logger.warning('Certificate._csr_check() error while parsing csr.\nerror: %s', err_) else: # get sans and compare identifiers against san try: @@ -233,9 +245,9 @@ def _identifiers_load(self, identifier_dic: Dict[str, str], csr: str) -> List[st identifier_status = self._identifer_status_list(identifiers, san_list) except Exception as err_: identifier_status = [] - self.logger.warning('Certificate._csr_check() error while checking csr.\nerror: {0}'.format(err_)) + self.logger.warning('Certificate._csr_check() error while checking csr.\nerror: %s', err_) - self.logger.debug('Certificate._identifiers_load() ended with {0}'.format(identifier_status)) + self.logger.debug('Certificate._identifiers_load() ended with %s', identifier_status) return identifier_status def _csr_check(self, certificate_name: str, csr: str) -> bool: @@ -244,7 +256,7 @@ def _csr_check(self, certificate_name: str, csr: str) -> bool: # fetch certificate dictionary from DB certificate_dic = self._info(certificate_name) - self.logger.debug('Certificate._info() ended with:{0}'.format(certificate_dic)) + self.logger.debug('Certificate._info() ended with:%s', certificate_dic) # empty list of statuses identifier_status = [] @@ -254,7 +266,7 @@ def _csr_check(self, certificate_name: str, csr: str) -> bool: try: identifier_dic = self.dbstore.order_lookup('name', certificate_dic['order'], ['identifiers']) except Exception as err_: - self.logger.critical('acme2certifier database error in Certificate._csr_check(): {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Certificate._csr_check(): %s', err_) identifier_dic = {} if identifier_dic and 'identifiers' in identifier_dic: @@ -265,10 +277,10 @@ def _csr_check(self, certificate_name: str, csr: str) -> bool: if identifier_status and False not in identifier_status: csr_check_result = True - self.logger.debug('Certificate._csr_check() ended with {0}'.format(csr_check_result)) + self.logger.debug('Certificate._csr_check() ended with %s', csr_check_result) return csr_check_result - def _enroll(self, csr: str, ca_handler: object) -> Tuple[str, str, str, str]: + def _enroll(self, csr: str) -> Tuple[str, str, str, str]: self.logger.debug('Certificate._enroll()') if self.cert_reusage_timeframe: (error, certificate, certificate_raw, poll_identifier) = self._cert_reusage_check(csr) @@ -278,7 +290,8 @@ def _enroll(self, csr: str, ca_handler: object) -> Tuple[str, str, str, str]: if not certificate or not certificate_raw: self.logger.debug('Certificate._enroll(): trigger enrollment') - (error, certificate, certificate_raw, poll_identifier) = ca_handler.enroll(csr) + with self.cahandler(self.debug, self.logger) as ca_handler: + (error, certificate, certificate_raw, poll_identifier) = ca_handler.enroll(csr) else: self.logger.info('Certificate._enroll(): reuse existing certificate') @@ -293,7 +306,7 @@ def _renewal_info_get(self, certificate: str) -> str: renewal_info_hex = certid_asn1_get(self.logger, certificate_list[0], certificate_list[1]) - self.logger.debug('Certificate.certid_asn1_get() ended with {0}'.format(renewal_info_hex)) + self.logger.debug('Certificate.certid_asn1_get() ended with %s', renewal_info_hex) return renewal_info_hex def _store(self, certificate: str, certificate_raw: str, poll_identifier: str, certificate_name: str, order_name: str, csr: str) -> Tuple[int, str]: @@ -309,33 +322,33 @@ def _store(self, certificate: str, certificate_raw: str, poll_identifier: str, c if self.hooks: try: self.hooks.success_hook(certificate_name, order_name, csr, certificate, certificate_raw, poll_identifier) - self.logger.debug('Certificate._enroll_and_store: success_hook successful') + self.logger.debug('Certificate._store: success_hook successful') except Exception as err: - self.logger.error('Certificate._enroll_and_store: success_hook exception: {0}'.format(err)) + self.logger.error('Certificate._store: success_hook exception: %s', err) if not self.ignore_success_hook_failure: error = (None, 'success_hook_error', str(err)) except Exception as err_: result = None - self.logger.critical('acme2certifier database error in Certificate._enroll_and_store(): {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Certificate._store(): %s', err_) self.logger.error('Certificate._store() ended') return (result, error) def _enrollerror_handler(self, error: str, poll_identifier: str, order_name: str, certificate_name: str) -> Tuple[None, str, str]: """ store error message for later analysis """ - self.logger.error('Certificate._enroll_and_store({0})'.format(error)) + self.logger.debug('Certificate._enrollerror_handler(%s)', error) result = None detail = None try: if not poll_identifier: - self.logger.debug('Certificate._enroll_and_store(): invalidating order as there is no certificate and no poll_identifier: {0}/{1}'.format(error, order_name)) + self.logger.debug('Certificate._enrollerror_handler(): invalidating order as there is no certificate and no poll_identifier: %s/%s', error, order_name) self._order_update({'name': order_name, 'status': 'invalid'}) self._store_cert_error(certificate_name, error, poll_identifier) except Exception as err_: result = None - self.logger.critical('acme2certifier database error in Certificate._enroll_and_store() _store_cert_error: {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Certificate._enrollerror_handler() _store_cert_error: %s', err_) # cover polling cases if poll_identifier: @@ -343,43 +356,43 @@ def _enrollerror_handler(self, error: str, poll_identifier: str, order_name: str else: error = self.err_msg_dic['serverinternal'] - self.logger.error('Certificate._enroll_and_store() ended with: {0}'.format(result)) + self.logger.debug('Certificate._enrollerror_handler() ended with: %s', result) return (result, error, detail) def _pre_hooks_process(self, certificate_name: str, order_name: str, csr: str) -> List[str]: - self.logger.debug('Certificate._pre_hooks_process({0}, {1})'.format(certificate_name, order_name)) + self.logger.debug('Certificate._pre_hooks_process(%s, %s)', certificate_name, order_name) hook_error = [] if self.hooks: try: self.hooks.pre_hook(certificate_name, order_name, csr) - self.logger.debug('Certificate._enroll_and_store(): pre_hook successful') + self.logger.debug('Certificate._pre_hooks_process(): pre_hook successful') except Exception as err: - self.logger.error('Certificate._enroll_and_store(): pre_hook exception: {0}'.format(err)) + self.logger.error('Certificate._pre_hooks_process(): pre_hook exception: %s', err) if not self.ignore_pre_hook_failure: hook_error = (None, 'pre_hook_error', str(err)) - self.logger.debug('Certificate._pre_hooks_process({0})'.format(hook_error)) + self.logger.debug('Certificate._pre_hooks_process(%s)', hook_error) return hook_error def _post_hooks_process(self, certificate_name: str, order_name: str, csr: str, error: str) -> List[str]: - self.logger.debug('Certificate._pre_hooks_process({0}, {1})'.format(certificate_name, order_name)) + self.logger.debug('Certificate._post_hooks_process(%s, %s', certificate_name, order_name) hook_error = [] if self.hooks: try: self.hooks.post_hook(certificate_name, order_name, csr, error) - self.logger.debug('Certificate._enroll_and_store(): post_hook successful') + self.logger.debug('Certificate._post_hooks_process(): post_hook successful') except Exception as err: - self.logger.error('Certificate._enroll_and_store(): post_hook exception: {0}'.format(err)) + self.logger.error('Certificate._post_hooks_process(): post_hook exception: %s', err) if not self.ignore_post_hook_failure: hook_error = (None, 'post_hook_error', str(err)) - self.logger.debug('Certificate._post_hooks_process({0})'.format(hook_error)) + self.logger.debug('Certificate._post_hooks_process(%s)', hook_error) return hook_error def _enroll_and_store(self, certificate_name: str, csr: str, order_name: str = None) -> Tuple[str, str, str]: """ enroll and store certificate """ - self.logger.debug('Certificate._enroll_and_store({0}, {1}, {2})'.format(certificate_name, order_name, csr)) + self.logger.debug('Certificate._enroll_and_store(%s, %s, %s)', certificate_name, order_name, csr) detail = None error = None @@ -388,29 +401,27 @@ def _enroll_and_store(self, certificate_name: str, csr: str, order_name: str = N if hook_error: return hook_error - with self.cahandler(self.debug, self.logger) as ca_handler: + # enroll certificate + (error, certificate, certificate_raw, poll_identifier) = self._enroll(csr) - # enroll certificate - (error, certificate, certificate_raw, poll_identifier) = self._enroll(csr, ca_handler) - - if certificate: - (result, error) = self._store(certificate, certificate_raw, poll_identifier, certificate_name, order_name, csr) - if error: - return error - else: - self.logger.error('acme2certifier enrollment error: {0}'.format(error)) - (result, error, detail) = self._enrollerror_handler(error, poll_identifier, order_name, certificate_name) + if certificate: + (result, error) = self._store(certificate, certificate_raw, poll_identifier, certificate_name, order_name, csr) + if error: + return error + else: + self.logger.error('acme2certifier enrollment error: %s', error) + (result, error, detail) = self._enrollerror_handler(error, poll_identifier, order_name, certificate_name) hook_error = self._post_hooks_process(certificate_name, order_name, csr, error) if hook_error: return hook_error - self.logger.debug('Certificate._enroll_and_store() ended with: {0}:{1}'.format(result, error)) + self.logger.debug('Certificate._enroll_and_store() ended with: %s:%s', result, error) return (result, error, detail) def _identifier_chk(self, cert_type: str, cert_value: str, identifiers: List[str], san_is_in: bool) -> bool: """ check identifier """ - self.logger.debug('Certificate._identifier_chk({0}/{1})'.format(cert_type, cert_value)) + self.logger.debug('Certificate._identifier_chk(%s/%s)', cert_type, cert_value) if cert_type and cert_value: for identifier in identifiers: @@ -419,7 +430,7 @@ def _identifier_chk(self, cert_type: str, cert_value: str, identifiers: List[str san_is_in = True break - self.logger.debug('Certificate._identifier_chk({0})'.format(san_is_in)) + self.logger.debug('Certificate._identifier_chk(%s)', san_is_in) return san_is_in def _identifer_status_list(self, identifiers: List[str], san_list: List[str]) -> List[str]: @@ -432,25 +443,25 @@ def _identifer_status_list(self, identifiers: List[str], san_list: List[str]) -> try: (cert_type, cert_value) = san.lower().split(':', 1) except Exception as err_: - self.logger.error('Error while splitting san {0}: {1}'.format(san, err_)) + self.logger.error('Error while splitting san %s: %s', san, err_) cert_type = None cert_value = None # check identifiers san_is_in = self._identifier_chk(cert_type, cert_value, identifiers, san_is_in) - self.logger.debug('SAN check for {0} against identifiers returned {1}'.format(san.lower(), san_is_in)) + self.logger.debug('SAN check for %s against identifiers returned %s', san.lower(), san_is_in) identifier_status.append(san_is_in) if not identifier_status: identifier_status.append(False) - self.logger.debug('Certificate._identifer_status_list() ended with {0}'.format(identifier_status)) + self.logger.debug('Certificate._identifer_status_list() ended with %s', identifier_status) return identifier_status def _identifier_tnauth_chk(self, identifier: Dict[str, str], tnauthlist: List[str]) -> bool: """ check tnauth identifier against tnauthlist """ - self.logger.debug('Certificate._identifier_tnauth_chk({0})'.format(identifier)) + self.logger.debug('Certificate._identifier_tnauth_chk(%s)', identifier) result = False # get the tnauthlist identifier @@ -459,7 +470,7 @@ def _identifier_tnauth_chk(self, identifier: Dict[str, str], tnauthlist: List[st if 'value' in identifier and identifier['value'] in tnauthlist: result = True - self.logger.debug('Certificate._identifier_tnauth_chk() endedt with {0}'.format(result)) + self.logger.debug('Certificate._identifier_tnauth_chk() endedt with %s', result) return result def _identifer_tnauth_list(self, identifier_dic: Dict[str, str], tnauthlist: List[str]): @@ -481,16 +492,16 @@ def _identifer_tnauth_list(self, identifier_dic: Dict[str, str], tnauthlist: Lis else: identifier_status.append(False) - self.logger.debug('Certificate._identifer_tnauth_list() ended with {0}'.format(identifier_status)) + self.logger.debug('Certificate._identifer_tnauth_list() ended with %s', identifier_status) return identifier_status def _info(self, certificate_name: str, flist: List[str] = ('name', 'csr', 'cert', 'order__name')) -> Dict[str, str]: """ get certificate from database """ - self.logger.debug('Certificate._info({0})'.format(certificate_name)) + self.logger.debug('Certificate._info(%s)', certificate_name) try: result = self.dbstore.certificate_lookup('name', certificate_name, flist) except Exception as err_: - self.logger.critical('acme2certifier database error in Certificate._info(): {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Certificate._info(): %s', err_) result = None return result @@ -535,13 +546,13 @@ def _expiredate_get(self, cert: Dict[str, str], timestamp: int, to_be_cleared: b # expired based on expire_uts from db to_be_cleared = True - self.logger.debug('Certificate._expiredate_get() ended with: to_be_cleared: {0}'.format(to_be_cleared)) + self.logger.debug('Certificate._expiredate_get() ended with: to_be_cleared: %s', to_be_cleared) return to_be_cleared def _invalidation_check(self, cert: Dict[str, str], timestamp: int, purge: bool = False): """ check if cert must be invalidated """ if 'name' in cert: - self.logger.debug('Certificate._invalidation_check({0})'.format(cert['name'])) + self.logger.debug('Certificate._invalidation_check(%s)', cert['name']) else: self.logger.debug('Certificate._invalidation_check()') @@ -564,23 +575,23 @@ def _invalidation_check(self, cert: Dict[str, str], timestamp: int, purge: bool to_be_cleared = True if 'name' in cert: - self.logger.debug('Certificate._invalidation_check({0}) ended with {1}'.format(cert['name'], to_be_cleared)) + self.logger.debug('Certificate._invalidation_check(%s) ended with %s', cert['name'], to_be_cleared) else: - self.logger.debug('Certificate._invalidation_check() ended with {0}'.format(to_be_cleared)) + self.logger.debug('Certificate._invalidation_check() ended with %s', to_be_cleared) return (to_be_cleared, cert) def _order_update(self, data_dic: Dict[str, str]): """ update order based on ordername """ - self.logger.debug('Certificate._order_update({0})'.format(data_dic)) + self.logger.debug('Certificate._order_update(%s)', data_dic) try: self.dbstore.order_update(data_dic) except Exception as err_: - self.logger.critical('acme2certifier database error in Certificate._order_update(): {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Certificate._order_update(): %s', err_) def _revocation_reason_check(self, reason: str) -> str: """ check reason """ - self.logger.debug('Certificate._revocation_reason_check({0})'.format(reason)) + self.logger.debug('Certificate._revocation_reason_check(%s)', reason) # taken from https://tools.ietf.org/html/rfc5280#section-5.3.1 allowed_reasons = { @@ -597,12 +608,12 @@ def _revocation_reason_check(self, reason: str) -> str: } result = allowed_reasons.get(reason, None) - self.logger.debug('Certificate._revocation_reason_check() ended with {0}'.format(result)) + self.logger.debug('Certificate._revocation_reason_check() ended with %s', result) return result def _revocation_request_validate(self, account_name: str, payload: Dict[str, str]) -> Tuple[int, str]: """ check revocaton request for consistency""" - self.logger.debug('Certificate._revocation_request_validate({0})'.format(account_name)) + self.logger.debug('Certificate._revocation_request_validate(%s)', account_name) # set a value to avoid that we are returning none by accident code = 400 @@ -634,34 +645,36 @@ def _revocation_request_validate(self, account_name: str, payload: Dict[str, str else: error = self.err_msg_dic['unauthorized'] - self.logger.debug('Certificate._revocation_request_validate() ended with: {0}, {1}'.format(code, error)) + self.logger.debug('Certificate._revocation_request_validate() ended with: %s, %s', code, error) return (code, error) def _store_cert(self, certificate_name: str, certificate: str, raw: str, issue_uts: int = 0, expire_uts: int = 0, poll_identifier: str = None) -> int: """ get key for a specific account id """ - self.logger.debug('Certificate._store_cert({0})'.format(certificate_name)) + self.logger.debug('Certificate._store_cert(%s)', certificate_name) renewal_info_hex = self._renewal_info_get(certificate) + serial = cert_serial_get(self.logger, raw, hexformat=True) + aki = cert_aki_get(self.logger, raw) - data_dic = {'cert': certificate, 'name': certificate_name, 'cert_raw': raw, 'issue_uts': issue_uts, 'expire_uts': expire_uts, 'poll_identifier': poll_identifier, 'renewal_info': renewal_info_hex} + data_dic = {'cert': certificate, 'name': certificate_name, 'cert_raw': raw, 'issue_uts': issue_uts, 'expire_uts': expire_uts, 'poll_identifier': poll_identifier, 'renewal_info': renewal_info_hex, 'serial': serial, 'aki': aki} try: cert_id = self.dbstore.certificate_add(data_dic) except Exception as err_: cert_id = None - self.logger.critical('acme2certifier database error in Certificate._store_cert(): {0}'.format(err_)) - self.logger.debug('Certificate._store_cert({0}) ended'.format(cert_id)) + self.logger.critical('acme2certifier database error in Certificate._store_cert(): %s', err_) + self.logger.debug('Certificate._store_cert(%s) ended', cert_id) return cert_id def _store_cert_error(self, certificate_name: str, error: str, poll_identifier: str) -> int: """ get key for a specific account id """ - self.logger.debug('Certificate._store_cert_error({0})'.format(certificate_name)) + self.logger.debug('Certificate._store_cert_error(%s)', certificate_name) data_dic = {'error': error, 'name': certificate_name, 'poll_identifier': poll_identifier} try: cert_id = self.dbstore.certificate_add(data_dic) except Exception as err_: cert_id = None - self.logger.critical('acme2certifier database error in Certificate._store_cert(): {0}'.format(err_)) - self.logger.debug('Certificate._store_cert_error({0}) ended'.format(cert_id)) + self.logger.critical('acme2certifier database error in Certificate._store_cert(): %s', err_) + self.logger.debug('Certificate._store_cert_error(%s) ended', cert_id) return cert_id def _tnauth_identifier_check(self, identifier_dic: Dict[str, str]) -> int: @@ -674,22 +687,22 @@ def _tnauth_identifier_check(self, identifier_dic: Dict[str, str]) -> int: if 'type' in identifier: if identifier['type'].lower() == 'tnauthlist': tnauthlist_identifer_in = True - self.logger.debug('Certificate._tnauth_identifier_check() ended with: {0}'.format(tnauthlist_identifer_in)) + self.logger.debug('Certificate._tnauth_identifier_check() ended with: %s', tnauthlist_identifer_in) return tnauthlist_identifer_in def certlist_search(self, key: str, value: str, vlist: List[str] = ('name', 'csr', 'cert', 'order__name')) -> Dict[str, str]: """ get certificate from database """ - self.logger.debug('Certificate.certlist_search({0}: {1})'.format(key, value)) + self.logger.debug('Certificate.certlist_search(%s: %s)', key, value) try: result = self.dbstore.certificates_search(key, value, vlist) except Exception as err_: - self.logger.critical('acme2certifier database error in Certificate.certlist_search(): {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Certificate.certlist_search(): %s', err_) result = None return result def _cleanup(self, report_list: List[str], timestamp: int, purge: bool): """ cleanup """ - self.logger.debug('Certificate.cleanup({0},{1})'.format(timestamp, purge)) + self.logger.debug('Certificate.cleanup(%s,%s)', timestamp, purge) if not purge: # we are just modifiying data for cert in report_list: @@ -697,26 +710,26 @@ def _cleanup(self, report_list: List[str], timestamp: int, purge: bool): 'name': cert['name'], 'expire_uts': cert['expire_uts'], 'issue_uts': cert['issue_uts'], - 'cert': 'removed by certificates.cleanup() on {0} '.format(uts_to_date_utc(timestamp)), + 'cert': f'removed by certificates.cleanup() on {uts_to_date_utc(timestamp)}', 'cert_raw': cert['cert_raw'] } try: self.dbstore.certificate_add(data_dic) except Exception as err_: - self.logger.critical('acme2certifier database error in Certificate.cleanup() add: {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Certificate.cleanup() add: %s', err_) else: # delete entries from certificates table for cert in report_list: try: self.dbstore.certificate_delete('id', cert['id']) except Exception as err_: - self.logger.critical('acme2certifier database error in Certificate.cleanup() delete: {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Certificate.cleanup() delete: %s', err_) self.logger.debug('Certificate.cleanup() ended') def cleanup(self, timestamp: int = None, purge: bool = False) -> Tuple[List[str], List[str]]: """ cleanup routine to shrink table-size """ - self.logger.debug('Certificate.cleanup({0},{1})'.format(timestamp, purge)) + self.logger.debug('Certificate.cleanup(%s,%s)', timestamp, purge) field_list = ['id', 'name', 'expire_uts', 'issue_uts', 'cert', 'cert_raw', 'csr', 'created_at', 'order__id', 'order__name'] @@ -724,7 +737,7 @@ def cleanup(self, timestamp: int = None, purge: bool = False) -> Tuple[List[str] try: certificate_list = self.dbstore.certificates_search('expire_uts', timestamp, field_list, '<=') except Exception as err_: - self.logger.critical('acme2certifier database error in Certificate.cleanup() search: {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Certificate.cleanup() search: %s', err_) certificate_list = [] report_list = [] @@ -737,7 +750,7 @@ def cleanup(self, timestamp: int = None, purge: bool = False) -> Tuple[List[str] # cleanup self._cleanup(report_list, timestamp, purge) - self.logger.debug('Certificate.cleanup() ended with: {0} certs'.format(len(report_list))) + self.logger.debug('Certificate.cleanup() ended with: %s certs', len(report_list)) return (field_list, report_list) def _dates_update(self, cert: Dict[str, str]): @@ -759,7 +772,7 @@ def dates_update(self): with Certificate(self.debug, None, self.logger) as certificate: cert_list = certificate.certlist_search('issue_uts', 0, vlist=('id', 'name', 'cert', 'cert_raw', 'issue_uts', 'expire_uts')) - self.logger.debug('Got {0} certificates to be updated...'.format(len(cert_list))) + self.logger.debug('Got {%s} certificates to be updated...', len(cert_list)) for cert in cert_list: self._dates_update(cert) @@ -767,7 +780,7 @@ def dates_update(self): def enroll_and_store(self, certificate_name: str, csr: str, order_name: str = None) -> Tuple[str, str]: """ check csr and trigger enrollment """ - self.logger.debug('Certificate.enroll_and_store({0},{1})'.format(certificate_name, order_name)) + self.logger.debug('Certificate.enroll_and_store(%s, %s)', certificate_name, order_name) # check csr against order csr_check_result = self._csr_check(certificate_name, csr) @@ -775,13 +788,15 @@ def enroll_and_store(self, certificate_name: str, csr: str, order_name: str = No # only continue if self.csr_check returned True if csr_check_result: twrv = ThreadWithReturnValue(target=self._enroll_and_store, args=(certificate_name, csr, order_name)) + twrv.daemon = True twrv.start() enroll_result = twrv.join(timeout=self.enrollment_timeout) + self.logger.debug('Certificate.enroll_and_store() ThreadWithReturnValue ended') if enroll_result: try: (result, error, detail) = enroll_result except Exception as err_: - self.logger.error('acme2certifier database error in Certificate.enroll_and_store(): split of {0} failed with err: {1}'.format(enroll_result, err_)) + self.logger.error('acme2certifier database error in Certificate.enroll_and_store(): split of %s failed with err: %s', enroll_result, err_) result = None error = self.err_msg_dic['serverinternal'] detail = 'unexpected enrollment result' @@ -794,13 +809,14 @@ def enroll_and_store(self, certificate_name: str, csr: str, order_name: str = No error = self.err_msg_dic['badcsr'] detail = 'CSR validation failed' - self.logger.debug('Certificate.enroll_and_store() ended with: {0}:{1}'.format(result, error)) + self.logger.debug('Certificate.enroll_and_store() ended with: %s:%s', result, error) return (error, detail) def new_get(self, url: str) -> Dict[str, str]: """ get request """ - certificate_name = string_sanitize(self.logger, url.replace('{0}{1}'.format(self.server_name, self.path_dic['cert_path']), '')) - self.logger.debug('Certificate.new_get({0})'.format(certificate_name)) + certificate_name = string_sanitize(self.logger, url.replace(f'{self.server_name}{self.path_dic["cert_path"]}', '')) + self.logger.debug('Certificate.new_get(%s)', certificate_name) + # fetch certificate dictionary from DB certificate_dic = self._info(certificate_name, ['name', 'csr', 'cert', 'order__name', 'order__status_id']) response_dic = {} @@ -818,7 +834,7 @@ def new_get(self, url: str) -> Dict[str, str]: response_dic['data'] = self.err_msg_dic['serverinternal'] elif certificate_dic['order__status_id'] == 4: # order status is processing - ratelimiting - response_dic['header'] = {'Retry-After': '{0}'.format(self.retry_after)} + response_dic['header'] = {'Retry-After': f'{self.retry_after}'} response_dic['code'] = 403 response_dic['data'] = self.err_msg_dic['ratelimited'] else: @@ -828,13 +844,12 @@ def new_get(self, url: str) -> Dict[str, str]: response_dic['code'] = 500 response_dic['data'] = self.err_msg_dic['serverinternal'] - self.logger.debug('Certificate.new_get({0}) ended'.format(response_dic['code'])) - + self.logger.debug('Certificate.new_get(%s) ended', response_dic['code']) return response_dic def new_post(self, content: str) -> Dict[str, str]: """ post request """ - self.logger.debug('Certificate.new_post({0})') + self.logger.debug('Certificate.new_post()') response_dic = {} # check message @@ -867,7 +882,7 @@ def new_post(self, content: str) -> Dict[str, str]: else: result = 'no code found' - self.logger.debug('Certificate.new_post() ended with: {0}'.format(result)) + self.logger.debug('Certificate.new_post() ended with: %s', result) return response_dic def revoke(self, content: str) -> Dict[str, str]: @@ -901,12 +916,12 @@ def revoke(self, content: str) -> Dict[str, str]: status_dic = {'code': code, 'type': message, 'detail': detail} response_dic = self.message.prepare_response(response_dic, status_dic) - self.logger.debug('Certificate.revoke() ended with: {0}'.format(response_dic)) + self.logger.debug('Certificate.revoke() ended with: %s', response_dic) return response_dic def poll(self, certificate_name: str, poll_identifier: str, csr: str, order_name: str) -> int: """ try to fetch a certificate from CA and store it into database """ - self.logger.debug('Certificate.poll({0}: {1})'.format(certificate_name, poll_identifier)) + self.logger.debug('Certificate.poll(%s: %s)', certificate_name, poll_identifier) with self.cahandler(self.debug, self.logger) as ca_handler: (error, certificate, certificate_raw, poll_identifier, rejected) = ca_handler.poll(certificate_name, poll_identifier, csr) @@ -919,7 +934,7 @@ def poll(self, certificate_name: str, poll_identifier: str, csr: str, order_name try: self.dbstore.order_update({'name': order_name, 'status': 'valid'}) except Exception as err_: - self.logger.critical('acme2certifier database error in Certificate.poll(): {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Certificate.poll(): %s', err_) else: # store error message for later analysis self._store_cert_error(certificate_name, error, poll_identifier) @@ -928,18 +943,19 @@ def poll(self, certificate_name: str, poll_identifier: str, csr: str, order_name try: self.dbstore.order_update({'name': order_name, 'status': 'invalid'}) except Exception as err_: - self.logger.critical('acme2certifier database error in Certificate.poll(): {0}'.format(err_)) - self.logger.debug('Certificate.poll({0}: {1})'.format(certificate_name, poll_identifier)) + self.logger.critical('acme2certifier database error in Certificate.poll(): %s', err_) + self.logger.debug('Certificate.poll(%s: %s)', certificate_name, poll_identifier) return _result def store_csr(self, order_name: str, csr: str, header_info: str) -> str: """ store csr into database """ - self.logger.debug('Certificate.store_csr({0})'.format(order_name)) + self.logger.debug('Certificate.store_csr(%s)', order_name) + certificate_name = generate_random_string(self.logger, 12) data_dic = {'order': order_name, 'csr': csr, 'name': certificate_name, 'header_info': header_info} try: self.dbstore.certificate_add(data_dic) except Exception as err_: - self.logger.critical('Database error in Certificate.store_csr(): {0}'.format(err_)) + self.logger.critical('Database error in Certificate.store_csr(): %s', err_) self.logger.debug('Certificate.store_csr() ended') return certificate_name diff --git a/acme_srv/challenge.py b/acme_srv/challenge.py index a3ca2143..29327c13 100644 --- a/acme_srv/challenge.py +++ b/acme_srv/challenge.py @@ -1,8 +1,9 @@ # -*- coding: utf-8 -*- """ Challenge class """ -# pylint: disable=C0209, r0913 +# pylint: disable=r0913 from __future__ import print_function import json +import time from typing import List, Tuple, Dict from acme_srv.helper import generate_random_string, parse_url, load_config, jwk_thumbprint_get, url_get, sha256_hash, sha256_hash_hex, b64_encode, b64_url_encode, txt_get, fqdn_resolve, uts_now, uts_to_date_utc, servercert_get, cert_san_get, cert_extensions_get, fqdn_in_san_check, proxy_check, error_dic_get, ip_validate from acme_srv.db_handler import DBstore @@ -23,6 +24,7 @@ def __init__(self, debug: bool = False, srv_name: str = None, logger: object = N self.expiry = expiry self.challenge_validation_disable = False self.challenge_validation_timeout = 10 + self.dns_validation_pause_timer = 0.5 self.tnauthlist_support = False self.sectigo_sim = False self.dns_server_list = None @@ -43,7 +45,7 @@ def _challengelist_search(self, key: str, value: str, vlist: List = ('name', 'ty try: challenge_list = self.dbstore.challenges_search(key, value, vlist) except Exception as err_: - self.logger.critical('acme2certifier database error in Challenge._challengelist_search(): {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Challenge._challengelist_search(): %s', err_) challenge_list = [] challenge_dic = {} @@ -54,7 +56,7 @@ def _challengelist_search(self, key: str, value: str, vlist: List = ('name', 'ty challenge_dic[challenge['type']]['token'] = challenge['token'] challenge_dic[challenge['type']]['type'] = challenge['type'] challenge_dic[challenge['type']]['url'] = challenge['name'] - challenge_dic[challenge['type']]['url'] = '{0}{1}{2}'.format(self.server_name, self.path_dic['chall_path'], challenge['name']) + challenge_dic[challenge['type']]['url'] = f"{self.server_name}{self.path_dic['chall_path']}{challenge['name']}" challenge_dic[challenge['type']]['name'] = challenge['name'] if 'status__name' in challenge: challenge_dic[challenge['type']]['status'] = challenge['status__name'] @@ -63,49 +65,64 @@ def _challengelist_search(self, key: str, value: str, vlist: List = ('name', 'ty for challenge, challenge_items in challenge_dic.items(): challenge_list.append(challenge_items) - self.logger.debug('Challenge._challengelist_search() ended with: {0}'.format(challenge_list)) + self.logger.debug('Challenge._challengelist_search() ended with: %s', challenge_list) return challenge_list + def _challenge_validate_loop(self, challenge_name: str, challenge_dic: Dict[str, str], payload: Dict[str, str], jwk_thumbprint: str) -> Tuple[bool, bool]: + """ inner loop function to validate challenges """ + self.logger.debug('Challenge._challenge_validate_loop(%s)', challenge_name) + + if challenge_dic['type'] == 'http-01' and jwk_thumbprint: + (result, invalid) = self._validate_http_challenge(challenge_name, challenge_dic['authorization__type'], challenge_dic['authorization__value'], challenge_dic['token'], jwk_thumbprint) + elif challenge_dic['type'] == 'dns-01' and jwk_thumbprint: + (result, invalid) = self._validate_dns_challenge(challenge_name, challenge_dic['authorization__type'], challenge_dic['authorization__value'], challenge_dic['token'], jwk_thumbprint) + elif challenge_dic['type'] == 'tls-alpn-01' and jwk_thumbprint: + (result, invalid) = self._validate_alpn_challenge(challenge_name, challenge_dic['authorization__type'], challenge_dic['authorization__value'], challenge_dic['token'], jwk_thumbprint) + elif challenge_dic['type'] == 'tkauth-01' and jwk_thumbprint and self.tnauthlist_support: + (result, invalid) = self._validate_tkauth_challenge(challenge_name, challenge_dic['authorization__type'], challenge_dic['authorization__value'], challenge_dic['token'], jwk_thumbprint, payload) + else: + self.logger.error('unknown challenge type "%s". Setting check result to False', challenge_dic['type']) + result = False + invalid = True + + self.logger.debug('Challenge._challenge_validate_loop() ended with: %s/%s', result, invalid) + return (result, invalid) + def _challenge_validate(self, pub_key: Dict[str, str], challenge_name: str, challenge_dic: Dict[str, str], payload: Dict[str, str]) -> Tuple[bool, bool]: """ challenge validate """ - self.logger.debug('Challenge._challenge_validate({0})'.format(challenge_name)) + self.logger.debug('Challenge._challenge_validate(%s)', challenge_name) jwk_thumbprint = jwk_thumbprint_get(self.logger, pub_key) + for _ele in range(0, 5): - if challenge_dic['type'] == 'http-01' and jwk_thumbprint: - (result, invalid) = self._validate_http_challenge(challenge_name, challenge_dic['authorization__type'], challenge_dic['authorization__value'], challenge_dic['token'], jwk_thumbprint) - elif challenge_dic['type'] == 'dns-01' and jwk_thumbprint: - (result, invalid) = self._validate_dns_challenge(challenge_name, challenge_dic['authorization__type'], challenge_dic['authorization__value'], challenge_dic['token'], jwk_thumbprint) - elif challenge_dic['type'] == 'tls-alpn-01' and jwk_thumbprint: - (result, invalid) = self._validate_alpn_challenge(challenge_name, challenge_dic['authorization__type'], challenge_dic['authorization__value'], challenge_dic['token'], jwk_thumbprint) - elif challenge_dic['type'] == 'tkauth-01' and jwk_thumbprint and self.tnauthlist_support: - (result, invalid) = self._validate_tkauth_challenge(challenge_name, challenge_dic['authorization__type'], challenge_dic['authorization__value'], challenge_dic['token'], jwk_thumbprint, payload) - else: - self.logger.error('unknown challenge type "{0}". Setting check result to False'.format(challenge_dic['type'])) - result = False - invalid = True + + result, invalid = self._challenge_validate_loop(challenge_name, challenge_dic, payload, jwk_thumbprint) + # pylint: disable=r1723 if result or invalid: # break loop if we got any good or bad response break + elif challenge_dic['type'] == 'dns-01' and jwk_thumbprint: + # sleep for a while before we try again + time.sleep(self.dns_validation_pause_timer) - self.logger.debug('Challenge._challenge_validate() ended with: {0}/{1}'.format(result, invalid)) + self.logger.debug('Challenge._challenge_validate() ended with: %s/%s', result, invalid) return (result, invalid) def _check(self, challenge_name: str, payload: Dict[str, str]) -> Tuple[bool, bool]: """ challenge check """ - self.logger.debug('Challenge._check({0})'.format(challenge_name)) + self.logger.debug('Challenge._check(%s)', challenge_name) try: challenge_dic = self.dbstore.challenge_lookup('name', challenge_name, ['type', 'status__name', 'token', 'authorization__name', 'authorization__type', 'authorization__value', 'authorization__token', 'authorization__order__account__name']) except Exception as err_: - self.logger.critical('acme2certifier database error in Challenge._check() lookup: {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Challenge._check() lookup: %s', err_) challenge_dic = {} if 'type' in challenge_dic and 'authorization__value' in challenge_dic and 'token' in challenge_dic and 'authorization__order__account__name' in challenge_dic: try: pub_key = self.dbstore.jwk_load(challenge_dic['authorization__order__account__name']) except Exception as err_: - self.logger.critical('acme2certifier database error in Challenge._check() jwk: {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Challenge._check() jwk: %s', err_) pub_key = None if pub_key: @@ -117,7 +134,7 @@ def _check(self, challenge_name: str, payload: Dict[str, str]) -> Tuple[bool, bo result = False invalid = False - self.logger.debug('challenge._check() ended with: {0}/{1}'.format(result, invalid)) + self.logger.debug('challenge._check() ended with: %s/%s', result, invalid) return (result, invalid) def _existing_challenge_validate(self, challenge_list: List[str]) -> Dict[str, str]: @@ -134,11 +151,11 @@ def _existing_challenge_validate(self, challenge_list: List[str]) -> Dict[str, s def _info(self, challenge_name): """ get challenge details """ - self.logger.debug('Challenge._info({0})'.format(challenge_name)) + self.logger.debug('Challenge._info(%s)', challenge_name) try: challenge_dic = self.dbstore.challenge_lookup('name', challenge_name, vlist=('type', 'token', 'status__name', 'validated')) except Exception as err_: - self.logger.critical('acme2certifier database error in Challenge._info(): {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Challenge._info(): %s', err_) challenge_dic = {} if 'status' in challenge_dic and challenge_dic['status'] == 'valid': @@ -152,7 +169,7 @@ def _info(self, challenge_name): if 'validated' in challenge_dic: challenge_dic.pop('validated') - self.logger.debug('Challenge._info({0}) ended'.format(challenge_name)) + self.logger.debug('Challenge._info(%s) ended', challenge_name) return challenge_dic def _config_proxy_load(self, config_dic: Dict[str, str]): @@ -163,10 +180,28 @@ def _config_proxy_load(self, config_dic: Dict[str, str]): try: self.proxy_server_list = json.loads(config_dic['DEFAULT']['proxy_server_list']) except Exception as err_: - self.logger.warning('Challenge._config_load() proxy_server_list failed with error: {0}'.format(err_)) + self.logger.warning('Challenge._config_load() proxy_server_list failed with error: %s', err_) self.logger.debug('Challenge._config_proxy_load() ended') + def _config_dns_load(self, config_dic: Dict[str, str]): + """ load dns config """ + self.logger.debug('Challenge._config_dns_load()') + + if 'Challenge' in config_dic and 'dns_server_list' in config_dic['Challenge']: + try: + self.dns_server_list = json.loads(config_dic['Challenge']['dns_server_list']) + except Exception as err_: + self.logger.warning('Challenge._config_load() dns_server_list failed with error: %s', err_) + + if 'dns_validation_pause_timer' in config_dic['Challenge']: + try: + self.dns_validation_pause_timer = int(config_dic['Challenge']['dns_validation_pause_timer']) + except Exception as err_: + self.logger.warning('Challenge._config_load() failed to load dns_validation_pause_timer: %s', err_) + + self.logger.debug('Challenge._config_dns_load() ended') + def _config_challenge_load(self, config_dic: Dict[str, str]): """ load proxy config """ self.logger.debug('Challenge._config_challenge_load()') @@ -174,16 +209,12 @@ def _config_challenge_load(self, config_dic: Dict[str, str]): if 'Challenge' in config_dic: self.challenge_validation_disable = config_dic.getboolean('Challenge', 'challenge_validation_disable', fallback=False) self.sectigo_sim = config_dic.getboolean('Challenge', 'sectigo_sim', fallback=False) - if 'dns_server_list' in config_dic['Challenge']: - try: - self.dns_server_list = json.loads(config_dic['Challenge']['dns_server_list']) - except Exception as err_: - self.logger.warning('Challenge._config_load() dns_server_list failed with error: {0}'.format(err_)) + if 'challenge_validation_timeout' in config_dic['Challenge']: try: self.challenge_validation_timeout = int(config_dic['Challenge']['challenge_validation_timeout']) except Exception as err_: - self.logger.warning('Challenge._config_load() failed to load challenge_validation_timeout: {0}'.format(err_)) + self.logger.warning('Challenge._config_load() failed to load challenge_validation_timeout: %s', err_) self.logger.debug('Challenge._config_challenge_load() ended') @@ -194,6 +225,7 @@ def _config_load(self): # load challenge parameters self._config_challenge_load(config_dic) + self._config_dns_load(config_dic) if 'Order' in config_dic: self.tnauthlist_support = config_dic.getboolean('Order', 'tnauthlist_support', fallback=False) @@ -208,7 +240,7 @@ def _config_load(self): def _extensions_validate(self, cert: str, extension_value: str, fqdn: str) -> bool: """ validate extension """ - self.logger.debug('Challenge._extensions_validate({0}/{1})'.format(extension_value, fqdn)) + self.logger.debug('Challenge._extensions_validate(%s/%s)', extension_value, fqdn) result = False san_list = cert_san_get(self.logger, cert, recode=False) fqdn_in_san = fqdn_in_san_check(self.logger, san_list, fqdn) @@ -222,21 +254,24 @@ def _extensions_validate(self, cert: str, extension_value: str, fqdn: str) -> bo else: self.logger.debug('fqdn check against san failed') - self.logger.debug('Challenge._extensions_validate() ended with: {0}'.format(result)) + self.logger.debug('Challenge._extensions_validate() ended with: %s', result) return result def _name_get(self, url: str) -> str: """ get challenge """ - self.logger.debug('Challenge.get_name({0})'.format(url)) + self.logger.debug('Challenge.get_name()') + url_dic = parse_url(self.logger, url) challenge_name = url_dic['path'].replace(self.path_dic['chall_path'], '') if '/' in challenge_name: (challenge_name, _sinin) = challenge_name.split('/', 1) + + self.logger.debug('Challenge.get_name() ended with: %s', challenge_name) return challenge_name def _new(self, authz_name: str, mtype: str, token: str = None, value: str = None) -> Dict[str, str]: """ new challenge """ - self.logger.debug('Challenge._new({0}:{2}:{1})'.format(authz_name, mtype, value)) + self.logger.debug('Challenge._new(%s:%s:%s)', authz_name, mtype, value) challenge_name = generate_random_string(self.logger, 12) @@ -255,13 +290,13 @@ def _new(self, authz_name: str, mtype: str, token: str = None, value: str = None try: chid = self.dbstore.challenge_add(value, mtype, data_dic) except Exception as err_: - self.logger.critical('acme2certifier database error in Challenge._new(): {0}, {2}:{1}'.format(err_, mtype, value)) + self.logger.critical('acme2certifier database error in Challenge._new(): %s, %s:%s', err_, value, mtype) chid = None challenge_dic = {} if chid: challenge_dic['type'] = mtype - challenge_dic['url'] = '{0}{1}{2}'.format(self.server_name, self.path_dic['chall_path'], challenge_name) + challenge_dic['url'] = f'{self.server_name}{self.path_dic["chall_path"]}{challenge_name}' challenge_dic['token'] = token challenge_dic['status'] = 'pending' if mtype == 'tkauth-01': @@ -275,7 +310,7 @@ def _new(self, authz_name: str, mtype: str, token: str = None, value: str = None def _parse(self, code: int, payload: Dict[str, str], protected: Dict[str, str], challenge_name: str, challenge_dic: Dict[str, str]) -> Tuple[int, str, str, Dict[str, str]]: # pylint: disable=R0913 """ challenge parse """ - self.logger.debug('Challenge._parse({0})'.format(challenge_name)) + self.logger.debug('Challenge._parse(%s)', challenge_name) response_dic = {} message = None @@ -307,28 +342,29 @@ def _parse(self, code: int, payload: Dict[str, str], protected: Dict[str, str], challenge_dic['url'] = protected['url'] response_dic['data'] = challenge_dic response_dic['header'] = {} - response_dic['header']['Link'] = '<{0}{1}>;rel="up"'.format(self.server_name, self.path_dic['authz_path']) + response_dic['header']['Link'] = f'<{self.server_name}{self.path_dic["authz_path"]}>;rel="up"' - self.logger.debug('Challenge._parse() ended with: {0}'.format(code)) + self.logger.debug('Challenge._parse() ended with: %s', code) return (code, message, detail, response_dic) def _update(self, data_dic: Dict[str, str]): """ update challenge """ - self.logger.debug('Challenge._update({0})'.format(data_dic)) + self.logger.debug('Challenge._update(%s)', data_dic) + try: self.dbstore.challenge_update(data_dic) except Exception as err_: - self.logger.critical('acme2certifier database error in Challenge._update(): {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Challenge._update(): %s', err_) self.logger.debug('Challenge._update() ended') def _update_authz(self, challenge_name: str, data_dic: Dict[str, str]): """ update authorizsation based on challenge_name """ - self.logger.debug('Challenge._update_authz({0})'.format(challenge_name)) + self.logger.debug('Challenge._update_authz(%s)', challenge_name) try: # lookup autorization based on challenge_name authz_name = self.dbstore.challenge_lookup('name', challenge_name, ['authorization__name'])['authorization'] except Exception as err_: - self.logger.critical('acme2certifier database error in Challenge._update_authz() lookup: {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Challenge._update_authz() lookup: %s', err_) authz_name = None if authz_name: @@ -337,13 +373,14 @@ def _update_authz(self, challenge_name: str, data_dic: Dict[str, str]): # update authorization self.dbstore.authorization_update(data_dic) except Exception as err_: - self.logger.critical('acme2certifier database error in Challenge._update_authz() upd: {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Challenge._update_authz() upd: %s', err_) self.logger.debug('Challenge._update_authz() ended') def _validate(self, challenge_name: str, payload: Dict[str, str]) -> bool: """ validate challenge""" - self.logger.debug('Challenge._validate({0}: {1})'.format(challenge_name, payload)) + self.logger.debug('Challenge._validate(%s: %s)', challenge_name, payload) + # change state to processing self._update({'name': challenge_name, 'status': 'processing'}) if self.challenge_validation_disable: @@ -367,17 +404,17 @@ def _validate(self, challenge_name: str, payload: Dict[str, str]) -> bool: data_dic = {'name': challenge_name, 'keyauthorization': payload['keyAuthorization']} self._update(data_dic) - self.logger.debug('Challenge._validate() ended with:{0}'.format(challenge_check)) + self.logger.debug('Challenge._validate() ended with:%s', challenge_check) return challenge_check def _validate_alpn_challenge(self, challenge_name: str, id_type: str, id_value: str, token: str, jwk_thumbprint: str) -> Tuple[bool, bool]: """ validate dns challenge """ - self.logger.debug('Challenge._validate_alpn_challenge({0}:{1}:{2})'.format(challenge_name, id_value, token)) + self.logger.debug('Challenge._validate_alpn_challenge(%s:%s:%s)', challenge_name, id_value, token) if id_type == 'dns': # resolve name (response, invalid) = fqdn_resolve(id_value, self.dns_server_list) - self.logger.debug('fqdn_resolve() ended with: {0}/{1}'.format(response, invalid)) + self.logger.debug('fqdn_resolve() ended with: %s/%s', response, invalid) sni = id_value elif id_type == 'ip': (sni, invalid) = ip_validate(self.logger, id_value) @@ -387,9 +424,9 @@ def _validate_alpn_challenge(self, challenge_name: str, id_type: str, id_value: # we are expecting a certifiate extension which is the sha256 hexdigest of token in a byte structure # which is base64 encoded '0420' has been taken from acme_srv.sh sources - sha256_digest = sha256_hash_hex(self.logger, '{0}.{1}'.format(token, jwk_thumbprint)) - extension_value = b64_encode(self.logger, bytearray.fromhex('0420{0}'.format(sha256_digest))) - self.logger.debug('computed value: {0}'.format(extension_value)) + sha256_digest = sha256_hash_hex(self.logger, f'{token}.{jwk_thumbprint}') + extension_value = b64_encode(self.logger, bytearray.fromhex(f'0420{sha256_digest}')) + self.logger.debug('computed value: %s', extension_value) if not invalid: # check if we need to set a proxy @@ -406,26 +443,27 @@ def _validate_alpn_challenge(self, challenge_name: str, id_type: str, id_value: else: result = False - self.logger.debug('Challenge._validate_alpn_challenge() ended with: {0}/{1}'.format(result, invalid)) + self.logger.debug('Challenge._validate_alpn_challenge() ended with: %s/%s', result, invalid) return (result, invalid) def _validate_dns_challenge(self, challenge_name: str, _type: str, fqdn: str, token: str, jwk_thumbprint: str) -> Tuple[bool, bool]: """ validate dns challenge """ - self.logger.debug('Challenge._validate_dns_challenge({0}:{1}:{2})'.format(challenge_name, fqdn, token)) + self.logger.debug('Challenge._validate_dns_challenge(%s:%s:%s)', challenge_name, fqdn, token) # handle wildcard domain fqdn = self._wcd_manipulate(fqdn) # rewrite fqdn to resolve txt record - fqdn = '_acme-challenge.{0}'.format(fqdn) + fqdn = f'_acme-challenge.{fqdn}' # compute sha256 hash - _hash = b64_url_encode(self.logger, sha256_hash(self.logger, '{0}.{1}'.format(token, jwk_thumbprint))) + _hash = b64_url_encode(self.logger, sha256_hash(self.logger, f'{token}.{jwk_thumbprint}')) + # query dns txt_list = txt_get(self.logger, fqdn, self.dns_server_list) # compare computed hash with result from DNS query - self.logger.debug('response_got: {0} response_expected: {1}'.format(txt_list, _hash)) + self.logger.debug('response_got: %s response_expected: %s', txt_list, _hash) if _hash in txt_list: self.logger.debug('validation successful') result = True @@ -433,17 +471,17 @@ def _validate_dns_challenge(self, challenge_name: str, _type: str, fqdn: str, to self.logger.debug('validation not successful') result = False - self.logger.debug('Challenge._validate_dns_challenge() ended with: {0}'.format(result)) + self.logger.debug('Challenge._validate_dns_challenge() ended with: %s', result) return (result, False) def _validate_http_challenge(self, challenge_name: str, id_type: str, id_value: str, token: str, jwk_thumbprint: str) -> Tuple[bool, bool]: """ validate http challenge """ - self.logger.debug('Challenge._validate_http_challenge({0}:{1}:{2})'.format(challenge_name, id_value, token)) + self.logger.debug('Challenge._validate_http_challenge(%s:%s:%s)', challenge_name, id_value, token) if id_type == 'dns': # resolve name (response, invalid) = fqdn_resolve(id_value, self.dns_server_list) - self.logger.debug('fqdn_resolve() ended with: {0}/{1}'.format(response, invalid)) + self.logger.debug('fqdn_resolve() ended with: %s/%s', response, invalid) elif id_type == 'ip': invalid = False (_sni, invalid) = ip_validate(self.logger, id_value) @@ -456,11 +494,11 @@ def _validate_http_challenge(self, challenge_name: str, id_type: str, id_value: proxy_server = proxy_check(self.logger, id_value, self.proxy_server_list) else: proxy_server = None - req = url_get(self.logger, 'http://{0}/.well-known/acme-challenge/{1}'.format(id_value, token), dns_server_list=self.dns_server_list, proxy_server=proxy_server, verify=False, timeout=self.challenge_validation_timeout) + req = url_get(self.logger, f'http://{id_value}/.well-known/acme-challenge/{token}', dns_server_list=self.dns_server_list, proxy_server=proxy_server, verify=False, timeout=self.challenge_validation_timeout) if req: response_got = req.splitlines()[0] - response_expected = '{0}.{1}'.format(token, jwk_thumbprint) - self.logger.debug('response_got: {0} response_expected: {1}'.format(response_got, response_expected)) + response_expected = f'{token}.{jwk_thumbprint}' + self.logger.debug('response_got: %s response_expected: %s', response_got, response_expected) if response_got == response_expected: self.logger.debug('validation successful') result = True @@ -473,21 +511,21 @@ def _validate_http_challenge(self, challenge_name: str, id_type: str, id_value: else: result = False - self.logger.debug('Challenge._validate_http_challenge() ended with: {0}/{1}'.format(result, invalid)) + self.logger.debug('Challenge._validate_http_challenge() ended with: %s/%s', result, invalid) return (result, invalid) def _validate_tkauth_challenge(self, challenge_name: str, _type: str, tnauthlist: str, _token: str, _jwk_thumbprint: str, payload: Dict[str, str]) -> Tuple[bool, bool]: """ validate tkauth challenge """ - self.logger.debug('Challenge._validate_tkauth_challenge({0}:{1}:{2})'.format(challenge_name, tnauthlist, payload)) + self.logger.debug('Challenge._validate_tkauth_challenge(%s:%s:%s)', challenge_name, tnauthlist, payload) result = True invalid = False - self.logger.debug('Challenge._validate_tkauth_challenge() ended with: {0}/{1}'.format(result, invalid)) + self.logger.debug('Challenge._validate_tkauth_challenge() ended with: %s/%s', result, invalid) return (result, invalid) def _validate_tnauthlist_payload(self, payload: Dict[str, str], challenge_dic: Dict[str, str]) -> Tuple[int, str, str]: """ check payload in cae tnauthlist option has been set """ - self.logger.debug('Challenge._validate_tnauthlist_payload({0})'.format(payload)) + self.logger.debug('Challenge._validate_tnauthlist_payload(%s)', payload) code = 400 message = None @@ -513,22 +551,24 @@ def _validate_tnauthlist_payload(self, payload: Dict[str, str], challenge_dic: D code = 200 else: message = self.err_msg_dic['malformed'] - detail = 'invalid challenge: {0}'.format(challenge_dic) + detail = f'invalid challenge: {challenge_dic}' - self.logger.debug('Challenge._validate_tnauthlist_payload() ended with:{0}'.format(code)) + self.logger.debug('Challenge._validate_tnauthlist_payload() ended with:%s', code) return (code, message, detail) def _wcd_manipulate(self, fqdn: str) -> str: """ wildcard domain handling """ - self.logger.debug('Challenge._wc_manipulate() for fqdn: {0}'.format(fqdn)) + self.logger.debug('Challenge._wc_manipulate() for fqdn: %s', fqdn) + if fqdn.startswith('*.'): fqdn = fqdn[2:] - self.logger.debug('Challenge._wc_manipulate() ended with: {0}'.format(fqdn)) + self.logger.debug('Challenge._wc_manipulate() ended with: %s', fqdn) return fqdn def challengeset_get(self, authz_name: str, _auth_status: str, token: str, tnauth: bool, id_type: str = 'dns', id_value: str = None) -> List[str]: """ get the challengeset for an authorization """ - self.logger.debug('Challenge.challengeset_get() for auth: {0}:{1}'.format(authz_name, id_value)) + self.logger.debug('Challenge.challengeset_get() for auth: %s:%s', authz_name, id_value) + # check database if there are exsting challenges for a particular authorization challenge_list = self._challengelist_search('authorization__name', authz_name) @@ -552,7 +592,8 @@ def challengeset_get(self, authz_name: str, _auth_status: str, token: str, tnaut def get(self, url: str) -> Dict[str, str]: """ get challenge details based on get request """ challenge_name = self._name_get(url) - self.logger.debug('Challenge.get({0})'.format(challenge_name)) + self.logger.debug('Challenge.get(%s)', challenge_name) + response_dic = {} response_dic['code'] = 200 response_dic['data'] = self._info(challenge_name) @@ -560,7 +601,8 @@ def get(self, url: str) -> Dict[str, str]: def new_set(self, authz_name: str, token: str, tnauth: bool = False, id_type: str = 'dns', value: str = None) -> List[str]: """ net challenge set """ - self.logger.debug('Challenge.new_set({0}, {1})'.format(authz_name, value)) + self.logger.debug('Challenge.new_set(%s, %s)', authz_name, value) + challenge_list = [] if tnauth: @@ -579,9 +621,9 @@ def new_set(self, authz_name: str, token: str, tnauth: bool = False, id_type: st if challenge_json: challenge_list.append(challenge_json) else: - self.logger.error('ERROR: Empty challenge returned for {0}'.format(challenge_type)) + self.logger.error('ERROR: Empty challenge returned for %s', challenge_type) - self.logger.debug('Challenge._new_set returned ({0})'.format(challenge_list)) + self.logger.debug('Challenge._new_set returned (%s)', challenge_list) return challenge_list def parse(self, content: str) -> Dict[str, str]: @@ -604,7 +646,7 @@ def parse(self, content: str) -> Dict[str, str]: else: code = 400 message = self.err_msg_dic['malformed'] - detail = 'invalid challenge: {0}'.format(challenge_name) + detail = f'invalid challenge: {challenge_name}' else: code = 400 message = self.err_msg_dic['malformed'] @@ -617,5 +659,5 @@ def parse(self, content: str) -> Dict[str, str]: # prepare/enrich response status_dic = {'code': code, 'type': message, 'detail': detail} response_dic = self.message.prepare_response(response_dic, status_dic) - self.logger.debug('challenge.parse() returns: {0}'.format(json.dumps(response_dic))) + self.logger.debug('challenge.parse() returns: %s', json.dumps(response_dic)) return response_dic diff --git a/acme_srv/directory.py b/acme_srv/directory.py index 39dd9aa6..bdf6b097 100644 --- a/acme_srv/directory.py +++ b/acme_srv/directory.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- """ Directory class """ -# pylint: disable=c0209, e0401, r0913 +# pylint: disable=e0401, r0913 from __future__ import print_function import uuid from typing import Dict @@ -9,6 +9,9 @@ from .db_handler import DBstore +GH_HOME = 'https://github.com/grindsa/acme2certifier' + + class Directory(object): """ class for directory handling """ @@ -17,6 +20,8 @@ def __init__(self, debug=None, srv_name=None, logger=None): self.logger = logger self.dbstore = DBstore(debug, self.logger) self.supress_version = False + self.suppress_product_information = False + self.home = GH_HOME self.tos_url = None self.version = __version__ self.dbversion = __dbversion__ @@ -48,6 +53,13 @@ def _config_load(self): if 'Directory' in config_dic and 'url_prefix' in config_dic['Directory']: self.url_prefix = config_dic['Directory']['url_prefix'] + self.home = config_dic.get('Directory', 'home', fallback=GH_HOME) + + try: + self.suppress_product_information = config_dic.getboolean('Directory', 'suppress_product_information', fallback=False) + except Exception as err_: + self.logger.error('Directory._config_load() suppress_product_information not set: %s', err_) + self.logger.debug('Directory._config_load() ended') def directory_get(self) -> Dict[str, str]: @@ -62,16 +74,21 @@ def directory_get(self) -> Dict[str, str]: 'revokeCert': self.server_name + self.url_prefix + '/acme/revokecert', 'keyChange': self.server_name + self.url_prefix + '/acme/key-change', 'renewalInfo': self.server_name + self.url_prefix + '/acme/renewal-info', - 'meta': { - 'home': 'https://github.com/grindsa/acme2certifier', - 'author': 'grindsa ', - 'name': 'acme2certifier' - }, + 'meta': {} } - # show version information in meta tags if not disabled.... - if not self.supress_version: - d_dic['meta']['version'] = self.version + if not self.suppress_product_information: + d_dic['meta'] = { + 'home': self.home, + 'author': 'grindsa ', + 'name': 'acme2certifier' + } + # show version information in meta tags if not disabled.... + if not self.supress_version: + d_dic['meta']['version'] = self.version + else: + if self.home != GH_HOME: + d_dic['meta']['home'] = self.home # add terms of service if self.tos_url: @@ -87,15 +104,16 @@ def directory_get(self) -> Dict[str, str]: if version == self.dbversion: d_dic['meta']['db_check'] = 'OK' else: - self.logger.error('acme2certifier database error: version mismatch: detected: {0}/ expected: {1}'.format(version, __dbversion__)) + self.logger.error('acme2certifier database error: version mismatch: detected: %s/ expected: %s', version, __dbversion__) d_dic['meta']['db_check'] = 'NOK' except Exception as err_: - self.logger.critical('acme2certifier database error in Directory.dbversion_check(): {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Directory.dbversion_check(): %s', err_) d_dic['meta']['db_check'] = 'NOK' # generate random key in json as recommended by LE d_dic[uuid.uuid4().hex] = 'https://community.letsencrypt.org/t/adding-random-entries-to-the-directory/33417' + return d_dic def servername_get(self) -> str: diff --git a/acme_srv/helper.py b/acme_srv/helper.py index 19c56fed..c032de0d 100644 --- a/acme_srv/helper.py +++ b/acme_srv/helper.py @@ -1,4 +1,4 @@ -# pylint: disable=c0209, c0302, e0401, r0913 +# pylint: disable=c0302, e0401, r0913 # -*- coding: utf-8 -*- """ helper functions for acme2certifier """ from __future__ import print_function @@ -33,17 +33,18 @@ from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import serialization, hashes from cryptography.x509 import load_pem_x509_certificate, ocsp +from OpenSSL import crypto import requests import requests.packages.urllib3.util.connection as urllib3_cn from .version import __version__ -USER_AGENT = 'acme2certifier/{0}'.format(__version__) +USER_AGENT = f'acme2certifier/{__version__}' def b64decode_pad(logger: logging.Logger, string: str) -> bytes: """ b64 decoding and padding of missing "=" """ - logger.debug('b64decode_pad()') + logger.debug('Helper.b64decode_pad()') try: b64dec = base64.urlsafe_b64decode(string + '=' * (4 - len(string) % 4)) except Exception: @@ -53,19 +54,19 @@ def b64decode_pad(logger: logging.Logger, string: str) -> bytes: def b64_decode(logger: logging.Logger, string: str) -> str: """ b64 decoding """ - logger.debug('b64decode()') + logger.debug('Helper.b64decode()') return convert_byte_to_string(base64.b64decode(string)) def b64_encode(logger: logging.Logger, string: str) -> str: """ encode a bytestream in base64 """ - logger.debug('b64_encode()') + logger.debug('Helper.b64_encode()') return convert_byte_to_string(base64.b64encode(string)) def b64_url_encode(logger: logging.Logger, string: str) -> str: """ encode a bytestream in base64 url and remove padding """ - logger.debug('b64_url_encode()') + logger.debug('Helper.b64_url_encode()') string = convert_string_to_byte(string) encoded = base64.urlsafe_b64encode(string) return encoded.rstrip(b"=") @@ -73,7 +74,7 @@ def b64_url_encode(logger: logging.Logger, string: str) -> str: def b64_url_recode(logger: logging.Logger, string: str) -> str: """ recode base64_url to base64 """ - logger.debug('b64_url_recode()') + logger.debug('Helper.b64_url_recode()') padding_factor = (4 - len(string) % 4) % 4 string = convert_byte_to_string(string) string += "=" * padding_factor @@ -83,20 +84,20 @@ def b64_url_recode(logger: logging.Logger, string: str) -> str: def build_pem_file(logger: logging.Logger, existing, certificate, wrap, csr=False): """ construct pem_file """ - logger.debug('build_pem_file()') + logger.debug('Helper.build_pem_file()') if csr: - pem_file = '-----BEGIN CERTIFICATE REQUEST-----\n{0}\n-----END CERTIFICATE REQUEST-----\n'.format(textwrap.fill(convert_byte_to_string(certificate), 64)) + pem_file = f'-----BEGIN CERTIFICATE REQUEST-----\n{textwrap.fill(convert_byte_to_string(certificate), 64)}\n-----END CERTIFICATE REQUEST-----\n' else: if existing: if wrap: - pem_file = '{0}-----BEGIN CERTIFICATE-----\n{1}\n-----END CERTIFICATE-----\n'.format(convert_byte_to_string(existing), textwrap.fill(convert_byte_to_string(certificate), 64)) + pem_file = f'{existing}-----BEGIN CERTIFICATE-----\n{textwrap.fill(convert_byte_to_string(certificate), 64)}\n-----END CERTIFICATE-----\n' else: - pem_file = '{0}-----BEGIN CERTIFICATE-----\n{1}\n-----END CERTIFICATE-----\n'.format(convert_byte_to_string(existing), convert_byte_to_string(certificate)) + pem_file = f'{convert_byte_to_string(existing)}-----BEGIN CERTIFICATE-----\n{convert_byte_to_string(certificate)}\n-----END CERTIFICATE-----\n' else: if wrap: - pem_file = '-----BEGIN CERTIFICATE-----\n{0}\n-----END CERTIFICATE-----\n'.format(textwrap.fill(convert_byte_to_string(certificate), 64)) + pem_file = f'-----BEGIN CERTIFICATE-----\n{textwrap.fill(convert_byte_to_string(certificate), 64)}\n-----END CERTIFICATE-----\n' else: - pem_file = '-----BEGIN CERTIFICATE-----\n{0}\n-----END CERTIFICATE-----\n'.format(convert_byte_to_string(certificate)) + pem_file = f'-----BEGIN CERTIFICATE-----\n{convert_byte_to_string(certificate)}\n-----END CERTIFICATE-----\n' return pem_file @@ -116,13 +117,13 @@ def ca_handler_load(logger: logging.Logger, config_dic: Dict) -> importlib.impor spec.loader.exec_module(ca_handler_module) return ca_handler_module except Exception as err_: - logger.critical('Helper.ca_handler_load(): loading CAhandler configured in cfg failed with err: {0}'.format(err_)) + logger.critical('Helper.ca_handler_load(): loading CAhandler configured in cfg failed with err: %s', err_) # if no 'handler_file' provided or loading was unsuccessful, try to load default handler try: ca_handler_module = importlib.import_module('acme_srv.ca_handler') except Exception as err_: - logger.critical('Helper.ca_handler_load(): loading default CAhandler failed with err: {0}'.format(err_)) + logger.critical('Helper.ca_handler_load(): loading default CAhandler failed with err: %s', err_) ca_handler_module = None return ca_handler_module @@ -135,7 +136,50 @@ def config_check(logger: logging.Logger, config_dic: Dict): for section, section_dic in config_dic.items(): for key, value in section_dic.items(): if value.startswith('"') or value.endswith('"'): - logger.warning('config_check(): section {0} option: {1} contains " characters. Check if this is really needed!'.format(section, key)) + logger.warning('config_check(): section %s option: %s contains " characters. Check if this is really needed!', section, key) + + +def config_eab_profile_load(logger: logging.Logger, config_dic: Dict[str, str]): + """ load parameters """ + logger.debug('Helper.config_eab_profile_load()') + + eab_profiling = False + eab_handler = None + + try: + eab_profiling = config_dic.getboolean('CAhandler', 'eab_profiling', fallback=False) + except Exception as err: + logger.warning('CAhandler._config_eab_profile_load() failed with error: %s', err) + eab_profiling = False + + if eab_profiling: + if 'EABhandler' in config_dic and 'eab_handler_file' in config_dic['EABhandler']: + # load eab_handler according to configuration + eab_handler_module = eab_handler_load(logger, config_dic) + if not eab_handler_module: + logger.critical('CAhandler._config_load(): EABHandler could not get loaded') + else: + eab_handler = eab_handler_module.EABhandler + else: + logger.critical('CAhandler._config_load(): EABHandler configuration incomplete') + + logger.debug('_config_profile_load() ended') + return eab_profiling, eab_handler + + +def config_headerinfo_load(logger: logging.Logger, config_dic: Dict[str, str]): + """ load parameters """ + logger.debug('Helper.config_headerinfo_load()') + + header_info_field = None + if 'Order' in config_dic and 'header_info_list' in config_dic['Order'] and config_dic['Order']['header_info_list']: + try: + header_info_field = json.loads(config_dic['Order']['header_info_list'])[0] + except Exception as err_: + logger.warning('Helper.config_headerinfo_load() header_info_list failed with error: %s', err_) + + logger.debug('config_headerinfo_load() ended') + return header_info_field def eab_handler_load(logger: logging.Logger, config_dic: Dict) -> importlib.import_module: @@ -149,18 +193,18 @@ def eab_handler_load(logger: logging.Logger, config_dic: Dict) -> importlib.impo eab_handler_module = importlib.util.module_from_spec(spec) spec.loader.exec_module(eab_handler_module) except Exception as err_: - logger.critical('Helper.eab_handler_load(): loading EABhandler configured in cfg failed with err: {0}'.format(err_)) + logger.critical('Helper.eab_handler_load(): loading EABhandler configured in cfg failed with err: %s', err_) try: eab_handler_module = importlib.import_module('acme_srv.eab_handler') except Exception as err_: eab_handler_module = None - logger.critical('Helper.eab_handler_load(): loading default EABhandler failed with err: {0}'.format(err_)) + logger.critical('Helper.eab_handler_load(): loading default EABhandler failed with err: %s', err_) else: if 'EABhandler' in config_dic: try: eab_handler_module = importlib.import_module('acme_srv.eab_handler') except Exception as err_: - logger.critical('Helper.eab_handler_load(): loading default EABhandler failed with err: {0}'.format(err_)) + logger.critical('Helper.eab_handler_load(): loading default EABhandler failed with err: %s', err_) eab_handler_module = None else: logger.error('Helper.eab_handler_load(): EABhandler configuration missing in config file') @@ -181,14 +225,51 @@ def hooks_load(logger: logging.Logger, config_dic: Dict) -> importlib.import_mod hooks_module = importlib.util.module_from_spec(spec) spec.loader.exec_module(hooks_module) except Exception as err_: - logger.critical('Helper.hooks_load(): loading Hooks configured in cfg failed with err: {0}'.format(err_)) + logger.critical('Helper.hooks_load(): loading Hooks configured in cfg failed with err: %s', err_) return hooks_module +def cert_aki_get(logger: logging.Logger, certificate: str) -> str: + """ get subject key identifier from certificate """ + logger.debug('Helper.cert_ski_get()') + + cert = cert_load(logger, certificate, recode=True) + try: + aki = cert.extensions.get_extension_for_oid(x509.OID_AUTHORITY_KEY_IDENTIFIER) + aki_value = aki.value.key_identifier.hex() + except Exception as _err: + aki_value = cert_aki_pyopenssl_get(logger, certificate) + logger.debug('cert_aki_get() ended with: %s', aki_value) + return aki_value + + +def cert_aki_pyopenssl_get(logger, certificate: str) -> str: + """Get Authority Key Identifier from a certificate as a hex string.""" + logger.debug('Helper.cert_aki_pyopenssl_cert()') + + pem_data = convert_string_to_byte(build_pem_file(logger, None, b64_url_recode(logger, certificate), True)) + cert = crypto.load_certificate(crypto.FILETYPE_PEM, pem_data) + # Get the AKI extension + aki = None + for i in range(cert.get_extension_count()): + ext = cert.get_extension(i) + if 'authorityKeyIdentifier' in str(ext.get_short_name()): + aki = ext + if aki: + # Get the SKI value and convert it to hex + aki_hex = aki.get_data()[4:].hex() + else: + logger.error("cert_ski_pyopenssl_get(): No AKI found in certificate") + aki_hex = None + logger.debug('Helper.cert_ski_pyopenssl_cert() ended with: %s', aki_hex) + return aki_hex + + def cert_load(logger: logging.Logger, certificate: str, recode: bool) -> x509.Certificate: """ load certificate object from pem _Format """ - logger.debug('cert_load({0})'.format(recode)) + logger.debug('Helper.cert_load(%s)', recode) + if recode: pem_data = convert_string_to_byte(build_pem_file(logger, None, b64_url_recode(logger, certificate), True)) else: @@ -200,10 +281,10 @@ def cert_load(logger: logging.Logger, certificate: str, recode: bool) -> x509.Ce def cert_dates_get(logger: logging.Logger, certificate: str) -> Tuple[int, int]: """ get date number form certificate """ - logger.debug('cert_dates_get()') + logger.debug('Helper.cert_dates_get()') + issue_date = 0 expiration_date = 0 - try: cert = cert_load(logger, certificate, recode=True) issue_date = date_to_uts_utc(cert.not_valid_before, _tformat='%Y-%m-%d %H:%M:%S') @@ -212,13 +293,13 @@ def cert_dates_get(logger: logging.Logger, certificate: str) -> Tuple[int, int]: issue_date = 0 expiration_date = 0 - logger.debug('cert_dates_get() ended with: {0}/{1}'.format(issue_date, expiration_date)) + logger.debug('cert_dates_get() ended with: %s/%s', issue_date, expiration_date) return (issue_date, expiration_date) def cert_cn_get(logger: logging.Logger, certificate: str) -> str: """ get cn from certificate """ - logger.debug('CAhandler.cert_cn_get()') + logger.debug('Helper.cert_cn_get()') cert = cert_load(logger, certificate, recode=True) # get subject and look for common name @@ -228,7 +309,7 @@ def cert_cn_get(logger: logging.Logger, certificate: str) -> str: if attr.oid == x509.NameOID.COMMON_NAME: result = attr.value break - logger.debug('CAhandler.cert_cn_get() ended with: {0}'.format(result)) + logger.debug('Helper.cert_cn_get() ended with: %s', result) return result @@ -241,11 +322,11 @@ def cert_der2pem(der_cert: bytes) -> str: def cert_issuer_get(logger: logging.Logger, certificate: str) -> str: """ get serial number form certificate """ - logger.debug('cert_issuer_get()') + logger.debug('Helper.cert_issuer_get()') cert = cert_load(logger, certificate, recode=True) result = cert.issuer.rfc4514_string() - logger.debug('CAhandler.cert_issuer_get() ended with: {0}'.format(result)) + logger.debug('Helper.cert_issuer_get() ended with: %s', result) return result @@ -258,20 +339,45 @@ def cert_pem2der(pem_cert: str) -> bytes: def cert_pubkey_get(logger: logging.Logger, certificate=str) -> str: """ get public key from certificate """ - logger.debug('CAhandler.cert_pubkey_get()') + logger.debug('Helper.cert_pubkey_get()') cert = cert_load(logger, certificate, recode=False) public_key = cert.public_key() pubkey_str = public_key.public_bytes( encoding=serialization.Encoding.PEM, format=serialization.PublicFormat.SubjectPublicKeyInfo ) - logger.debug('CAhandler.cert_pubkey_get() ended with: {0}'.format(pubkey_str)) + logger.debug('Helper.cert_pubkey_get() ended with: %s', pubkey_str) return convert_byte_to_string(pubkey_str) +def cert_san_pyopenssl_get(logger, certificate, recode=True): + """ get subject alternate names from certificate """ + logger.debug('Helper.cert_san_pyopenssl_get()') + if recode: + pem_file = build_pem_file(logger, None, b64_url_recode(logger, certificate), True) + else: + pem_file = certificate + + cert = crypto.load_certificate(crypto.FILETYPE_PEM, pem_file) + san = [] + ext_count = cert.get_extension_count() + for i in range(0, ext_count): + ext = cert.get_extension(i) + if 'subjectAltName' in str(ext.get_short_name()): + # pylint: disable=c2801 + san_list = ext.__str__().split(',') + for san_name in san_list: + san_name = san_name.rstrip() + san_name = san_name.lstrip() + san.append(san_name) + + logger.debug('Helper.cert_san_pyopenssl_get() ended') + return san + + def cert_san_get(logger: logging.Logger, certificate: str, recode: bool = True) -> List[str]: """ get subject alternate names from certificate """ - logger.debug('cert_san_get({0})'.format(recode)) + logger.debug('Helper.cert_san_get(%s)', recode) cert = cert_load(logger, certificate, recode=recode) sans = [] @@ -279,40 +385,121 @@ def cert_san_get(logger: logging.Logger, certificate: str, recode: bool = True) ext = cert.extensions.get_extension_for_oid(x509.OID_SUBJECT_ALTERNATIVE_NAME) sans_list = ext.value.get_values_for_type(x509.DNSName) for san in sans_list: - sans.append('DNS:{0}'.format(san)) + sans.append(f'DNS:{san}') sans_list = ext.value.get_values_for_type(x509.IPAddress) for san in sans_list: - sans.append('IP:{0}'.format(san)) + sans.append(f'IP:{san}') except Exception as err: - logger.error('cert_san_get(): Error: {0}'.format(err)) + logger.error('cert_san_get(): Error: %s', err) + # we may add the routing to get the sanes via pyopenssl here if needed (sans = cert_san_pyopenssl_get(logger, certificate, recode=recode)) - logger.debug('cert_san_get() ended') + logger.debug('Helper.cert_san_get() ended') return sans +def cert_ski_pyopenssl_get(logger, certificate: str) -> str: + """Get Subject Key Identifier from a certificate as a hex string.""" + logger.debug('Helper.cert_ski_pyopenssl_cert()') + + pem_data = convert_string_to_byte(build_pem_file(logger, None, b64_url_recode(logger, certificate), True)) + cert = crypto.load_certificate(crypto.FILETYPE_PEM, pem_data) + # Get the SKI extension + ski = None + for i in range(cert.get_extension_count()): + ext = cert.get_extension(i) + if 'subjectKeyIdentifier' in str(ext.get_short_name()): + ski = ext + if ski: + # Get the SKI value and convert it to hex + ski_hex = ski.get_data()[2:].hex() + else: + logger.error("cert_ski_pyopenssl_get(): No SKI found in certificate") + ski_hex = None + logger.debug('Helper.cert_ski_pyopenssl_cert() ended with: %s', ski_hex) + return ski_hex + + +def cert_ski_get(logger: logging.Logger, certificate: str) -> str: + """ get subject key identifier from certificate """ + logger.debug('Helper.cert_ski_get()') + + cert = cert_load(logger, certificate, recode=True) + try: + ski = cert.extensions.get_extension_for_oid(x509.OID_SUBJECT_KEY_IDENTIFIER) + ski_value = ski.value.digest.hex() + except Exception as err: + logger.error('cert_ski_get(): Error: %s', err) + ski_value = cert_ski_pyopenssl_get(logger, certificate) + logger.debug('Helper.cert_ski_get() ended with: %s', ski_value) + return ski_value + + +def cryptography_version_get(logger: logging.Logger) -> int: + """ get version number of cryptography module """ + logger.debug('Helper.cryptography_version_get()') + # pylint: disable=c0415 + import cryptography + + try: + version_list = cryptography.__version__.split('.') + if version_list: + major_version = int(version_list[0]) + except Exception as err: + logger.error('cryptography_version_get(): Error: %s', err) + major_version = 36 + + logger.debug('cryptography_version_get() ended with %s', major_version) + return major_version + + def cert_extensions_get(logger: logging.Logger, certificate: str, recode: bool = True): """ get extenstions from certificate certificate """ - logger.debug('cert_extensions_get()') + logger.debug('Helper.cert_extensions_get()') - cert = cert_load(logger, certificate, recode=recode) + crypto_module_version = cryptography_version_get(logger) + if crypto_module_version < 36: + logger.debug('Helper.cert_extensions_get(): using pyopenssl') + extension_list = cert_extensions_py_openssl_get(logger, certificate, recode) + else: + cert = cert_load(logger, certificate, recode=recode) + extension_list = [] + for extension in cert.extensions: + extension_list.append(convert_byte_to_string(base64.b64encode(extension.value.public_bytes()))) + + logger.debug('Helper.cert_extensions_get() ended with: %s', extension_list) + return extension_list + + +def cert_extensions_py_openssl_get(logger, certificate, recode=True): + """ get extenstions from certificate certificate """ + logger.debug('cert_extensions_py_openssl_get()') + if recode: + pem_file = build_pem_file(logger, None, b64_url_recode(logger, certificate), True) + else: + pem_file = certificate + cert = crypto.load_certificate(crypto.FILETYPE_PEM, pem_file) extension_list = [] - for extension in cert.extensions: - extension_list.append(convert_byte_to_string(base64.b64encode(extension.value.public_bytes()))) + ext_count = cert.get_extension_count() + for i in range(0, ext_count): + ext = cert.get_extension(i) + extension_list.append(convert_byte_to_string(base64.b64encode(ext.get_data()))) - logger.debug('cert_extensions_get() ended with: {0}'.format(extension_list)) + logger.debug('cert_extensions_py_openssl_get() ended with: %s', extension_list) return extension_list def cert_serial_get(logger: logging.Logger, certificate: str, hexformat: bool = False): """ get serial number form certificate """ - logger.debug('cert_serial_get()') + logger.debug('Helper.cert_serial_get()') cert = cert_load(logger, certificate, recode=True) if hexformat: - serial_number = '{0:x}'.format(cert.serial_number) + serial_number = f'{cert.serial_number:x}' + # add leading zero if needed + serial_number = serial_number.zfill(len(serial_number) + len(serial_number) % 2) else: serial_number = cert.serial_number - logger.debug('cert_serial_get() ended with: {0}'.format(serial_number)) + logger.debug('Helper.cert_serial_get() ended with: %s', serial_number) return serial_number @@ -338,7 +525,8 @@ def convert_string_to_byte(value: str) -> bytes: def csr_load(logger: logging.Logger, csr: str) -> x509.CertificateSigningRequest: """ load certificate object from pem _Format """ - logger.debug('cert_load({0})') + logger.debug('Helper.cert_load()') + pem_data = convert_string_to_byte(build_pem_file(logger, None, b64_url_recode(logger, csr), True, True)) csr_data = x509.load_pem_x509_csr(pem_data) @@ -347,10 +535,9 @@ def csr_load(logger: logging.Logger, csr: str) -> x509.CertificateSigningRequest def csr_cn_get(logger: logging.Logger, csr_pem: str) -> str: """ get cn from certificate request """ - logger.debug('CAhandler.csr_cn_get()') + logger.debug('Helper.csr_cn_get()') csr = csr_load(logger, csr_pem) - # Extract the subject's common name common_name = None for attribute in csr.subject: @@ -358,37 +545,53 @@ def csr_cn_get(logger: logging.Logger, csr_pem: str) -> str: common_name = attribute.value break - logger.debug('CAhandler.csr_cn_get() ended with: {0}'.format(common_name)) + logger.debug('Helper.csr_cn_get() ended with: %s', common_name) return common_name def csr_dn_get(logger: logging.Logger, csr: str) -> str: """ get subject from certificate request in openssl notation """ - logger.debug('CAhandler.csr_dn_get()') + logger.debug('Helper.csr_dn_get()') csr_obj = csr_load(logger, csr) subject = csr_obj.subject.rfc4514_string() - logger.debug('CAhandler.csr_dn_get() ended with: {0}'.format(subject)) + logger.debug('Helper.csr_dn_get() ended with: %s', subject) return subject -def csr_pubkey_get(logger, csr): +def csr_pubkey_get(logger: logging.Logger, csr, encoding='pem'): """ get public key from certificate request """ - logger.debug('CAhandler.csr_pubkey_get()') + logger.debug('Helper.csr_pubkey_get()') csr_obj = csr_load(logger, csr) public_key = csr_obj.public_key() - pubkey_str = public_key.public_bytes( - encoding=serialization.Encoding.PEM, - format=serialization.PublicFormat.SubjectPublicKeyInfo - ) - logger.debug('CAhandler.cert_pubkey_get() ended with: {0}'.format(pubkey_str)) - return convert_byte_to_string(pubkey_str) + if encoding == 'pem': + pubkey_str = public_key.public_bytes( + encoding=serialization.Encoding.PEM, + format=serialization.PublicFormat.SubjectPublicKeyInfo + ) + pubkey = convert_byte_to_string(pubkey_str) + elif encoding == 'base64der': + pubkey_str = public_key.public_bytes( + encoding=serialization.Encoding.DER, + format=serialization.PublicFormat.SubjectPublicKeyInfo + ) + pubkey = b64_encode(logger, pubkey_str) + + elif encoding == 'der': + pubkey = public_key.public_bytes( + encoding=serialization.Encoding.DER, + format=serialization.PublicFormat.SubjectPublicKeyInfo + ) + else: + pubkey = None + logger.debug('Helper.cert_pubkey_get() ended with: %s', pubkey) + return pubkey def csr_san_get(logger: logging.Logger, csr: str) -> List[str]: """ get subject alternate names from certificate """ - logger.debug('cert_san_get()') + logger.debug('Helper.cert_san_get()') sans = [] if csr: @@ -399,21 +602,44 @@ def csr_san_get(logger: logging.Logger, csr: str) -> List[str]: sans_list = ext.value.get_values_for_type(x509.DNSName) for san in sans_list: - sans.append('DNS:{0}'.format(san)) + sans.append(f'DNS:{san}') sans_list = ext.value.get_values_for_type(x509.IPAddress) for san in sans_list: - sans.append('IP:{0}'.format(san)) + sans.append(f'IP:{san}') except Exception as err: - logger.error('csr_san_get(): Error: {0}'.format(err)) + logger.error('csr_san_get(): Error: %s', err) - logger.debug('csr_san_get() ended with: {0}'.format(str(sans))) + logger.debug('Helper.csr_san_get() ended with: %s', str(sans)) return sans +def csr_san_byte_get(logger: logging.Logger, csr: str) -> bytes: + """ get sans from CSR as base64 encoded byte squence""" + # Load the CSR + logger.debug('Helper.csr_san_byte_get()') + + csr = csr_load(logger, csr) + + # Get the SAN extension + san_extension = csr.extensions.get_extension_for_oid(x509.oid.ExtensionOID.SUBJECT_ALTERNATIVE_NAME) + + # Get the SANs + sans = san_extension.value + + # Serialize the SANs to a byte sequence + sans_bytes = sans.public_bytes() + + # Encode the byte sequence as base64 + sans_base64 = b64_encode(logger, sans_bytes) + + logger.debug('Helper.csr_san_byte_get() ended') + return sans_base64 + + def csr_extensions_get(logger: logging.Logger, csr: str) -> List[str]: """ get extensions from certificate """ - logger.debug('csr_extensions_get()') + logger.debug('Helper.csr_extensions_get()') csr_obj = csr_load(logger, csr) @@ -421,13 +647,29 @@ def csr_extensions_get(logger: logging.Logger, csr: str) -> List[str]: for extension in csr_obj.extensions: extension_list.append(convert_byte_to_string(base64.b64encode(extension.value.public_bytes()))) - logger.debug('csr_extensions_get() ended with: {0}'.format(extension_list)) + logger.debug('Helper.csr_extensions_get() ended with: %s', extension_list) return extension_list +def csr_subject_get(logger: logging.Logger, csr: str) -> Dict[str, str]: + """ get subject from csr as a list of tuples """ + logger.debug('Helper.csr_subject_get()') + # pylint: disable=w0212 + + csr_obj = csr_load(logger, csr) + subject_dic = {} + # get subject and look for common name + subject = csr_obj.subject + for attr in subject: + subject_dic[attr.oid._name] = attr.value + + logger.debug('Helper.csr_subject_get() ended') + return subject_dic + + def decode_deserialize(logger: logging.Logger, string: str) -> Dict: """ decode and deserialize string """ - logger.debug('decode_deserialize()') + logger.debug('Helper.decode_deserialize()') # b64 decode string_decode = b64decode_pad(logger, string) # deserialize if b64 decoding was successful @@ -442,7 +684,7 @@ def decode_deserialize(logger: logging.Logger, string: str) -> Dict: def decode_message(logger: logging.Logger, message: str) -> Tuple[str, str, Dict[str, str], Dict[str, str], str]: """ decode jwstoken and return header, payload and signature """ - logger.debug('decode_message()') + logger.debug('Helper.decode_message()') jwstoken = jws.JWS() result = False error = None @@ -456,7 +698,7 @@ def decode_message(logger: logging.Logger, message: str) -> Tuple[str, str, Dict signature = jwstoken.objects['signature'] result = True except Exception as err: - logger.error('decode_message() err: {0}'.format(err)) + logger.error('decode_message() err: %s', err) error = str(err) protected = {} payload = {} @@ -480,7 +722,7 @@ def dkeys_lower(tree: Dict[str, str]) -> Dict[str, str]: def fqdn_in_san_check(logger: logging.Logger, san_list: List[str], fqdn: str) -> bool: """ check if fqdn is in a list of sans """ - logger.debug('fqdn_in_san_check([%s], %s)', san_list, fqdn) + logger.debug('Helper.fqdn_in_san_check([%s], %s)', san_list, fqdn) result = False if fqdn and san_list: @@ -491,15 +733,15 @@ def fqdn_in_san_check(logger: logging.Logger, san_list: List[str], fqdn: str) -> result = True break except Exception: - logger.error('ERROR: fqdn_in_san_check() SAN split failed: {0}'.format(san)) + logger.error('ERROR: fqdn_in_san_check() SAN split failed: %s', san) - logger.debug('fqdn_in_san_check() ended with: {}'.format(result)) + logger.debug('Helper.fqdn_in_san_check() ended with: %s', result) return result def generate_random_string(logger: logging.Logger, length: int) -> str: """ generate random string to be used as name """ - logger.debug('generate_random_string()') + logger.debug('Helper.generate_random_string()') char_set = digits + ascii_letters return ''.join(random.choice(char_set) for _ in range(length)) @@ -526,23 +768,80 @@ def get_url(environ: Dict[str, str], include_path: bool = False) -> str: proto = 'http' if include_path and 'PATH_INFO' in environ: - result = '{0}://{1}{2}'.format(proto, server_name, html.escape(environ['PATH_INFO'])) + result = f'{proto}://{server_name}{html.escape(environ["PATH_INFO"])}' + else: + result = f'{proto}://{server_name}' + return result + + +def header_info_field_validate(logger, csr: str, header_info_field: str, value: str, value_list: List[str]) -> Tuple[str, str]: + """ select value from list""" + logger.debug('Helper.header_info_field_validate(%s)', value) + + value_to_set = None + error = None + # get header info + header_info_value = header_info_lookup(logger, csr, header_info_field, value) + if header_info_value: + if header_info_value in value_list: + value_to_set = header_info_value + else: + error = f'{value} "{header_info_value}" is not allowed' else: - result = '{0}://{1}'.format(proto, server_name) + # header not set, use first value from list + value_to_set = value_list[0] + + logger.debug('Helper.header_info_field_validate(%s) ended with %s/%s', value, value_to_set, error) + return value_to_set, error + + +def header_info_jsonify(logger: logging.Logger, header_info: str) -> Dict[str, str]: + """ jsonify header info""" + logger.debug('Helper.header_info_json_parse()') + + header_info_dic = {} + try: + if isinstance(header_info, list) and 'header_info' in header_info[-1]: + header_info_dic = json.loads(header_info[-1]['header_info']) + except Exception as err: + logger.error('header_info_lookup() could not parse header_info_field: %s', err) + + logger.debug('Helper.header_info_json_parse() ended with: %s', bool(header_info_dic)) + return header_info_dic + + +def header_info_lookup(logger, csr: str, header_info_field, key: str) -> str: + """ lookup header info """ + logger.debug('Helper.header_info_lookup(%s)', key) + + result = None + header_info = header_info_get(logger, csr=csr) + + if header_info: + header_info_dic = header_info_jsonify(logger, header_info) + if header_info_field in header_info_dic: + for ele in header_info_dic[header_info_field].split(' '): + if key in ele.lower(): + result = ele.split('=', 1)[1] + break + else: + logger.error('header_info_lookup() header_info_field not found: %s', header_info_field) + + logger.debug('Helper.header_info_lookup(%s) ended with: %s', key, result) return result -def header_info_get(logger: logging.Logger, csr: str, vlist: List[str] = ('id', 'name', 'header_info')) -> List[str]: +def header_info_get(logger: logging.Logger, csr: str, vlist: List[str] = ('id', 'name', 'header_info'), field_name: str = 'csr') -> List[str]: """ lookup header information """ - logger.debug('header_info_get()') + logger.debug('Helper.header_info_get()') try: from acme_srv.db_handler import DBstore # pylint: disable=c0415 dbstore = DBstore(logger=logger) - result = dbstore.certificates_search('csr', csr, vlist) + result = dbstore.certificates_search(field_name, csr, vlist) except Exception as err: result = [] - logger.error('Helper.header_info_get(): error: {0}'.format(err)) + logger.error('Helper.header_info_get(): error: %s', err) return list(result) @@ -555,7 +854,7 @@ def load_config(logger: logging.Logger = None, mfilter: str = None, cfg_file: st else: cfg_file = os.path.dirname(__file__) + '/' + 'acme_srv.cfg' if logger: - logger.debug('load_config({1}:{0})'.format(mfilter, cfg_file)) + logger.debug('load_config(%s:%s)', mfilter, cfg_file) config = configparser.ConfigParser(interpolation=None) config.optionxform = str config.read(cfg_file, encoding='utf8') @@ -564,7 +863,8 @@ def load_config(logger: logging.Logger = None, mfilter: str = None, cfg_file: st def parse_url(logger: logging.Logger, url: str) -> Dict[str, str]: """ split url into pieces """ - logger.debug('parse_url({0})'.format(url)) + logger.debug('Helper.parse_url()') + url_dic = { 'proto': urlparse(url).scheme, 'host': urlparse(url).netloc, @@ -575,7 +875,7 @@ def parse_url(logger: logging.Logger, url: str) -> Dict[str, str]: def encode_url(logger: logging.Logger, input_string: str) -> str: """ urlencoding """ - logger.debug('encode_url({0})'.format(input_string)) + logger.debug('Helper.encode_url(%s)', input_string) return quote(input_string) @@ -626,7 +926,7 @@ def logger_info(logger: logging.Logger, addr: str, locator: str, dat_dic: Dict[s # remove token from challenge data_dic = _logger_challenges_modify(data_dic) - logger.info('{0} {1} {2}'.format(addr, locator, str(data_dic))) + logger.info('%s %s %s', addr, locator, str(data_dic)) def logger_setup(debug: bool) -> logging.Logger: @@ -654,45 +954,45 @@ def logger_setup(debug: bool) -> logging.Logger: def print_debug(debug: bool, text: str): """ little helper to print debug messages """ if debug: - print('{0}: {1}'.format(datetime.datetime.now(), text)) + print(f'{datetime.datetime.now()}: {text}') def jwk_thumbprint_get(logger: logging.Logger, pub_key: Dict[str, str]) -> str: """ get thumbprint """ - logger.debug('jwk_thumbprint_get()') + logger.debug('Helper.jwk_thumbprint_get()') if pub_key: try: jwkey = jwk.JWK(**pub_key) thumbprint = jwkey.thumbprint() except Exception as err: - logger.error('jwk_thumbprint_get(): error: {0}'.format(err)) + logger.error('jwk_thumbprint_get(): error: %s', err) thumbprint = None else: thumbprint = None - logger.debug('jwk_thumbprint_get() ended with: {0}'.format(thumbprint)) + logger.debug('Helper.jwk_thumbprint_get() ended with: %s', thumbprint) return thumbprint def sha256_hash(logger: logging.Logger, string: str) -> str: """ hash string """ - logger.debug('sha256_hash()') + logger.debug('Helper.sha256_hash()') result = hashlib.sha256(string.encode('utf-8')).digest() - logger.debug('sha256_hash() ended with {0} (base64-encoded)'.format(b64_encode(logger, result))) + logger.debug('Helper.sha256_hash() ended with %s (base64-encoded)', b64_encode(logger, result)) return result def sha256_hash_hex(logger: logging.Logger, string: str) -> str: """ hash string """ - logger.debug('sha256_hash_hex()') + logger.debug('Helper.sha256_hash_hex()') result = hashlib.sha256(string.encode('utf-8')).hexdigest() - logger.debug('sha256_hash_hex() ended with {0}'.format(result)) + logger.debug('Helper.sha256_hash_hex() ended with %s', result) return result def signature_check(logger: logging.Logger, message: str, pub_key: str, json_: bool = False) -> Tuple[bool, str]: """ check JWS """ - logger.debug('signature_check({0})'.format(json_)) + logger.debug('Helper.signature_check(%s)', json_) result = False error = None @@ -701,11 +1001,13 @@ def signature_check(logger: logging.Logger, message: str, pub_key: str, json_: b # load key try: if json_: + logger.debug('Helper.signature_check(): load key from json') jwkey = jwk.JWK.from_json(pub_key) else: + logger.debug('Helper.signature_check(): load plain json') jwkey = jwk.JWK(**pub_key) except Exception as err: - logger.error('load key failed {0}'.format(err)) + logger.error('load key failed %s', err) jwkey = None result = False error = str(err) @@ -718,17 +1020,21 @@ def signature_check(logger: logging.Logger, message: str, pub_key: str, json_: b jwstoken.verify(jwkey) result = True except Exception as err: - logger.error('verify failed {0}'.format(err)) + logger.error('verify failed %s', err) error = str(err) + else: + logger.error('No jwkey extracted') else: + logger.error('No pubkey specified.') error = 'No key specified.' + logger.debug('Helper.signature_check() ended with: %s, %s', result, error) return (result, error) def string_sanitize(logger: logging.Logger, unsafe_str: str) -> str: """ sanitize string """ - logger.debug('string_sanitize()') + logger.debug('Helper.string_sanitize()') allowed_range = set(range(32, 127)) safe_str = '' for char in unsafe_str: @@ -805,7 +1111,7 @@ def dns_server_list_load() -> List[str]: def error_dic_get(logger: logging.Logger) -> Dict[str, str]: """ load acme error messages """ - logger.debug('error_dict_get()') + logger.debug('Helper.error_dict_get()') # this is the main dictionary error_dic = { 'badcsr': 'urn:ietf:params:acme:error:badCSR', @@ -821,7 +1127,8 @@ def error_dic_get(logger: logging.Logger) -> Dict[str, str]: 'unsupportedidentifier': 'urn:ietf:params:acme:error:unsupportedIdentifier', 'ordernotready': 'urn:ietf:params:acme:error:orderNotReady', 'ratelimited': 'urn:ietf:params:acme:error:rateLimited', - 'badrevocationreason': 'urn:ietf:params:acme:error:badRevocationReason'} + 'badrevocationreason': 'urn:ietf:params:acme:error:badRevocationReason', + 'rejectedidentifier': 'urn:ietf:params:acme:error:rejectedIdentifier'} return error_dic @@ -839,7 +1146,7 @@ def patched_create_connection(address: List[str], *args, **kwargs): # pragma: n def proxy_check(logger: logging.Logger, fqdn: str, proxy_server_list: Dict[str, str]) -> str: """ check proxy server """ - logger.debug('proxy_check({0})'.format(fqdn)) + logger.debug('Helper.proxy_check(%s)', fqdn) # remove leading *. proxy_server_list_new = {k.replace('*.', ''): v for k, v in proxy_server_list.items()} @@ -851,20 +1158,20 @@ def proxy_check(logger: logging.Logger, fqdn: str, proxy_server_list: Dict[str, if bool(regex_compiled.search(fqdn)): # parameter is in - set flag accordingly and stop loop proxy = proxy_server_list_new[regex] - logger.debug('proxy_check() match found: fqdn: {0}, regex: {1}'.format(fqdn, regex)) + logger.debug('Helper.proxy_check() match found: fqdn: %s, regex: %s', fqdn, regex) break if '*' in proxy_server_list_new.keys() and not proxy: - logger.debug('proxy_check() wildcard match found: fqdn: {0}'.format(fqdn)) + logger.debug('Helper.proxy_check() wildcard match found: fqdn: %s', fqdn) proxy = proxy_server_list_new['*'] - logger.debug('proxy_check() ended with {0}'.format(proxy)) + logger.debug('Helper.proxy_check() ended with %s', proxy) return proxy def url_get_with_own_dns(logger: logging.Logger, url: str, verify: bool = True) -> str: """ request by using an own dns resolver """ - logger.debug('url_get_with_own_dns({0})'.format(url)) + logger.debug('Helper.url_get_with_own_dns(%s)', url) # patch an own connection handler into URL lib # pylint: disable=W0212 connection._orig_create_connection = connection.create_connection @@ -874,7 +1181,7 @@ def url_get_with_own_dns(logger: logging.Logger, url: str, verify: bool = True) result = req.text except Exception as err_: result = None - logger.error('url_get_with_own_dns error: {0}'.format(err_)) + logger.error('Helper.url_get_with_own_dns error: %s', err_) # cleanup connection.create_connection = connection._orig_create_connection return result @@ -888,7 +1195,7 @@ def allowed_gai_family() -> socket.AF_INET: def url_get_with_default_dns(logger: logging.Logger, url: str, proxy_list: Dict[str, str], verify: bool, timeout: int) -> str: """ http get with default dns server """ - logger.debug('url_get_with_default_dns({0}) vrf={1}, timout:{2}'.format(url, verify, timeout)) + logger.debug('Helper.url_get_with_default_dns(%s) vrf=%s, timout:%s', url, verify, timeout) # we need to tweak headers and url for ipv6 addresse (headers, url) = v6_adjust(logger, url) @@ -897,9 +1204,9 @@ def url_get_with_default_dns(logger: logging.Logger, url: str, proxy_list: Dict[ req = requests.get(url, verify=verify, timeout=timeout, headers=headers, proxies=proxy_list) result = req.text except Exception as err_: - logger.debug('url_get({0}): error'.format(err_)) + logger.debug('Helper.url_get(%s): error', err_) # force fallback to ipv4 - logger.debug('url_get({0}): fallback to v4'.format(url)) + logger.debug('Helper.url_get(%s): fallback to v4', url) old_gai_family = urllib3_cn.allowed_gai_family try: urllib3_cn.allowed_gai_family = allowed_gai_family @@ -907,7 +1214,7 @@ def url_get_with_default_dns(logger: logging.Logger, url: str, proxy_list: Dict[ result = req.text except Exception as err: result = None - logger.error('url_get error: {0}'.format(err)) + logger.error('url_get error: %s', err) urllib3_cn.allowed_gai_family = old_gai_family return result @@ -915,7 +1222,7 @@ def url_get_with_default_dns(logger: logging.Logger, url: str, proxy_list: Dict[ def url_get(logger: logging.Logger, url: str, dns_server_list: List[str] = None, proxy_server=None, verify=True, timeout=20) -> str: """ http get """ - logger.debug('url_get({0}) vrf={1}, timout:{2}'.format(url, verify, timeout)) + logger.debug('Helper.url_get(%s) vrf=%s, timout:%s', url, verify, timeout) # pylint: disable=w0621 # configure proxy servers if specified if proxy_server: @@ -927,13 +1234,13 @@ def url_get(logger: logging.Logger, url: str, dns_server_list: List[str] = None, else: result = url_get_with_default_dns(logger, url, proxy_list, verify, timeout) - logger.debug('url_get() ended with: {0}'.format(result)) + logger.debug('Helper.url_get() ended with: %s', result) return result def txt_get(logger: logging.Logger, fqdn: str, dns_srv: List[str] = None) -> List[str]: """ dns query to get the TXt record """ - logger.debug('txt_get({0}: {1})'.format(fqdn, dns_srv)) + logger.debug('Helper.txt_get(%s: %s)', fqdn, dns_srv) # rewrite dns resolver if configured if dns_srv: @@ -945,14 +1252,14 @@ def txt_get(logger: logging.Logger, fqdn: str, dns_srv: List[str] = None) -> Lis for rrecord in response: txt_record_list.append(rrecord.strings[0]) except Exception as err_: - logger.error('txt_get() error: {0}'.format(err_)) - logger.debug('txt_get() ended with: {0}'.format(txt_record_list)) + logger.error('txt_get() error: %s', err_) + logger.debug('Helper.txt_get() ended with: %s', txt_record_list) return txt_record_list def uts_now(): """ unixtimestamp in utc """ - return calendar.timegm(datetime.datetime.utcnow().utctimetuple()) + return calendar.timegm(datetime.datetime.now(datetime.timezone.utc).utctimetuple()) def uts_to_date_utc(uts: int, tformat: str = '%Y-%m-%dT%H:%M:%SZ') -> str: @@ -990,12 +1297,13 @@ def datestr_to_date(datestr: str, tformat: str = '%Y-%m-%dT%H:%M:%S') -> str: def proxystring_convert(logger: logging.Logger, proxy_server: str) -> Tuple[str, str, str]: """ convert proxy string """ - logger.debug('proxystring_convert({0})'.format(proxy_server)) + logger.debug('Helper.proxystring_convert(%s)', proxy_server) + proxy_proto_dic = {'http': socks.PROXY_TYPE_HTTP, 'socks4': socks.PROXY_TYPE_SOCKS4, 'socks5': socks.PROXY_TYPE_SOCKS5} try: (proxy_proto, proxy) = proxy_server.split('://') except Exception: - logger.error('proxystring_convert(): error splitting proxy_server string: {0}'.format(proxy_server)) + logger.error('proxystring_convert(): error splitting proxy_server string: %s', proxy_server) proxy = None proxy_proto = None @@ -1003,7 +1311,7 @@ def proxystring_convert(logger: logging.Logger, proxy_server: str) -> Tuple[str, try: (proxy_addr, proxy_port) = proxy.split(':') except Exception: - logger.error('proxystring_convert(): error splitting proxy into host/port: {0}'.format(proxy)) + logger.error('proxystring_convert(): error splitting proxy into host/port: %s', proxy) proxy_addr = None proxy_port = None else: @@ -1014,25 +1322,25 @@ def proxystring_convert(logger: logging.Logger, proxy_server: str) -> Tuple[str, try: proto_string = proxy_proto_dic[proxy_proto] except Exception: - logger.error('proxystring_convert(): unknown proxy protocol: {0}'.format(proxy_proto)) + logger.error('proxystring_convert(): unknown proxy protocol: %s', proxy_proto) proto_string = None else: - logger.error('proxystring_convert(): proxy_proto ({0}), proxy_addr ({1}) or proxy_port ({2}) missing'.format(proxy_proto, proxy_addr, proxy_port)) + logger.error('proxystring_convert(): proxy_proto (%s), proxy_addr (%s) or proxy_port (%s) missing', proxy_proto, proxy_addr, proxy_port) proto_string = None try: proxy_port = int(proxy_port) except Exception: - logger.error('proxystring_convert(): unknown proxy port: {0}'.format(proxy_port)) + logger.error('proxystring_convert(): unknown proxy port: %s', proxy_port) proxy_port = None - logger.debug('proxystring_convert() ended with {0}, {1}, {2}'.format(proto_string, proxy_addr, proxy_port)) + logger.debug('Helper.proxystring_convert() ended with %s, %s, %s', proto_string, proxy_addr, proxy_port) return (proto_string, proxy_addr, proxy_port) def servercert_get(logger: logging.Logger, hostname: str, port: int = 443, proxy_server: str = None, sni: str = None) -> str: """ get server certificate from an ssl connection """ - logger.debug('servercert_get({0}:{1})'.format(hostname, port)) + logger.debug('Helper.servercert_get(%s:%s)', hostname, port) pem_cert = None @@ -1051,7 +1359,12 @@ def servercert_get(logger: logging.Logger, hostname: str, port: int = 443, proxy context.options |= ssl.PROTOCOL_TLS_CLIENT context.set_alpn_protocols(["acme-tls/1"]) # reject insecure ssl version - context.minimum_version = ssl.TLSVersion.TLSv1_2 + try: + # this does not work on RH8 + context.minimum_version = ssl.TLSVersion.TLSv1_2 + except Exception: # pragma: no cover + logger.error('servercert_get(): minimum_version not supported') + context.options |= ssl.OP_NO_SSLv3 context.options |= ssl.OP_NO_TLSv1 context.options |= ssl.OP_NO_TLSv1_1 @@ -1059,36 +1372,36 @@ def servercert_get(logger: logging.Logger, hostname: str, port: int = 443, proxy if proxy_server: (proxy_proto, proxy_addr, proxy_port) = proxystring_convert(logger, proxy_server) if proxy_proto and proxy_addr and proxy_port: - logger.debug('servercert_get() configure proxy') + logger.debug('servercert_get(): configure proxy') sock.setproxy(proxy_proto, proxy_addr, port=proxy_port) try: sock.connect((hostname, port)) with context.wrap_socket(sock, server_hostname=sni) as sslsock: - logger.debug('servercert_get(): {0}:{1}:{2} version: {3}'.format(hostname, sni, port, sslsock.version())) + logger.debug('servercert_get(): %s:%s:%s version: %s', hostname, sni, port, sslsock.version()) der_cert = sslsock.getpeercert(True) # from binary DER format to PEM if der_cert: pem_cert = ssl.DER_cert_to_PEM_cert(der_cert) except Exception as err_: - logger.error('servercert_get() failed with: {0}'.format(err_)) + logger.error('servercert_get() failed with: %s', err_) pem_cert = None if pem_cert: - logger.debug('servercert_get() ended with: {0}'.format(b64_encode(logger, convert_string_to_byte(pem_cert)))) + logger.debug('Helper.servercert_get() ended with: %s', b64_encode(logger, convert_string_to_byte(pem_cert))) else: - logger.debug('servercert_get() ended with: None') + logger.debug('Helper.servercert_get() ended with: None') return pem_cert def validate_csr(logger: logging.Logger, order_dic: Dict[str, str], _csr) -> bool: """ validate certificate signing request against order""" - logger.debug('validate_csr({0})'.format(order_dic)) + logger.debug('Helper.validate_csr(%s)', order_dic) return True def validate_email(logger: logging.Logger, contact_list: List[str]) -> bool: """ validate contact against RFC608""" - logger.debug('validate_email()') + logger.debug('Helper.validate_email()') result = True pattern = r"^[A-Za-z0-9\.\+_-]+@[A-Za-z]+[A-Za-z0-9\._-]+[A-Za-z0-9]+\.[a-zA-Z\.]+[a-zA-Z]+$" # check if we got a list or single address @@ -1097,14 +1410,64 @@ def validate_email(logger: logging.Logger, contact_list: List[str]) -> bool: contact = contact.replace('mailto:', '') contact = contact.lstrip() tmp_result = bool(re.search(pattern, contact)) - logger.debug('# validate: {0} result: {1}'.format(contact, tmp_result)) + logger.debug('# validate: %s result: %s', contact, tmp_result) if not tmp_result: result = tmp_result else: contact_list = contact_list.replace('mailto:', '') contact_list = contact_list.lstrip() result = bool(re.search(pattern, contact_list)) - logger.debug('# validate: {0} result: {1}'.format(contact_list, result)) + logger.debug('Helper.validate_email() of: %s emded with result: %s', contact_list, result) + return result + + +def validate_identifier(logger: logging.Logger, id_type: str, identifier: str, tnauthlist_support: bool = False) -> bool: + """ validate identifier """ + logger.debug('Helper.validate_identifier()') + + result = False + if identifier: + if id_type == 'dns': + result = validate_fqdn(logger, identifier) + elif id_type == 'ip': + result = validate_ip(logger, identifier) + elif id_type == 'tnauthlist' and tnauthlist_support: + result = True + + logger.debug('Helper.validate_identifier() ended with: %s', result) + return result + + +def validate_ip(logger: logging.Logger, ip: str) -> bool: + """ validate ip address """ + logger.debug('Helper.validate_ip()') + try: + ipaddress.ip_address(ip) + result = True + except ValueError: + result = False + logger.debug('Helper.validate_ip() ended with: %s', result) + return result + + +def validate_fqdn(logger: logging.Logger, fqdn: str) -> bool: + """ validate fqdn """ + logger.debug('Helper.validate_fqdn()') + + result = False + regex = r"^(([a-z0-9]\-*[a-z0-9]*){1,63}\.?){1,255}$" + p = re.compile(regex) + if re.search(p, fqdn): + result = True + + if not result: + logger.debug('Helper.validate_fqdn(): invalid fqdn. Check for wildcard : %s', fqdn) + regex = r"^\*\.[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$" + p = re.compile(regex) + if re.search(p, fqdn): + result = True + + logger.debug('Helper.validate_fqdn() ended with: %s', result) return result @@ -1120,7 +1483,7 @@ def handle_exception(exc_type, exc_value, exc_traceback): # pragma: no cover def pembundle_to_list(logger: logging.Logger, pem_bundle: str) -> List[str]: """ split pem bundle into a list of certificates """ - logger.debug('pembundle_to_list()') + logger.debug('Helper.pembundle_to_list()') cert_list = [] pem_data = "" if '-----BEGIN CERTIFICATE-----' in pem_bundle: @@ -1132,13 +1495,13 @@ def pembundle_to_list(logger: logging.Logger, pem_bundle: str) -> List[str]: pem_data += line + "\n" if pem_data: cert_list.append(pem_data) - logger.debug('pembundle_to_list() returned {0} certificates'.format(len(cert_list))) + logger.debug('Helper.pembundle_to_list() returned %s certificates', cert_list) return cert_list def certid_asn1_get(logger: logging.Logger, cert_pem: str, issuer_pem: str) -> str: """ get renewal information from certificate """ - logger.debug('certid_asn1_get()') + logger.debug('Helper.certid_asn1_get()') cert = load_pem_x509_certificate(convert_string_to_byte(cert_pem)) issuer = load_pem_x509_certificate(convert_string_to_byte(issuer_pem)) @@ -1156,7 +1519,7 @@ def certid_asn1_get(logger: logging.Logger, cert_pem: str, issuer_pem: str) -> s def certid_hex_get(logger: logging.Logger, renewal_info: str) -> Tuple[str, str]: """ get certid in hex from renewal_info field """ - logger.debug('certid_hex_get()') + logger.debug('Helper.certid_hex_get()') renewal_info_b64 = b64_url_recode(logger, renewal_info) renewal_info_hex = b64_decode(logger, renewal_info_b64).hex() @@ -1165,13 +1528,13 @@ def certid_hex_get(logger: logging.Logger, renewal_info: str) -> Tuple[str, str] mda, certid_renewal = renewal_info_hex.split('0420', 1) mda = mda[4:] - logger.debug('certid_hex_get() endet with {0}'.format(certid_renewal)) + logger.debug('Helper.certid_hex_get() endet with %s', certid_renewal) return mda, certid_renewal def certid_check(logger: logging.Logger, renewal_info: str, certid_database: str) -> str: """ compare certid with renewal info """ - logger.debug('certid_check()') + logger.debug('Helper.certid_check()') renewal_info_b64 = b64_url_recode(logger, renewal_info) renewal_info_hex = b64_decode(logger, renewal_info_b64).hex() @@ -1180,13 +1543,13 @@ def certid_check(logger: logging.Logger, renewal_info: str, certid_database: str _header, certid_renewal = renewal_info_hex.split('0420', 1) result = certid_renewal == certid_database - logger.debug('certid_check() ended with: {0}'.format(result)) + logger.debug('Helper.certid_check() ended with: %s', result) return result def ip_validate(logger: logging.Logger, ip_addr: str) -> Tuple[str, bool]: """ validate ip address """ - logger.debug('ip_validate({0})'.format(ip_addr)) + logger.debug('Helper.ip_validate(%s)', ip_addr) try: reverse_pointer = ipaddress.ip_address(ip_addr).reverse_pointer @@ -1194,13 +1557,13 @@ def ip_validate(logger: logging.Logger, ip_addr: str) -> Tuple[str, bool]: except ValueError: reverse_pointer = None invalid = True - logger.debug('ip_validate() ended with: {0}:{1}'.format(reverse_pointer, invalid)) + logger.debug('Helper.ip_validate() ended with: %s:%s', reverse_pointer, invalid) return (reverse_pointer, invalid) def v6_adjust(logger: logging.Logger, url: str) -> Tuple[Dict[str, str], str]: """ corner case for v6 addresses """ - logger.debug('v6_adjust({0})'.format(url)) + logger.debug('Helper.v6_adjust(%s)', url) headers = {'Connection': 'close', 'Accept-Encoding': 'gzip', 'User-Agent': USER_AGENT} @@ -1209,25 +1572,348 @@ def v6_adjust(logger: logging.Logger, url: str) -> Tuple[Dict[str, str], str]: # adjust headers and url in case we have an ipv6address if ipv6_chk(logger, url_dic['host']): headers['Host'] = url_dic['host'] - url = '{0}://[{1}]/{2}'.format(url_dic['proto'], url_dic['host'], url_dic['path']) + url = f"{url_dic['proto']}://[{url_dic['host']}]/{url_dic['path']}" - logger.debug('v6_adjust() ended') + logger.debug('Helper.v6_adjust() ended') return (headers, url) def ipv6_chk(logger: logging.Logger, address: str) -> bool: """ check if an address is ipv6 """ - logger.debug('ipv6_chk({0})'.format(address)) + logger.debug('Helper.ipv6_chk(%s)', address) try: # we need to set a host header and braces for ipv6 headers and if isinstance(ipaddress.ip_address(address), ipaddress.IPv6Address): - logger.debug('v6_adjust(}): ipv6 address detected') + logger.debug('Helper.v6_adjust(}): ipv6 address detected') result = True else: result = False except Exception: result = False - logger.debug('ipv6_chk() ended with {0}'.format(result)) + logger.debug('Helper.ipv6_chk() ended with %s', result) + return result + + +def domainlist_check(logger, entry: str, list_: List[str], toggle: bool = False) -> bool: + """ check string against list """ + logger.debug('Helper.domainlist_check(%s:%s)', entry, toggle) + # print(list_) + logger.debug('Helper.check against list: %s', list_) + + # default setting + check_result = False + + if entry: + if list_: + for regex in list_: + # check entry + check_result = domainlist_entry_check(logger, entry, regex, check_result) + else: + # empty list, flip parameter to make the check successful + check_result = True + + if toggle: + # toggle result if this is a blacklist + check_result = not check_result + + logger.debug('Helper.domainlist_check() ended with: %s', check_result) + return check_result + + +def domainlist_entry_check(logger, entry: str, regex: str, check_result: bool) -> bool: + """ check string against regex """ + logger.debug('Helper.domainlist_entry_check(%s/%s):', entry, regex) + + if regex.startswith('*.'): + regex = regex.replace('*.', '.') + regex_compiled = re.compile(regex) + + if bool(regex_compiled.search(entry)): + # parameter is in set flag accordingly and stop loop + check_result = True + + logger.debug('Helper.domainlist_entry_check() ended with: %s', check_result) + return check_result + + +def allowed_domainlist_check(logger: logging.Logger, csr, allowed_domain_list: List[str]) -> bool: + """ check if domain is in allowed domain list """ + logger.debug('Helper.allowed_domainlist_check(%s)') + + result = False + (san_list, check_list) = sancheck_lists_create(logger, csr) + + # go over the san list and check each entry + for san in san_list: + check_list.append(domainlist_check(logger, san, allowed_domain_list)) + + if check_list: + # cover a cornercase with empty checklist (no san, no cn) + if False in check_list: + result = False + else: + result = True + + logger.debug('Helper.allowed_domainlist_check() ended with: %s', result) return result + + +def sancheck_lists_create(logger, csr: str) -> Tuple[List[str], List[str]]: + """ create lists for san check """ + logger.debug('Helper.sancheck_lists_create()') + + check_list = [] + san_list = [] + + # get sans and build a list + _san_list = csr_san_get(logger, csr) + + if _san_list: + for san in _san_list: + try: + # SAN list must be modified/filtered) + (_san_type, san_value) = san.lower().split(':') + san_list.append(san_value) + except Exception: + # force check to fail as something went wrong during parsing + check_list.append(False) + logger.debug('Helper.sancheck_lists_create(): san_list parsing failed at entry: $s', san) + + # get common name and attach it to san_list + cn = csr_cn_get(logger, csr) + + if cn: + cn = cn.lower() + if cn not in san_list: + # append cn to san_list + logger.debug('Helper.sancheck_lists_create()): append cn to san_list') + san_list.append(cn) + + return (san_list, check_list) + + +def eab_profile_header_info_check(logger: logging.Logger, cahandler, csr: str, handler_hifield: str = 'profile_name', ) -> str: + """ check profile """ + logger.debug('Helper.eab_profile_header_info_check()') + + if cahandler.eab_profiling: + + if cahandler.eab_handler: + # profiling enabled - check profile + error = eab_profile_check(logger, cahandler, csr, handler_hifield) + else: + logger.error('Helper.eab_profile_header_info_check(): eab_profiling enabled but no handler defined') + error = 'Eab_profiling enabled but no handler defined' + + elif cahandler.header_info_field: + # no profiling - parse profileid from http_header + hil_value = header_info_lookup(logger, csr, cahandler.header_info_field, handler_hifield) + if hil_value: + logger.debug('Helper.eab_profile_header_info_check(): setting %s to %s', handler_hifield, hil_value) + setattr(cahandler, handler_hifield, hil_value) + error = None + else: + logger.debug('Helper.eab_profile_header_info_check(): no header_info field found') + error = None + else: + # no profiling - no header_info_field + error = None + + logger.debug('Helper.eab_profile_header_info_check() ended with %s', error) + return error + + +def cn_validate(logger: logging.Logger, cn: str) -> bool: + """ validate common name """ + logger.debug('Helper.cn_validate(%s)', cn) + + error = False + if cn: + # check if CN is a valid IP address + result = validate_ip(logger, cn) + if not result: + # check if CN is a valid fqdn + result = validate_fqdn(logger, cn) + if not result: + error = 'Profile subject check failed: CN validation failed' + else: + error = 'Profile subject check failed: commonName missing' + + logger.debug('Helper.cn_validate() ended with: %s', error) + return error + + +def eab_profile_subject_string_check(logger: logging.Logger, profile_subject_dic, key: str, value: str) -> str: + """ check if a for a string value taken from profile if its a variable inside a class and apply value """ + logger.debug('Helper.eab_profile_subject_string_check(): string: key: %s, value: %s', key, value) + + error = False + if key == 'commonName': + # check if CN is a valid IP address or fqdn + error = cn_validate(logger, value) + elif key in profile_subject_dic: + if isinstance(profile_subject_dic[key], str) and (value == profile_subject_dic[key] or profile_subject_dic[key] == '*'): + logger.debug('Helper.eab_profile_subject_check() successul for string : %s', key) + del profile_subject_dic[key] + elif isinstance(profile_subject_dic[key], list) and value in profile_subject_dic[key]: + logger.debug('Helper.eab_profile_subject_check() successul for list : %s', key) + del profile_subject_dic[key] + else: + logger.error('Helper.eab_profile_subject_check() failed for: %s: value: %s expected: %s', key, value, profile_subject_dic[key]) + error = f'Profile subject check failed for {key}' + else: + logger.error('Helper.eab_profile_subject_check() failed for: %s', key) + error = f'Profile subject check failed for {key}' + + logger.debug('Helper.eab_profile_subject_string_check() ended') + return error + + +def eab_profile_subject_check(logger: logging.Logger, csr: str, profile_subject_dic: str) -> str: + """ check subject against profile information""" + logger.debug('Helper.eab_profile_subject_check()') + error = None + + # get subject from csr + subject_dic = csr_subject_get(logger, csr) + + # check if all profile subject entries are in csr + for key, value in subject_dic.items(): + error = eab_profile_subject_string_check(logger, profile_subject_dic, key, value) + if error: + break + + # check if we have any entries left in the profile_subject_dic + if not error and profile_subject_dic: + logger.error('Helper.eab_profile_subject_check() failed for: %s', list(profile_subject_dic.keys())) + error = 'Profile subject check failed' + + logger.debug('Helper.eab_profile_subject_check() ended with: %s', error) + return error + + +def eab_profile_check(logger: logging.Logger, cahandler, csr: str, handler_hifield: str) -> str: + """ check eab profile""" + logger.debug('Helper.eab_profile_check()') + + result = None + with cahandler.eab_handler(logger) as eab_handler: + eab_profile_dic = eab_handler.eab_profile_get(csr) + for key, value in eab_profile_dic.items(): + if key == 'subject': + result = eab_profile_subject_check(logger, csr, value) + elif isinstance(value, str): + eab_profile_string_check(logger, cahandler, key, value) + elif isinstance(value, list): + # check if we need to execute a function from the handler + if 'eab_profile_list_check' in dir(cahandler): + result = cahandler.eab_profile_list_check(eab_handler, csr, key, value) + else: + result = eab_profile_list_check(logger, cahandler, eab_handler, csr, key, value) + if result: + break + + # we need to reject situations where profiling is enabled but the header_hifiled is not defined in json + if cahandler.header_info_field and handler_hifield not in eab_profile_dic: + hil_value = header_info_lookup(logger, csr, cahandler.header_info_field, handler_hifield) + if hil_value: + # setattr(self, handler_hifield, hil_value) + result = f'header_info field "{handler_hifield}" is not allowed by profile' + + logger.debug('Helper.eab_profile_check() ended with: %s', result) + return result + + +def eab_profile_list_check(logger, cahandler, eab_handler, csr, key, value): + """ check if a for a list value taken from profile if its a variable inside a class and apply value """ + logger.debug('Helper.eab_profile_list_check(): list: key: %s, value: %s', key, value) + + result = None + if hasattr(cahandler, key) and key != 'allowed_domainlist': + new_value, error = header_info_field_validate(logger, csr, cahandler.header_info_field, key, value) + if new_value: + logger.debug('Helper.eab_profile_list_check(): setting attribute: %s to %s', key, new_value) + setattr(cahandler, key, new_value) + else: + result = error + elif key == 'allowed_domainlist': + # check if csr contains allowed domains + error = eab_handler.allowed_domains_check(csr, value) + if error: + result = error + else: + logger.error('Helper.eab_profile_list_check(): ignore list attribute: key: %s value: %s', key, value) + + logger.debug('Helper.eab_profile_list_check() ended with: %s', result) + return result + + +def eab_profile_string_check(logger, cahandler, key, value): + """ check if a for a string value taken from profile if its a variable inside a class and apply value """ + logger.debug('Helper.eab_profile_string_check(): string: key: %s, value: %s', key, value) + + if hasattr(cahandler, key): + logger.debug('Helper.eab_profile_string_check(): setting attribute: %s to %s', key, value) + setattr(cahandler, key, value) + else: + logger.error('Helper.eab_profile_string_check(): ignore string attribute: key: %s value: %s', key, value) + + logger.debug('Helper.eab_profile_string_check() ended') + + +def request_operation(logger: logging.Logger, headers: Dict[str, str] = None, proxy: Dict[str, str] = None, timeout: int = 20, url: str = None, session=requests, method: str = 'GET', payload: Dict[str, str] = None): + """ check if a for a string value taken from profile if its a variable inside a class and apply value """ + logger.debug('Helper.api_operation(): method: %s', method) + + try: + if method.lower() == 'get': + api_response = session.get(url=url, headers=headers, proxies=proxy, timeout=timeout) + elif method.lower() == 'post': + api_response = session.post(url=url, headers=headers, proxies=proxy, timeout=timeout, json=payload) + elif method.lower() == 'put': + api_response = session.put(url=url, headers=headers, proxies=proxy, timeout=timeout, json=payload) + else: + logger.error('unknown request method: %s', method) + api_response = None + + code = api_response.status_code + if api_response.text: + try: + content = api_response.json() + except Exception as err_: + logger.error('request_operation returned error during json parsing: %s', err_) + content = str(err_) + else: + content = None + + except Exception as err_: + logger.error('request_operation returned error: %s', err_) + code = 500 + content = str(err_) + + logger.debug('Helper.request_operation() ended with: %s', code) + return code, content + + +def csr_cn_lookup(logger: logging.Logger, csr: str) -> str: + """ lookup CN/ 1st san from CSR """ + logger.debug('CAhandler._csr_cn_lookup()') + + csr_cn = csr_cn_get(logger, csr) + if not csr_cn: + # lookup first san + san_list = csr_san_get(logger, csr) + if san_list and len(san_list) > 0: + for san in san_list: + try: + csr_cn = san.split(':')[1] + break + except Exception as err: + logger.error('CAhandler._csr_cn_lookup() split failed: %s', err) + else: + logger.error('CAhandler._csr_cn_lookup() no SANs found in CSR') + + logger.debug('CAhandler._csr_cn_lookup() ended with: %s', csr_cn) + return csr_cn diff --git a/acme_srv/housekeeping.py b/acme_srv/housekeeping.py index 01649f4c..fd41a71e 100644 --- a/acme_srv/housekeeping.py +++ b/acme_srv/housekeeping.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- -# pylint: disable=c0209 """ Housekeeping class """ from __future__ import print_function import csv @@ -37,7 +36,7 @@ def _accountlist_get(self) -> Dict[str, str]: try: result = self.dbstore.accountlist_get() except Exception as err_: - self.logger.critical('acme2certifier database error in Housekeeping._accountlist_get(): {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Housekeeping._accountlist_get(): %s', err_) result = None return result @@ -47,7 +46,7 @@ def _certificatelist_get(self) -> Dict[str, str]: try: result = self.dbstore.certificatelist_get() except Exception as err_: - self.logger.critical('acme2certifier database error in Housekeeping.certificatelist_get(): {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Housekeeping.certificatelist_get(): %s', err_) result = None return result @@ -68,7 +67,7 @@ def _cliaccounts_list(self, silent: bool = True) -> Dict[str, str]: try: result = self.dbstore.cliaccountlist_get() except Exception as err_: - self.logger.critical('acme2certifier database error in Housekeeping._cliaccounts_list(): {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Housekeeping._cliaccounts_list(): %s', err_) result = None if result and not silent: self._cliaccounts_format(result) @@ -78,14 +77,14 @@ def _cliaccounts_format(self, result_list: List[str]): """ format cliaccount report """ self.logger.debug('Housekeeping._cliaccounts_format()') try: - print('\n{0}|{1}|{2}|{3}|{4}|{5}'.format('Name'.ljust(15), 'Contact'.ljust(20), 'cliadm'.ljust(6), 'repadm'.ljust(6), 'certadm'.ljust(7), 'Created at'.ljust(20))) + print(f"\n{'Name'.ljust(15)}|{'Contact'.ljust(20)}|{'cliadm'.ljust(6)}|{'repadm'.ljust(6)}|{'certadm'.ljust(7)}|{'Created at'.ljust(20)}") print('-' * 78) for account in sorted(result_list, key=lambda k: k['id']): - print('{0}|{1}|{2}|{3}|{4}|{5}'.format(account['name'][:15].ljust(15), account['contact'][:20].ljust(20), str(bool(account['cliadmin'])).ljust(6), str(bool(account['reportadmin'])).ljust(6), str(bool(account['certificateadmin'])).ljust(7), account['created_at'].ljust(20))) + print(f"{account['name'][:15].ljust(15)}|{account['contact'][:20].ljust(20)}|{str(bool(account['cliadmin'])).ljust(6)}|{str(bool(account['reportadmin'])).ljust(6)}|{str(bool(account['certificateadmin'])).ljust(7)}|{account['created_at'].ljust(20)}") print('\n') except Exception as err: self.logger.error('acme2certifier error in Housekeeping._cliaccounts_format()') - self.logger.error('acme2certifier error in Housekeeping._cliaccounts_format(): {0}'.format(err)) + self.logger.error('acme2certifier error in Housekeeping._cliaccounts_format(): %s', err) def _report_get(self, payload: Dict[str, str]) -> Tuple[Dict[str, str], int, str, str]: """ create report """ @@ -130,7 +129,7 @@ def _clireport_get(self, payload: Dict[str, str], permissions_dic: Dict[str, str message = self.error_msg_dic['unauthorized'] detail = 'No permissions to download reports' - self.logger.debug('Housekeeping._clireport_get() returned with: {0}/{1}'.format(code, detail)) + self.logger.debug('Housekeeping._clireport_get() returned with: %s/%s', code, detail) return (code, message, detail, response_dic) def _config_load(self): @@ -240,7 +239,7 @@ def _data_dic_build(self, config_dic: Dict[str, str]) -> Dict[str, str]: try: data_dic.update(config_dic['permissions']) except Exception as err: - self.logger.error('acme2certifier error in Housekeeping._data_dic_build(): {0}'.format(err)) + self.logger.error('acme2certifier error in Housekeeping._data_dic_build(): %s', err) if 'jwk' in config_dic: data_dic['jwk'] = json.dumps(config_dic['jwk']) @@ -266,12 +265,12 @@ def _fieldlist_normalize(self, field_list: List[str], prefix: str) -> Dict[str, f_list = field.split('__') # items from selected list which do not have a table reference get prefix added if len(f_list) == 1: - new_field = '{0}.{1}'.format(prefix, field) + new_field = f'{prefix}.{field}' elif f_list[-2] == 'status' and len(f_list) >= 3: # status fields have one reference more - new_field = '{0}.{1}.{2}'.format(f_list[-3], f_list[-2], f_list[-1]) + new_field = f'{f_list[-3]}.{f_list[-2]}.{f_list[-1]}' else: - new_field = '{0}.{1}'.format(f_list[-2], f_list[-1]) + new_field = f'{f_list[-2]}.{f_list[-1]}' field_dic[field] = new_field return field_dic @@ -430,7 +429,7 @@ def _to_list(self, field_list: List[str], cert_list: List[str]) -> List[str]: # append list to output csv_list.append(tmp_list) - self.logger.debug('Housekeeping._to_list() ended with {0} entries'.format(len(csv_list))) + self.logger.debug('Housekeeping._to_list() ended with %s entries', len(csv_list)) return csv_list def accountreport_get(self, report_format: str = 'csv', report_name: str = None, nested: bool = False) -> List[str]: @@ -445,18 +444,18 @@ def accountreport_get(self, report_format: str = 'csv', report_name: str = None, account_list = self._convert_data(account_list) if account_list: - self.logger.debug('output to dump: {0}.{1}'.format(report_name, report_format)) + self.logger.debug('output to dump: %s.%s', report_name, report_format) if report_format == 'csv': self.logger.debug('Housekeeping.certreport_get() dump in csv-format') csv_list = self._to_list(field_list, account_list) account_list = csv_list if report_name: - self._csv_dump('{0}.{1}'.format(report_name, report_format), csv_list) + self._csv_dump(f'{report_name}.{report_format}', csv_list) elif report_format == 'json': if nested: account_list = self._to_acc_json(account_list) if report_name: - self._json_dump('{0}.{1}'.format(report_name, report_format), account_list) + self._json_dump(f'{report_name}.{report_format}', account_list) return account_list @@ -478,17 +477,17 @@ def certreport_get(self, report_format: str = 'csv', report_name: str = None) -> field_list.insert(8, 'certificate.expire_date') if cert_list: - self.logger.debug('Prepare output in: {0} format'.format(report_format)) + self.logger.debug('Prepare output in: %s format', report_format) if report_format == 'csv': self.logger.debug('Housekeeping.certreport_get(): Dump in csv-format') csv_list = self._to_list(field_list, cert_list) cert_list = csv_list if report_name: - self._csv_dump('{0}.{1}'.format(report_name, report_format), csv_list) + self._csv_dump(f'{report_name}.{report_format}', csv_list) elif report_format == 'json': self.logger.debug('Housekeeping.certreport_get(): Dump in json-format') if report_name: - self._json_dump('{0}.{1}'.format(report_name, report_format), cert_list) + self._json_dump(f'{report_name}.{report_format}', cert_list) else: self.logger.info('Housekeeping.certreport_get(): No dump just return report') @@ -519,10 +518,10 @@ def certificates_cleanup(self, uts: int = None, purge: bool = False, report_form if report_format == 'csv': self.logger.debug('Housekeeping.certificates_cleanup(): Dump in csv-format') csv_list = self._to_list(field_list, cert_list) - self._csv_dump('{0}.{1}'.format(report_name, report_format), csv_list) + self._csv_dump(f'{report_name}.{report_format}', csv_list) elif report_format == 'json': self.logger.debug('Housekeeping.certificates_cleanup(): Dump in json-format') - self._json_dump('{0}.{1}'.format(report_name, report_format), cert_list) + self._json_dump(f'{report_name}.{report_format}', cert_list) else: self.logger.debug('Housekeeping.certificates_cleanup(): No dump just return report') else: @@ -554,13 +553,13 @@ def cli_usermgr(self, config_dic: Dict[str, str]) -> int: self.logger.error('acme2certifier error in Housekeeping.cli_usermgr(): data incomplete') except Exception as err_: - self.logger.critical('acme2certifier database error in Housekeeping.cli_usermgr(): {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Housekeeping.cli_usermgr(): %s', err_) return result def authorizations_invalidate(self, uts: int = uts_now(), report_format: str = 'csv', report_name: str = None): """ authorizations cleanup based on expiry date """ - self.logger.debug('Housekeeping.authorization_invalidate({0})'.format(uts)) + self.logger.debug('Housekeeping.authorization_invalidate(%s)', uts) with Authorization(self.debug, None, self.logger) as authorization: # get expired orders @@ -576,10 +575,10 @@ def authorizations_invalidate(self, uts: int = uts_now(), report_format: str = ' if report_format == 'csv': self.logger.debug('Housekeeping.authorizations_invalidate(): Dump in csv-format') csv_list = self._to_list(field_list, authorization_list) - self._csv_dump('{0}.{1}'.format(report_name, report_format), csv_list) + self._csv_dump(f'{report_name}.{report_format}', csv_list) elif report_format == 'json': self.logger.debug('Housekeeping.authorizations_invalidate(): Dump in json-format') - self._json_dump('{0}.{1}'.format(report_name, report_format), authorization_list) + self._json_dump(f'{report_name}.{report_format}', authorization_list) else: self.logger.debug('Housekeeping.authorizations_invalidate(): No dump just return report') else: @@ -587,25 +586,25 @@ def authorizations_invalidate(self, uts: int = uts_now(), report_format: str = ' def dbversion_check(self, version: str = None): """ check database version """ - self.logger.debug('Housekeeping.dbversion_check({0})'.format(version)) + self.logger.debug('Housekeeping.dbversion_check(%s)', version) if version: try: (result, script_name) = self.dbstore.dbversion_get() except Exception as err_: - self.logger.critical('acme2certifier database error in Housekeeping.dbversion_check(): {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Housekeeping.dbversion_check(): %s', err_) result = None script_name = 'handler specific migration' if result != version: - self.logger.critical('acme2certifier database version mismatch in: version is {0} but should be {1}. Please run the "{2}" script'.format(result, version, script_name)) + self.logger.critical('acme2certifier database version mismatch in: version is %s but should be %s. Please run the "%s" script', result, version, script_name) else: - self.logger.debug('acme2certifier database version: {0} is upto date'.format(version)) + self.logger.debug('acme2certifier database version: %s is upto date', version) else: self.logger.critical('acme2certifier database version could not be verified in Housekeeping.dbversion_check()') def orders_invalidate(self, uts: int = uts_now(), report_format: str = 'csv', report_name: str = None) -> List[str]: """ orders cleanup based on expiry date""" - self.logger.debug('Housekeeping.orders_invalidate({0})'.format(uts)) + self.logger.debug('Housekeeping.orders_invalidate(%s)', uts) with Order(self.debug, None, self.logger) as order: # get expired orders @@ -621,10 +620,10 @@ def orders_invalidate(self, uts: int = uts_now(), report_format: str = 'csv', re if report_format == 'csv': self.logger.debug('Housekeeping.orders_invalidate(): Dump in csv-format') csv_list = self._to_list(field_list, order_list) - self._csv_dump('{0}.{1}'.format(report_name, report_format), csv_list) + self._csv_dump(f'{report_name}.{report_format}', csv_list) elif report_format == 'json': self.logger.debug('Housekeeping.orders_invalidate(): Dump in json-format') - self._json_dump('{0}.{1}'.format(report_name, report_format), order_list) + self._json_dump(f'{report_name}.{report_format}', order_list) else: self.logger.debug('Housekeeping.orders_invalidate(): No dump just return report') else: diff --git a/acme_srv/message.py b/acme_srv/message.py index fd8dbad7..a79ac775 100644 --- a/acme_srv/message.py +++ b/acme_srv/message.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# pylint: disable=c0209 +# pylint: disable=r0913 """ message class """ from __future__ import print_function import json @@ -49,7 +49,7 @@ def _name_rev_get(self, content: Dict[str, str]) -> str: try: account_list = self.dbstore.account_lookup('jwk', json.dumps(content['jwk'])) except Exception as err_: - self.logger.critical('acme2certifier database error in Message._name_rev_get(): {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Message._name_rev_get(): %s', err_) account_list = [] if account_list: if 'name' in account_list: @@ -59,7 +59,7 @@ def _name_rev_get(self, content: Dict[str, str]) -> str: else: kid = None - self.logger.debug('Message._name_rev_get() ended with kid: {0}'.format(kid)) + self.logger.debug('Message._name_rev_get() ended with kid: %s', kid) return kid def _name_get(self, content: Dict[str, str]) -> str: @@ -67,19 +67,19 @@ def _name_get(self, content: Dict[str, str]) -> str: self.logger.debug('Message._name_get()') if 'kid' in content: - self.logger.debug('kid: {0}'.format(content['kid'])) - kid = content['kid'].replace('{0}{1}'.format(self.server_name, self.path_dic['acct_path']), '') + self.logger.debug('kid: %s', content['kid']) + kid = content['kid'].replace(f'{self.server_name}{self.path_dic["acct_path"]}', '') if '/' in kid: kid = None elif 'jwk' in content and 'url' in content: - if content['url'] == '{0}{1}'.format(self.server_name, self.path_dic['revocation_path']): + if content['url'] == f'{self.server_name}{self.path_dic["revocation_path"]}': # this is needed for cases where we get a revocation message signed with account key but account name is missing kid = self._name_rev_get(content) else: kid = None else: kid = None - self.logger.debug('Message._name_get() returns: {0}'.format(kid)) + self.logger.debug('Message._name_get() returns: %s', kid) return kid def _check(self, skip_nonce_check: bool, skip_signature_check: bool, content: str, protected: Dict[str, str], use_emb_key: bool) -> Tuple[int, str, str, str]: @@ -114,13 +114,14 @@ def _check(self, skip_nonce_check: bool, skip_signature_check: bool, content: st message = error detail = error_detail - self.logger.debug('Message._check() ended with: {0}'.format(code)) + self.logger.debug('Message._check() ended with: %s', code) return (code, message, detail, account_name) # pylint: disable=R0914 def check(self, content: str, use_emb_key: bool = False, skip_nonce_check: bool = False) -> Tuple[int, str, str, Dict[str, str], Dict[str, str], str]: """ validate message """ self.logger.debug('Message.check()') + # disable signature check if paramter has been set if self.disable_dic['signature_check_disable']: self.logger.error('**** SIGNATURE_CHECK_DISABLE!!! Severe security issue ****') @@ -139,7 +140,7 @@ def check(self, content: str, use_emb_key: bool = False, skip_nonce_check: bool message = 'urn:ietf:params:acme:error:malformed' detail = error_detail - self.logger.debug('Message.check() ended with:{0}'.format(code)) + self.logger.debug('Message.check() ended with:%s', code) return (code, message, detail, protected, payload, account_name) def cli_check(self, content: str) -> Tuple[int, str, str, Dict[str, str], Dict[str, str], str, Dict[str, str]]: @@ -171,7 +172,7 @@ def cli_check(self, content: str) -> Tuple[int, str, str, Dict[str, str], Dict[s message = 'urn:ietf:params:acme:error:malformed' detail = error_detail - self.logger.debug('Message.check() ended with:{0}'.format(code)) + self.logger.debug('Message.check() ended with:%s', code) return (code, message, detail, protected, payload, account_name, permissions) def prepare_response(self, response_dic: Dict[str, str], status_dic: Dict[str, str], add_nonce: bool = True) -> Dict[str, str]: diff --git a/acme_srv/nonce.py b/acme_srv/nonce.py index 78243389..63924ac1 100644 --- a/acme_srv/nonce.py +++ b/acme_srv/nonce.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- """ Nonce class """ -# pylint: disable=c0209 from __future__ import print_function import uuid from typing import Tuple, Dict @@ -24,19 +23,19 @@ def __exit__(self, *args): def _check_and_delete(self, nonce: str) -> Tuple[int, str, str]: """ check if nonce exists and delete it """ - self.logger.debug('Nonce.nonce._check_and_delete({0})'.format(nonce)) + self.logger.debug('Nonce.nonce._check_and_delete(%s)', nonce) try: nonce_chk_result = self.dbstore.nonce_check(nonce) except Exception as err_: - self.logger.critical('acme2certifier database error during nonce_check() in Nonce._check_and_delete(): {0}'.format(err_)) + self.logger.critical('acme2certifier database error during nonce_check() in Nonce._check_and_delete(): %s', err_) nonce_chk_result = False if nonce_chk_result: try: self.dbstore.nonce_delete(nonce) except Exception as err_: - self.logger.critical('acme2certifier database error during nonce_delete() in Nonce._check_and_delete(): {0}'.format(err_)) + self.logger.critical('acme2certifier database error during nonce_delete() in Nonce._check_and_delete(): %s', err_) code = 200 message = None detail = None @@ -44,7 +43,7 @@ def _check_and_delete(self, nonce: str) -> Tuple[int, str, str]: code = 400 message = 'urn:ietf:params:acme:error:badNonce' detail = nonce - self.logger.debug('Nonce._check_and_delete() ended with:{0}'.format(code)) + self.logger.debug('Nonce._check_and_delete() ended with:%s', code) return (code, message, detail) def _new(self) -> str: @@ -61,18 +60,18 @@ def check(self, protected_decoded: Dict[str, str]) -> Tuple[int, str, str]: code = 400 message = 'urn:ietf:params:acme:error:badNonce' detail = 'NONE' - self.logger.debug('Nonce.check_nonce() ended with:{0}'.format(code)) + self.logger.debug('Nonce.check_nonce() ended with:%s', code) return (code, message, detail) def generate_and_add(self) -> str: """ generate new nonce and store it """ self.logger.debug('Nonce.nonce_generate_and_add()') nonce = self._new() - self.logger.debug('got nonce: {0}'.format(nonce)) - # self.logger.critical('foo') + + self.logger.debug('got nonce: %s', nonce) try: _id = self.dbstore.nonce_add(nonce) # lgtm [py/unused-local-variable] except Exception as err_: - self.logger.critical('acme2certifier database error in Nonce.generate_and_add(): {0}'.format(err_)) - self.logger.debug('Nonce.generate_and_add() ended with:{0}'.format(nonce)) + self.logger.critical('acme2certifier database error in Nonce.generate_and_add(): %s', err_) + self.logger.debug('Nonce.generate_and_add() ended with:%s', nonce) return nonce diff --git a/acme_srv/order.py b/acme_srv/order.py index b83bba2d..4214e51b 100644 --- a/acme_srv/order.py +++ b/acme_srv/order.py @@ -1,10 +1,9 @@ # -*- coding: utf-8 -*- """ Order class """ -# pylint: disable=c0209 from __future__ import print_function import json from typing import List, Tuple, Dict -from acme_srv.helper import b64_url_recode, generate_random_string, load_config, parse_url, uts_to_date_utc, uts_now, error_dic_get +from acme_srv.helper import b64_url_recode, generate_random_string, load_config, parse_url, uts_to_date_utc, uts_now, error_dic_get, validate_identifier from acme_srv.certificate import Certificate from acme_srv.db_handler import DBstore from acme_srv.message import Message @@ -27,6 +26,7 @@ def __init__(self, debug: bool = None, srv_name: str = None, logger: object = No self.retry_after = 600 self.tnauthlist_support = False self.sectigo_sim = False + self.identifier_limit = 20 self.header_info_list = [] def __enter__(self): @@ -38,7 +38,7 @@ def __exit__(self, *args): """ cose the connection at the end of the context """ def _auth_add(self, oid: str, payload: Dict[str, str], auth_dic: Dict[str, str]) -> str: - self.logger.debug('Order._auth_add({0})'.format(oid)) + self.logger.debug('Order._auth_add(%s)', oid) if oid: error = None @@ -57,16 +57,17 @@ def _auth_add(self, oid: str, payload: Dict[str, str], auth_dic: Dict[str, str]) auth['status'] = 'valid' self.dbstore.authorization_update(auth) except Exception as err_: - self.logger.critical('acme2certifier database error in Order._add() authz: {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Order._add() authz: %s', err_) else: error = self.error_msg_dic['malformed'] - self.logger.debug('Order._auth_add() ended with {0}'.format(error)) + self.logger.debug('Order._auth_add() ended with %s', error) return error def _add(self, payload: Dict[str, str], aname: str) -> Tuple[str, str, Dict[str, str], int]: """ add order request to database """ - self.logger.debug('Order._add({0})'.format(aname)) + self.logger.debug('Order._add(%s)', aname) + error = None auth_dic = {} order_name = generate_random_string(self.logger, 12) @@ -91,7 +92,7 @@ def _add(self, payload: Dict[str, str], aname: str) -> Tuple[str, str, Dict[str, # add order to db oid = self.dbstore.order_add(data_dic) except Exception as err_: - self.logger.critical('acme2certifier database error in Order._add() order: {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Order._add() order: %s', err_) oid = None if not error: @@ -111,7 +112,7 @@ def _config_headerinfo_config_load(self, config_dic: Dict[str, str]): try: self.header_info_list = json.loads(config_dic['Order']['header_info_list']) except Exception as err_: - self.logger.warning('Order._config_orderconfig_load() header_info_list failed with error: {0}'.format(err_)) + self.logger.warning('Order._config_orderconfig_load() header_info_list failed with error: %s', err_) self.logger.debug('Order._config_headerinfo_config_load() ended') @@ -130,12 +131,16 @@ def _config_orderconfig_load(self, config_dic: Dict[str, str]): try: self.retry_after = int(config_dic['Order']['retry_after_timeout']) except Exception: - self.logger.warning('Order._config_load(): failed to parse retry_after: {0}'.format(config_dic['Order']['retry_after_timeout'])) + self.logger.warning('Order._config_load(): failed to parse retry_after: %s', config_dic['Order']['retry_after_timeout']) if 'validity' in config_dic['Order']: try: self.validity = int(config_dic['Order']['validity']) except Exception: - self.logger.warning('Order._config_load(): failed to parse validity: {0}'.format(config_dic['Order']['validity'])) + self.logger.warning('Order._config_load(): failed to parse validity: %s', config_dic['Order']['validity']) + try: + self.identifier_limit = int(config_dic.get('Order', 'identifier_limit', fallback=20)) + except Exception: + self.logger.warning('Order._config_load(): failed to parse identifier_limit: %s', config_dic['Order']['identifier_limit']) self.logger.debug('Order._config_orderconfig_load() ended') @@ -153,7 +158,7 @@ def _config_load(self): try: self.authz_validity = int(config_dic['Authorization']['validity']) except Exception: - self.logger.warning('Order._config_load(): failed to parse authz validity: {0}'.format(config_dic['Authorization']['validity'])) + self.logger.warning('Order._config_load(): failed to parse authz validity: %s', config_dic['Authorization']['validity']) if 'Directory' in config_dic and 'url_prefix' in config_dic['Directory']: self.path_dic = {k: config_dic['Directory']['url_prefix'] + v for k, v in self.path_dic.items()} @@ -162,7 +167,8 @@ def _config_load(self): def _name_get(self, url: str) -> str: """ get ordername """ - self.logger.debug('Order._name_get({0})'.format(url)) + self.logger.debug('Order._name_get(%s)', url) + url_dic = parse_url(self.logger, url) order_name = url_dic['path'].replace(self.path_dic['order_path'], '') if '/' in order_name: @@ -170,9 +176,10 @@ def _name_get(self, url: str) -> str: self.logger.debug('Order._name_get() ended') return order_name - def _identifiers_check(self, identifiers_list: List[str]) -> str: - """ check validity of identifers in order """ - self.logger.debug('Order._identifiers_check({0})'.format(identifiers_list)) + def _identifiers_allowed(self, identifiers_list: List[str]) -> bool: + """ check if identifiers are allowed """ + self.logger.debug('Order._identifiers_allowed()') + error = None allowed_identifers = ['dns', 'ip'] @@ -180,27 +187,44 @@ def _identifiers_check(self, identifiers_list: List[str]) -> str: if self.tnauthlist_support: allowed_identifers.append('tnauthlist') - if identifiers_list and isinstance(identifiers_list, list): - for identifier in identifiers_list: - if 'type' in identifier: - if identifier['type'].lower() not in allowed_identifers: - error = self.error_msg_dic['unsupportedidentifier'] - break + for identifier in identifiers_list: + if 'type' in identifier: + # pylint: disable=R1723 + if identifier['type'].lower() not in allowed_identifers: + error = self.error_msg_dic['unsupportedidentifier'] + break else: - error = self.error_msg_dic['malformed'] + if not validate_identifier(self.logger, identifier['type'].lower(), identifier['value'], self.tnauthlist_support): + error = self.error_msg_dic['rejectedidentifier'] + break + else: + error = self.error_msg_dic['malformed'] + + self.logger.debug('Order._identifiers_allowed() ended with: %s', error) + return error + + def _identifiers_check(self, identifiers_list: List[str]) -> str: + """ check validity of identifers in order """ + self.logger.debug('Order._identifiers_check(%s)', identifiers_list) + + if identifiers_list and isinstance(identifiers_list, list): + if len(identifiers_list) > self.identifier_limit: + error = self.error_msg_dic['rejectedidentifier'] + else: + error = self._identifiers_allowed(identifiers_list) else: error = self.error_msg_dic['malformed'] - self.logger.debug('Order._identifiers_check() done with {0}:'.format(error)) + self.logger.debug('Order._identifiers_check() done with %s:', error) return error def _info(self, order_name: str) -> Dict[str, str]: """ list details of an order """ - self.logger.debug('Order._info({0})'.format(order_name)) + self.logger.debug('Order._info(%s)', order_name) try: result = self.dbstore.order_lookup('name', order_name) except Exception as err_: - self.logger.critical('acme2certifier database error in Order._info(): {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Order._info(): %s', err_) result = None return result @@ -218,7 +242,7 @@ def _header_info_lookup(self, header: str) -> str: if header_info_dic: result = json.dumps(header_info_dic) - self.logger.debug('Order._header_info_lookup() ended with: {0} keys in dic'.format(len(header_info_dic.keys()))) + self.logger.debug('Order._header_info_lookup() ended with: %s keys in dic', len(header_info_dic.keys())) return result def _finalize(self, order_name: str, payload: Dict[str, str], header: str = None) -> Tuple[int, str, str, str]: @@ -267,7 +291,8 @@ def _finalize(self, order_name: str, payload: Dict[str, str], header: str = None def _process(self, order_name: str, protected: Dict[str, str], payload: Dict[str, str], header: str = None) -> Tuple[int, str, str, str]: """ process order """ - self.logger.debug('Order._process({0})'.format(order_name)) + self.logger.debug('Order._process({%s)', order_name) + certificate_name = None message = None detail = None @@ -283,7 +308,7 @@ def _process(self, order_name: str, protected: Dict[str, str], payload: Dict[str try: cert_dic = self.dbstore.certificate_lookup('order__name', order_name) except Exception as err_: - self.logger.critical('acme2certifier database error in Order._process(): {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Order._process(): %s', err_) cert_dic = {} if cert_dic: # we found a cert in the database @@ -295,12 +320,12 @@ def _process(self, order_name: str, protected: Dict[str, str], payload: Dict[str message = self.error_msg_dic['malformed'] detail = 'url is missing in protected' - self.logger.debug('Order._process() ended with order:{0} {1}:{2}:{3}'.format(order_name, code, message, detail)) + self.logger.debug('Order._process() ended with order:%s %s:%s:%s', order_name, code, message, detail) return (code, message, detail, certificate_name) def _csr_process(self, order_name: str, csr: str, header_info: str) -> Tuple[int, str, str]: """ process certificate signing request """ - self.logger.debug('Order._csr_process({0})'.format(order_name)) + self.logger.debug('Order._csr_process(%s)', order_name) order_dic = self._info(order_name) @@ -327,18 +352,19 @@ def _csr_process(self, order_name: str, csr: str, header_info: str) -> Tuple[int else: code = 400 message = self.error_msg_dic['unauthorized'] - detail = 'order: {0} not found'.format(order_name) + detail = f'order: {order_name} not found' - self.logger.debug('Order._csr_process() ended with order:{0} {1}:{2}:{3}'.format(order_name, code, message, detail)) + self.logger.debug('Order._csr_process() ended with order:%s %s:{%s:%s', order_name, code, message, detail) return (code, message, detail) def _update(self, data_dic: Dict[str, str]): """ update order based on ordername """ - self.logger.debug('Order._update({0})'.format(data_dic)) + self.logger.debug('Order._update(%s)', data_dic) + try: self.dbstore.order_update(data_dic) except Exception as err_: - self.logger.critical('acme2certifier database error in Order._update(): {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Order._update(): %s', err_) def _order_dic_create(self, tmp_dic: Dict[str, str]) -> Dict[str, str]: """ create order dictionary """ @@ -357,19 +383,19 @@ def _order_dic_create(self, tmp_dic: Dict[str, str]) -> Dict[str, str]: try: order_dic['identifiers'] = json.loads(tmp_dic['identifiers']) except Exception: - self.logger.error('Order._order_dic_create(): error while parsing the identifier {0}'.format(tmp_dic['identifiers'])) + self.logger.error('Order._order_dic_create(): error while parsing the identifier %s', tmp_dic['identifiers']) self.logger.debug('Order._order_dic_create() ended') return order_dic def _authz_list_lookup(self, order_name: str) -> List[str]: """ lookup authorization list """ - self.logger.debug('Order._authz_list_lookup({0})'.format(order_name)) + self.logger.debug('Order._authz_list_lookup(%s)', order_name) try: authz_list = self.dbstore.authorization_lookup('order__name', order_name, ['name', 'status__name']) except Exception as err_: - self.logger.critical('acme2certifier database error in Order._authz_list_lookup(): {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Order._authz_list_lookup(): %s', err_) authz_list = [] self.logger.debug('Order._authz_list_lookup() ended') @@ -380,7 +406,7 @@ def _validity_list_create(self, authz_list: List[str], order_dic: Dict[str, str] validity_list = [] for authz in authz_list: if 'name' in authz: - order_dic["authorizations"].append('{0}{1}{2}'.format(self.server_name, self.path_dic['authz_path'], authz['name'])) + order_dic["authorizations"].append(f'{self.server_name}{self.path_dic["authz_path"]}{authz["name"]}') if 'status__name' in authz: if authz['status__name'] == 'valid': validity_list.append(True) @@ -396,7 +422,7 @@ def _validity_list_create(self, authz_list: List[str], order_dic: Dict[str, str] def _lookup(self, order_name: str) -> Dict[str, str]: """ sohw order details based on ordername """ - self.logger.debug('Order._validity_list_create({0})'.format(order_name)) + self.logger.debug('Order._validity_list_create(%s)', order_name) order_dic = {} tmp_dic = self._info(order_name) @@ -417,16 +443,16 @@ def _lookup(self, order_name: str) -> Dict[str, str]: def invalidate(self, timestamp: int = None) -> Tuple[List[str], List[str]]: """ invalidate orders """ - self.logger.debug('Order.invalidate({0})'.format(timestamp)) + self.logger.debug('Order.invalidate(%s)', timestamp) if not timestamp: timestamp = uts_now() - self.logger.debug('Order.invalidate(): set timestamp to {0}'.format(timestamp)) + self.logger.debug('Order.invalidate(): set timestamp to %s', timestamp) field_list = ['id', 'name', 'expires', 'identifiers', 'created_at', 'status__id', 'status__name', 'account__id', 'account__name', 'account__contact'] try: order_list = self.dbstore.orders_invalid_search('expires', timestamp, vlist=field_list, operant='<=') except Exception as err_: - self.logger.critical('acme2certifier database error in Order._invalidate() search: {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Order._invalidate() search: %s', err_) order_list = [] output_list = [] for order in order_list: @@ -438,9 +464,9 @@ def invalidate(self, timestamp: int = None) -> Tuple[List[str], List[str]]: try: self.dbstore.order_update(data_dic) except Exception as err_: - self.logger.critical('acme2certifier database error in Order._invalidate() upd: {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Order._invalidate() upd: %s', err_) - self.logger.debug('Order.invalidate() ended: {0} orders identified'.format(len(output_list))) + self.logger.debug('Order.invalidate() ended: %s orders identified', len(output_list)) return (field_list, output_list) def new(self, content: str) -> Dict[str, str]: @@ -455,25 +481,30 @@ def new(self, content: str) -> Dict[str, str]: if not error: code = 201 response_dic['header'] = {} - response_dic['header']['Location'] = '{0}{1}{2}'.format(self.server_name, self.path_dic['order_path'], order_name) + response_dic['header']['Location'] = f'{self.server_name}{self.path_dic["order_path"]}{order_name}' response_dic['data'] = {} response_dic['data']['identifiers'] = [] response_dic['data']['authorizations'] = [] response_dic['data']['status'] = 'pending' response_dic['data']['expires'] = expires - response_dic['data']['finalize'] = '{0}{1}{2}/finalize'.format(self.server_name, self.path_dic['order_path'], order_name) + response_dic['data']['finalize'] = f'{self.server_name}{self.path_dic["order_path"]}{order_name}/finalize' for auth_name, value in auth_dic.items(): - response_dic['data']['authorizations'].append('{0}{1}{2}'.format(self.server_name, self.path_dic['authz_path'], auth_name)) + response_dic['data']['authorizations'].append(f'{self.server_name}{self.path_dic["authz_path"]}{auth_name}') response_dic['data']['identifiers'].append(value) + elif error == self.error_msg_dic['rejectedidentifier']: + code = 403 + message = error + detail = 'Some of the requested identifiers got rejected' else: code = 400 message = error - detail = 'could not process order' + detail = 'Could not process order' + # prepare/enrich response status_dic = {'code': code, 'type': message, 'detail': detail} response_dic = self.message.prepare_response(response_dic, status_dic) - self.logger.debug('Order.new() returns: {0}'.format(json.dumps(response_dic))) + self.logger.debug('Order.new() returns: %s', json.dumps(response_dic)) return response_dic def _parse(self, protected: Dict[str, str], payload: Dict[str, str], header: str = None) -> Tuple[int, str, str, str, str]: @@ -501,7 +532,7 @@ def _parse(self, protected: Dict[str, str], payload: Dict[str, str], header: str message = self.error_msg_dic['malformed'] detail = 'url is missing in protected' - self.logger.debug('Order._parse() ended with code: {0}'.format(code)) + self.logger.debug('Order._parse() ended with code: %s', code) return (code, message, detail, certificate_name, order_name) def parse(self, content: str, header: str = None) -> Dict[str, str]: @@ -524,20 +555,20 @@ def parse(self, content: str, header: str = None) -> Dict[str, str]: if code == 200: # create response response_dic['header'] = {} - response_dic['header']['Location'] = '{0}{1}{2}'.format(self.server_name, self.path_dic['order_path'], order_name) + response_dic['header']['Location'] = f'{self.server_name}{self.path_dic["order_path"]}{order_name}' response_dic['data'] = self._lookup(order_name) if 'status' in response_dic['data'] and response_dic['data']['status'] == 'processing': # set retry header as cert issuane is not completed. - response_dic['header']['Retry-After'] = '{0}'.format(self.retry_after) - response_dic['data']['finalize'] = '{0}{1}{2}/finalize'.format(self.server_name, self.path_dic['order_path'], order_name) + response_dic['header']['Retry-After'] = f'{self.retry_after}' + response_dic['data']['finalize'] = f'{self.server_name}{self.path_dic["order_path"]}{order_name}/finalize' # add the path to certificate if order-status is ready # if certificate_name: if certificate_name and 'status' in response_dic['data'] and response_dic['data']['status'] == 'valid': - response_dic['data']['certificate'] = '{0}{1}{2}'.format(self.server_name, self.path_dic['cert_path'], certificate_name) + response_dic['data']['certificate'] = f'{self.server_name}{self.path_dic["cert_path"]}{certificate_name}' # prepare/enrich response status_dic = {'code': code, 'type': message, 'detail': detail} response_dic = self.message.prepare_response(response_dic, status_dic) - self.logger.debug('Order.parse() returns: {0}'.format(json.dumps(response_dic))) + self.logger.debug('Order.parse() returns: %s', json.dumps(response_dic)) return response_dic diff --git a/acme_srv/renewalinfo.py b/acme_srv/renewalinfo.py index 27699834..d420f3eb 100644 --- a/acme_srv/renewalinfo.py +++ b/acme_srv/renewalinfo.py @@ -1,11 +1,10 @@ # -*- coding: utf-8 -*- """ Nonce class """ -# pylint: disable=c0209 from __future__ import print_function from typing import Dict from acme_srv.db_handler import DBstore from acme_srv.message import Message -from acme_srv.helper import string_sanitize, certid_hex_get, uts_to_date_utc, error_dic_get, load_config, uts_now +from acme_srv.helper import string_sanitize, certid_hex_get, uts_to_date_utc, error_dic_get, load_config, uts_now, cert_serial_get, cert_aki_get, b64_url_recode, b64_decode class Renewalinfo(object): @@ -44,32 +43,89 @@ def _config_load(self): try: self.renewaltreshold_pctg = float(config_dic['Renewalinfo']['renewaltreshold_pctg']) except Exception as err_: - self.logger.error('acme2certifier Renewalinfo._config_load() renewaltreshold_pctg parsing error: {0}'.format(err_)) + self.logger.error('acme2certifier Renewalinfo._config_load() renewaltreshold_pctg parsing error: %s', err_) if 'retry_after_timeout' in config_dic['Renewalinfo']: try: self.retry_after_timeout = int(config_dic['Renewalinfo']['retry_after_timeout']) except Exception as err_: - self.logger.error('acme2certifier Renewalinfo._config_load() retry_after_timeout parsing error: {0}'.format(err_)) + self.logger.error('acme2certifier Renewalinfo._config_load() retry_after_timeout parsing error: %s', err_) - def _lookup(self, certid_hex: str) -> Dict[str, str]: - """ lookup expiry dates based on renewal info """ - self.logger.debug('Renewalinfo._lookup()') + def _cert_dic_lookup(self, renewalinfo_string: str) -> Dict[str, str]: + """ lookup certificate based on renewalinfo string """ + self.logger.debug('Renewalinfo._cert_dic_lookup(%s)', renewalinfo_string) + + if '.' in renewalinfo_string: + # draft-ietf-acme-ari-02 + (serial, aki) = self._serial_aki_get(renewalinfo_string) + # lookup database for certificate data + cert_dic = self._draft02_lookup(serial, aki) + + else: + # draft-ietf-acme-ari-01 + (_mda, certid_hex) = certid_hex_get(self.logger, renewalinfo_string) + # lookup database for certificate data + cert_dic = self._draft01_lookup(certid_hex) + + self.logger.debug('Renewalinfo._cert_dic_lookup(%s) - ended with: %s', renewalinfo_string, bool(cert_dic)) + return cert_dic + + def _cert_table_update(self): + """ add serial and aki to certificate table """ + self.logger.debug('Renewalinfo._cert_table_update()') + + try: + certificate_list = self.dbstore.certificates_search('serial', None, operant='is', vlist=['id', 'name', 'cert', 'cert_raw', 'serial', 'aki']) + except Exception as err_: + self.logger.critical('acme2certifier database error in Renewalinfo._cert_table_update(): %s', err_) + certificate_list = [] + + update_cnt = 0 + for cert in certificate_list: + if 'cert_raw' in cert and cert['cert_raw'] and 'name' in cert and 'cert' in cert: + serial = cert_serial_get(self.logger, cert['cert_raw'], hexformat=True) + aki = cert_aki_get(self.logger, cert['cert_raw']) + data_dic = {'serial': serial, 'aki': aki, 'name': cert['name'], 'cert_raw': cert['cert_raw'], 'cert': cert['cert']} + self.dbstore.certificate_add(data_dic) + update_cnt += 1 + + self.logger.debug('Renewalinfo._cert_table_update(%s) - done', update_cnt) + + def _draft01_lookup(self, certid_hex: str) -> Dict[str, str]: + """ lookup expiry dates based on certid accoridng to acme-ari-01 """ + self.logger.debug('Renewalinfo._draft01_lookup()') try: result_dic = self.dbstore.certificate_lookup('renewal_info', certid_hex, ('id', 'name', 'cert', 'cert_raw', 'expire_uts', 'issue_uts', 'created_at')) except Exception as err_: - self.logger.critical('acme2certifier database error in Renewalinfo._lookup(): {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Renewalinfo._draft01_lookup(): %s', err_) result_dic = None return result_dic - def _renewalinfo_get(self, certid_hex: str) -> Dict[str, str]: - """ create dictionary containing renwal infor data """ - self.logger.debug('Renewalinfo.get()') + def _draft02_lookup(self, serial: str, aki: str) -> Dict[str, str]: + """ lookup expiry dates based on certid accoridng to acme-ari-02 """ + self.logger.debug('Renewalinfo._draft02_lookup()') + + cert_dic = {} + try: + cert_list = self.dbstore.certificates_search('serial', serial, operant='is', vlist=['id', 'name', 'cert', 'cert_raw', 'expire_uts', 'issue_uts', 'aki', 'created_at']) + if not cert_list and serial.startswith('0'): + # cover cornercase where serial is padded with leading zeros + cert_list = self.dbstore.certificates_search('serial', serial.lstrip('0'), operant='is', vlist=['id', 'name', 'cert', 'cert_raw', 'expire_uts', 'issue_uts', 'aki', 'created_at']) + for cert in cert_list: + if cert['aki'] == aki: + cert_dic = cert + break + except Exception as err_: + self.logger.critical('acme2certifier database error in Renewalinfo._draft02_lookup(): %s', err_) - # lookup database for certificate data - cert_dic = self._lookup(certid_hex) + self.logger.debug('Renewalinfo._draft02_lookup() ended with: %s', bool(cert_dic)) + return cert_dic + + def _renewalinfo_generate(self, cert_dic: Dict[str, str]) -> Dict[str, str]: + """ create dictionary containing renwal info data """ + self.logger.debug('Renewalinfo._renewalinfo_generate()') if 'expire_uts' in cert_dic and cert_dic['expire_uts']: @@ -95,54 +151,89 @@ def _renewalinfo_get(self, certid_hex: str) -> Dict[str, str]: else: renewalinfo_dic = {} + self.logger.debug('Renewalinfo._renewalinfo_generate() ended') return renewalinfo_dic - def renewalinfo_string_get(self, url: str) -> str: + def _renewalinfo_get(self, renewalinfo_string: str) -> Dict[str, str]: + """ get renewal info dictionary """ + self.logger.debug('Renewalinfo._renewalinfo_get()') + + cert_dic = self._cert_dic_lookup(renewalinfo_string) + rewalinfo_dic = self._renewalinfo_generate(cert_dic) + + self.logger.debug('Renewalinfo._renewalinfo_get() ended with: %s', rewalinfo_dic) + return rewalinfo_dic + + def _renewalinfo_string_get(self, url: str) -> str: """ get renewal string from url""" self.logger.debug('Renewalinfo.renewal_string_get()') # we need to workaround a strange issue in win-acme - url = url.replace('{0}{1}'.format(self.server_name, self.path_dic['renewalinfo'].rstrip('/')), '') + url = url.replace(f'{self.server_name}{self.path_dic["renewalinfo"].rstrip("/")}', '') url = url.lstrip('/') # sanitize renewal_info string renewalinfo_string = string_sanitize(self.logger, url) - self.logger.debug('Renewalinfo.renewal_string_get() - renewalinfo_string: {0}'.format(renewalinfo_string)) + self.logger.debug('Renewalinfo.renewal_string_get() - renewalinfo_string: %s', renewalinfo_string) return renewalinfo_string + def _serial_aki_get(self, renewalinfo_string: str) -> (str, str): + """ get serial and aki from renewalinfo string """ + self.logger.debug('Renewalinfo._serial_aki_get()') + + # split renewalinfo_string + renewalinfo_list = renewalinfo_string.split('.') + + if len(renewalinfo_list) == 2: + serial = b64_decode(self.logger, b64_url_recode(self.logger, renewalinfo_list[1])).hex() + aki = b64_decode(self.logger, b64_url_recode(self.logger, renewalinfo_list[0])).hex() + else: + serial = None + aki = None + + self.logger.debug('Renewalinfo._serial_aki_get() - serial: %s, aki: %s', serial, aki) + return (serial, aki) + def get(self, url: str) -> Dict[str, str]: """ get renewal information """ self.logger.debug('Renewalinfo.get()') - # parse renewalinfo - renewalinfo_string = self.renewalinfo_string_get(url) + # shousekeeping - add serial and aki to certificate table + if not self.dbstore.hkparameter_get('cert_aki_serial_update'): + self._cert_table_update() + self.logger.debug('Renewalinfo.get() - update housekeeping') + self.dbstore.hkparameter_add({'name': 'cert_aki_serial_update', 'value': True}) - (mda, certid_hex) = certid_hex_get(self.logger, renewalinfo_string) + # parse renewalinfo string + renewalinfo_string = self._renewalinfo_string_get(url) - response_dic = {} - # we cannot verify the AKI thus we accept any value - if mda: - # get renewal window datas - rewalinfo_dic = self._renewalinfo_get(certid_hex) + # get renewal information + try: + rewalinfo_dic = self._renewalinfo_get(renewalinfo_string) if rewalinfo_dic: - response_dic['code'] = 200 - # filter certificate and decode it - response_dic['data'] = rewalinfo_dic - # order status is processing - ratelimiting - response_dic['header'] = {'Retry-After': '{0}'.format(self.retry_after_timeout)} + rc_code = 200 else: - response_dic['code'] = 404 - response_dic['data'] = self.err_msg_dic['malformed'] + rc_code = 404 + except Exception as err_: + self.logger.error('Renewalinfo.get() - error: %s', err_) + rewalinfo_dic = {} + rc_code = 400 + + response_dic = {'code': rc_code} + if rewalinfo_dic: + # filter certificate and decode it + response_dic['data'] = rewalinfo_dic + # order status is processing - ratelimiting + response_dic['header'] = {'Retry-After': f'{self.retry_after_timeout}'.format()} else: - response_dic['code'] = 400 response_dic['data'] = self.err_msg_dic['malformed'] return response_dic def update(self, content: str) -> Dict[str, str]: """ update renewalinfo request """ - self.logger.debug('Renewalinfo.update({0})') + self.logger.debug('Renewalinfo.update()') # check message (code, _message, _detail, _protected, payload, _account_name) = self.message.check(content) @@ -150,9 +241,7 @@ def update(self, content: str) -> Dict[str, str]: response_dic = {} if code == 200 and 'certid' in payload and 'replaced' in payload: - (_mda, certid_hex) = certid_hex_get(self.logger, payload['certid']) - - cert_dic = self._lookup(certid_hex) + cert_dic = self._cert_dic_lookup(payload['certid']) if cert_dic and payload['replaced']: cert_dic['replaced'] = True diff --git a/acme_srv/signature.py b/acme_srv/signature.py index fa6ae983..ce10c539 100644 --- a/acme_srv/signature.py +++ b/acme_srv/signature.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- """ Signature class """ -# pylint: disable=c0209 from __future__ import print_function from typing import Tuple, Dict from acme_srv.helper import signature_check, load_config, error_dic_get @@ -25,27 +24,27 @@ def __init__(self, debug: bool = False, srv_name: str = None, logger: object = N def _cli_jwk_load(self, kid: int) -> Dict[str, str]: """ get key for a specific account id """ - self.logger.debug('Signature._cli_jwk_load({0})'.format(kid)) + self.logger.debug('Signature._cli_jwk_load(%s)', kid) try: result = self.dbstore.cli_jwk_load(kid) except Exception as err_: - self.logger.critical('acme2certifier database error in Signature._cli_jwk_load(): {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Signature._cli_jwk_load(): %s', err_) result = None return result def _jwk_load(self, kid: str) -> Dict[str, str]: """ get key for a specific account id """ - self.logger.debug('Signature._jwk_load({0})'.format(kid)) + self.logger.debug('Signature._jwk_load(%s)', kid) try: result = self.dbstore.jwk_load(kid) except Exception as err_: - self.logger.critical('acme2certifier database error in Signature._jwk_load(): {0}'.format(err_)) + self.logger.critical('acme2certifier database error in Signature._jwk_load(): %s', err_) result = None return result def cli_check(self, aname: str, content: str) -> Tuple[str, str, None]: """ signature check against cli key """ - self.logger.debug('Signature.cli_check({0})'.format(aname)) + self.logger.debug('Signature.cli_check(%s)', aname) result = False error = None @@ -62,12 +61,12 @@ def cli_check(self, aname: str, content: str) -> Tuple[str, str, None]: else: error = self.err_msg_dic['malformed'] - self.logger.debug('Signature.cli_check() ended with: {0}:{1}'.format(result, error)) + self.logger.debug('Signature.cli_check() ended with: %s:%s', result, error) return (result, error, None) def check(self, aname: str, content: str, use_emb_key: bool = False, protected: Dict[str, str] = None) -> Tuple[str, str, None]: """ signature check """ - self.logger.debug('Signature.check({0})'.format(aname)) + self.logger.debug('Signature.check(%s)', aname) result = False if content: error = None @@ -90,7 +89,7 @@ def check(self, aname: str, content: str, use_emb_key: bool = False, protected: else: error = self.err_msg_dic['malformed'] - self.logger.debug('Signature.check() ended with: {0}:{1}'.format(result, error)) + self.logger.debug('Signature.check() ended with: %s:%s', result, error) return (result, error, None) def eab_check(self, content: str, mac_key: str) -> Tuple[str, str]: @@ -101,4 +100,5 @@ def eab_check(self, content: str, mac_key: str) -> Tuple[str, str]: if content and mac_key: (result, error) = signature_check(self.logger, content, mac_key, json_=True) + self.logger.debug('Signature.signature_check() ended with: %s:%s', result, error) return (result, error) diff --git a/acme_srv/trigger.py b/acme_srv/trigger.py index b175d05e..f7e46521 100644 --- a/acme_srv/trigger.py +++ b/acme_srv/trigger.py @@ -44,7 +44,7 @@ def _certname_lookup(self, cert_pem: str) -> List[str]: csr_pubkey = csr_pubkey_get(self.logger, cert['csr']) if csr_pubkey == cert_pubkey: result_list.append({'cert_name': cert['name'], 'order_name': cert['order__name']}) - self.logger.debug('Trigger._certname_lookup() ended with: {0}'.format(result_list)) + self.logger.debug('Trigger._certname_lookup() ended with: %s', result_list) return result_list @@ -61,9 +61,9 @@ def _config_load(self): try: self.cahandler = ca_handler_module.CAhandler except Exception as err_: - self.logger.critical('Certificate._config_load(): loading CAhandler failed with err: {0}'.format(err_)) + self.logger.critical('Certificate._config_load(): loading CAhandler failed with err: %s', err_) - self.logger.debug('ca_handler: {0}'.format(ca_handler_module)) + self.logger.debug('ca_handler: %s', ca_handler_module) self.logger.debug('Certificate._config_load() ended.') def _cert_store(self, cert_bundle: str, cert_raw: str) -> Tuple[int, str, str]: @@ -82,13 +82,13 @@ def _cert_store(self, cert_bundle: str, cert_raw: str) -> Tuple[int, str, str]: try: self.dbstore.certificate_add(data_dic) except Exception as err_: - self.logger.critical('acme2certifier database error in trigger._payload_process() add: {0}'.format(err_)) + self.logger.critical('acme2certifier database error in trigger._payload_process() add: %s', err_) if 'order_name' in cert and cert['order_name']: try: # update order status to 5 (valid) self.dbstore.order_update({'name': cert['order_name'], 'status': 'valid'}) except Exception as err_: - self.logger.critical('acme2certifier database error in trigger._payload_process() upd: {0}'.format(err_)) + self.logger.critical('acme2certifier database error in trigger._payload_process() upd: %s', err_) code = 200 message = 'OK' detail = None @@ -118,7 +118,7 @@ def _payload_process(self, payload: str) -> Tuple[int, str, str]: message = 'payload malformed' detail = None - self.logger.debug('Trigger._payload_process() ended with: {0} {1}'.format(code, message)) + self.logger.debug('Trigger._payload_process() ended with: %s %s', code, message) return (code, message, detail) def parse(self, content: str) -> Dict[str, str]: @@ -151,5 +151,5 @@ def parse(self, content: str) -> Dict[str, str]: if detail: response_dic['data']['detail'] = detail - self.logger.debug('Trigger.parse() returns: {0}'.format(json.dumps(response_dic))) + self.logger.debug('Trigger.parse() returns: %s', json.dumps(response_dic)) return response_dic diff --git a/acme_srv/version.py b/acme_srv/version.py index 53e69b9a..45dec189 100644 --- a/acme_srv/version.py +++ b/acme_srv/version.py @@ -3,5 +3,5 @@ # 1) we don't load dependencies by storing it in __init__.py # 2) we can import it in setup.py for the same reason # 3) we can import it into your module module -__version__ = '0.32' -__dbversion__ = '0.30' +__version__ = '0.36' +__dbversion__ = '0.33.2' diff --git a/docs/a2c-alma-loadbalancing.md b/docs/a2c-alma-loadbalancing.md new file mode 100644 index 00000000..71144c92 --- /dev/null +++ b/docs/a2c-alma-loadbalancing.md @@ -0,0 +1,672 @@ + + +# How to build an acme2certifier cluster on Alma Linux 9 + +This tutorial describes the configuration of a two-node acme2certifier cluster running in active/active configuration. Although both nodes are active at the same time and provide proxy services via different ip-addresses database, configuration and runtime objects will be replicated among the nodes. + +This setup requires the switch to a different database engine as SQLite, which is the default a2c backend, is not designed to handle concurrent write access, which can happen in an active/active setup. Thus, [MariaDB](https://mariadb.org/) will be used. Configuration files and runtime objects will be replicated using [Lsyncd](https://github.com/lsyncd/lsyncd). The following diagram depicts the application stack to be used. + +![architecture](a2c-alma-loadbalancing.png "architecture") + +The guide is written for **Alma Linux 9**, however adapting to other Linux distributions ir Redhat derivates should not be difficult. There is also a guide for [Ubuntu 22.04](a2c-ubuntu-loadbalancing.md) available + +## Preparation + +To set up the MariaDB Master-Master replication between multiple servers, you will need to ensure each system hostname is resolved to the correct IP address. I recommend setting up the FQDN in /etc/hosts on each server. + +```cfg +cat /etc/hosts +... +192.168.14.136 alma9-c1.bar.local alma9-c1 +192.168.14.137 alma9-c2.bar.local alma9-c2 +``` + +Furthermore, the EPEL-repository need ot be enabled on both nodes. + +```bash +sudo yum install -y epel-release +sudo yum update -y +``` + +Stop the firewalld on both nodes + +```bash +sudo systemctl stop firewalld +sudo systemctl disable firewalld +``` + +## Installation and configuration of MariaDB + +The following instructions are based on [an existing tutorial](https://www.howtoforge.com/how-to-setup-mariadb-master-master-replication-on-debian-11/). + +### Setting up alma9-c1 + +- install MariaDB-server + +```bash +sudo yum install -y mariadb-server +``` + +- start MariaDB during startup + +```bash +sudo systemctl enable mariadb +sudo systemctl status mariadb +``` + +- modify `/etc/my.cnf.d/mariadb-server.cnf` change the ip-binding and add the follwinng lines + +```cfg +# listen on external address +bind-address = 192.168.14.136 + +server-id = 1 +report_host = alma9-c1 + +log_bin = /var/log/mariadb/mariadb-bin +log_bin_index = /var/log/mariadb/mariadb-bin.index + +relay_log = /var/log/mariadb/relay-bin +relay_log_index = /var/log/mariadb/relay-bin.index + +# avoiding primary key collision +log-slave-updates +auto_increment_increment=2 +auto_increment_offset=1 +``` + +- restart MariaDB-server + +```bash +sudo systemctl restart mariadb +``` + +- verify service binding + +```bash +ss -plnt +State Recv-Q Send-Q Local Address:Port Peer Address:Port Process +... +LISTEN 0 80 192.168.14.136:3306 0.0.0.0:* users:(("mariadbd",pid=815,fd=43)) +... +``` + +- open the mysql commandclient client + +```bash +sudo mysql -u root +``` + +- create the replication user + +```SQL +CREATE USER 'replusr'@'%' IDENTIFIED BY 'replpasswd'; +GRANT REPLICATION SLAVE ON *.* TO 'replusr'@'%'; +FLUSH PRIVILEGES; +``` + +- Next, run the following query to check the current binary log and its exact position of it. In this example, the binary log file for the MariaDB server is "mariadb-bin.000001" with the position "773". These outputs will be used in the next stage for setting up the "alma9-c2" server. + +```SQL +SHOW MASTER STATUS; +``` + +```SQL ++--------------------+----------+--------------+------------------+ +| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | ++--------------------+----------+--------------+------------------+ +| mariadb-bin.000001 | 773 | | | ++--------------------+----------+--------------+------------------+ +1 row in set (0.000 sec) +``` + +### Setting up alma9-c2 + +- install MariaDB-server + +```bash +sudo yum install -y mariadb-server +``` + +- start MariaDB during startup + +```bash +sudo systemctl enable mariadb +sudo systemctl status mariadb +``` + +- modify `/etc/my.cnf.d/mariadb-server.cnf` change the ip-binding and add the follwinng lines + +```cfg +# listen on external address +bind-address = 192.168.14.137 + +server-id = 2 +report_host = alma9-c2 + +log_bin = /var/log/mariadb/mariadb-bin +log_bin_index = /var/log/mariadb/mariadb-bin.index + +relay_log = /var/log/mariadb/relay-bin +relay_log_index = /var/log/mariadb/relay-bin.index + +# avoiding primary key collision +log-slave-updates +auto_increment_increment=2 +auto_increment_offset=2 +``` + +- restart MariaDB-server + +```bash +sudo systemctl restart mariadb +``` + +- verify service binding + +```bash +ss -plnt +``` + +```bash +State Recv-Q Send-Q Local Address:Port Peer Address:Port Process +... +LISTEN 0 80 192.168.14.137:3306 0.0.0.0:* users:(("mariadbd",pid=841,fd=41)) +... +``` + +- open the mysql commandclient client + +```bash +sudo mysql -u root +``` + +- create the replication user + +```SQL +CREATE USER 'replusr'@'%' IDENTIFIED BY 'replpasswd'; +GRANT REPLICATION SLAVE ON *.* TO 'replusr'@'%'; +FLUSH PRIVILEGES; +``` + +- stop the slave and add information about the alma9-c1 master node as well as the binlog file name ("mariadb-bin.000001") and position ("773") from alma9-c1. + +```SQL +STOP SLAVE; +CHANGE MASTER TO MASTER_HOST='alma9-c1', MASTER_USER='replusr', MASTER_PASSWORD='replpasswd', MASTER_LOG_FILE='mariadb-bin.000001', MASTER_LOG_POS=773; +``` + +- start the slave again and verify the slave status on the "alma9-c2" server. You should get "Slave_IO_Running: Yes" and "Slave_SQL_Running: Yes", + +```SQL +START SLAVE; +SHOW SLAVE STATUS\G +``` + +```SQL +*************************** 1. row *************************** + Slave_IO_State: Waiting for master to send event + Master_Host: alma9-c1 +... + Slave_IO_Running: Yes + Slave_SQL_Running: Yes +... +``` + +### Configure master-master replication on alma9-c1 + +- open the mysql commandclient client and create the replication user + +```bash +sudo mysql -u root +``` + +- stop the slave and add information about the alma9-c2 master node as well as the binlog file name and position. + +```SQL +STOP SLAVE; +CHANGE MASTER TO MASTER_HOST='alma9-c2', MASTER_USER='replusr', MASTER_PASSWORD='replpasswd', MASTER_LOG_FILE='mariadb-bin.000001', MASTER_LOG_POS=773; +``` + +- start the slave again and verify the slave status + +```SQL +START SLAVE; +SHOW SLAVE STATUS\G +``` + +```SQL +*************************** 1. row *************************** + Slave_IO_State: Waiting for master to send event + Master_Host: alma9-c1 +... + Slave_IO_Running: Yes + Slave_SQL_Running: Yes +... +``` + +### Test master-master replication + +#### test on alma9-c1 + +- open the mysql commandline client + +```bash +sudo mysql -u root +``` + +- create a testdatabase and a test-table + +```SQL +CREATE DATABASE testdb; +``` + +#### test on alma9-c2 + +- open the mysql commandline client + +```bash +sudo mysql -u root +``` + +- check the databases created in previous step + +```SQL +SHOW DATABASES; +``` + +```SQL ++--------------------+ +| Database | ++--------------------+ +| information_schema | +| mysql | +| performance_schema | +| testdb | ++--------------------+ +5 rows in set (0.000 sec) + +MariaDB [(none)]> +``` + +- delete database + +```SQL +DROP DATABASE testdb; +``` + +#### verification on alma9-c1 + +- back on alma9-c1 check the databases to make sure that "testdb" is not present anymore + +```SQL +SHOW DATABASES; +``` + +```SQL ++--------------------+ +| Database | ++--------------------+ +| information_schema | +| mysql | +| performance_schema | ++--------------------+ +4 rows in set (0.000 sec) + +``` + +## Configure directory replication via Lsyncd + +The following instructions are based on [an existing tutorial](https://docs.rackspace.com/docs/set-up-lsyncd-locally-and-over-ssh-to-sync-directories). + +To accomplish a remote synchronization using Lsyncd, each node must have password-less SSH access to its peer. Further, it is recommended to use the root-user for synchronization to ensure that permissions, ownership, and group information of the synchronized objects will be preserved. + +### on both nodes to be executed as root-user + +- generate ssh keys + +```bash +sudo ssh-keygen -t rsa -f /root/.ssh/id_lsyncd +``` + +- copy the newly created public key `/root/.ssh/id_lsyncd.pub` from each host to peer and add it to `/root/.ssh/authorized_keys` file + +- create the acme2certifier directory to be synchronized between the two hosts + +```bash +sudo mkdir -p /opt/acme2certifier/volume +``` + +- install Lsyncd + +```bash +sudo yum install -y lsyncd +``` + +### configuration on alma9-c1 + +- test passwordless ssh access by logging in to alma9-c2 + +```bash +sudo ssh -i /root/.ssh/id_lsyncd root@alma9-c2 +exit +``` + +- create a configuration file `/etc/lsyncd.conf` with the following content + +```lua +settings { + logfile = "/var/log/lsyncd/lsyncd.log", + statusFile = "/var/log/lsyncd/lsyncd.status", + statusInterval = 20, + nodaemon = false +} + +sync { + default.rsyncssh, + source = "/opt/acme2certifier/volume/", + host = "alma9-c2", + targetdir = "/opt/acme2certifier/volume/", + rsync = { + rsh = "/usr/bin/ssh -l root -i /root/.ssh/id_lsyncd -o StrictHostKeyChecking=no", + compress = true, + owner = true, + group = true, + archive = true + } +} +``` + +- start Lsyncd and enable automatic startup + +```bash +sudo systemctl restart lsyncd +sudo systemctl enable lsyncd +``` + +### configuration on alma9-c2 + +- test passwordless ssh access by logging in to alma9-c1 + +```bash +sudo ssh -i /root/.ssh/id_lsyncd root@alma9-c1 +``` + +- create a configuration file `/etc/lsyncd.conf` with the following content + +```lua +settings { + logfile = "/var/log/lsyncd/lsyncd.log", + statusFile = "/var/log/lsyncd/lsyncd.status", + statusInterval = 20, + nodaemon = false +} + +sync { + default.rsyncssh, + source = "/opt/acme2certifier/volume/", + host = "alma9-c1", + targetdir = "/opt/acme2certifier/volume/", + rsync = { + rsh = "/usr/bin/ssh -l root -i /root/.ssh/id_lsyncd -o StrictHostKeyChecking=no", + compress = true, + owner = true, + group = true, + archive = true + } +} +``` + +- start Lsyncd and enable automatic startup + +```bash +sudo systemctl restart lsyncd +sudo systemctl enable lsyncd +``` + +### Test replication + +#### test replication on alma9-c1 + +- create a file in `/opt/acme2certifier/volume` directory + +```bash +sudo touch /opt/acme2certifier/volume/test.txt +``` + +#### test replication on alma9-c2 + +- verify that the '/opt/acme2certifier/volume/test.txt' has been syncronized to alma9-c2 (please note that replication can take up to 20s) + +```bash +sudo ls -la /opt/acme2certifier/volume +``` + +- delete the '/opt/acme2certifier/volume/test.txt' + +```bash +sudo rm /opt/acme2certifier/volume/test.txt +``` + +#### verify deletion on alma9-c1 + +- back on alma9-c1 check `/opt/acme2certifier/volume` to make sure that "test.txt" has been deleted (please note that replication can take up to 20s) + +```bash +sudo ls -la /opt/acme2certifier/volume +``` + +In case of problem check the logfiles stored in `/var/log/lsyncd` for errors. + +## Install acme2certifier + +### on both nodes + +- Install django packages and mysqlclient + +```bash +sudo yum install python3-mysqlclient python3-django3 python3-pyyaml -y +``` + +- Downlaod the [latest rpm package](https://github.com/grindsa/acme2certifier/releases) +- install the package locally and fix permissions + +```bash +sudo yum localinstall -y ./acme2certifier_-1.0.noarch.rpm + sudo chown -R nginx /opt/acme2certifier/volume/ +``` + +- Copy and activete nginx configuration file + +```bash +sudo cp /opt/acme2certifier/examples/nginx/nginx_acme_srv.conf /etc/nginx/conf.d +``` + +- Copy and activate nginx ssl configuration file (optional) + +```bash +sudo cp /opt/acme2certifier/examples/nginx/nginx_acme_srv_ssl.conf /etc/nginx/conf.d +``` + +- copy the django handler and the django directory structure + +```bash +sudo cp /opt/acme2certifier/examples/db_handler/django_handler.py /opt/acme2certifier/acme_srv/db_handler.py +sudo cp -r /opt/acme2certifier/examples/django/* /opt/acme2certifier/ +``` + +- move the acme2certifier configuration file `acme_srv.cfg` into the mirrored diectory and create a symbolic link + +```bash +sudo mv /opt/acme2certifier/acme_srv/acme_srv.cfg /opt/acme2certifier/volume/ +sudo ln -s /opt/acme2certifier/volume/acme_srv.cfg /opt/acme2certifier/acme_srv/ +``` + +- Enable and start the apache2 service + +```bash +sudo systemctl enable acme2certifier +sudo systemctl start acme2certifier +sudo systemctl enable nginx +sudo systemctl start nginx +``` + +### on alma9-c1 + +- open the mysql commandline client + +```bash +sudo mysql -u root +``` + +- create a testdatabase and a test-table + +```SQL +CREATE DATABASE acme2certifier CHARACTER SET UTF8; +GRANT ALL PRIVILEGES ON acme2certifier.* TO 'acme2certifier'@'%' IDENTIFIED BY 'a2cpasswd'; +FLUSH PRIVILEGES; +``` + +- generate a new django secret-key and note it down + +```bash +python3 /opt/acme2certifier/tools/django_secret_keygen.py ++%*lei)yj9b841=2d5(u)a&7*uwi@l99$(*&ong@g*p1%q)g$e +``` + +- modify `/opt/acme2certifier/acme2certifier/settings.py` and + - insert the secret-key created in the previous step + - update the 'ALLOWED_HOSTS'- section with both ip-address and fqdn of the node + - configure a connection to mariadb as shown below + +```python +SECRET_KEY = '+%*lei)yj9b841=2d5(u)a&7*uwi@l99$(*&ong@g*p1%q)g$e' +... +ALLOWED_HOSTS = ['192.168.14.136', 'alma9-c1.bar.local'] +... + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.mysql', + 'NAME': 'acme2certifier', + 'USER': 'acme2certifier', + 'PASSWORD': 'a2cpasswd', + 'HOST': "alma9-c1", + 'OPTIONS': {"init_command": "SET sql_mode='STRICT_TRANS_TABLES', innodb_strict_mode=1","charset": "utf8mb4", "use_unicode": True}, + }, + +} +``` + +- Modify the [configuration file](acme_srv.md) `/opt/acme2certifier/volume/acme_srv.cfg`according to you needs. If your ca-handler needs runtime information (configuration files, keys, certificate-bundles etc.) to be shared between the nodes make sure that they get loaded from `/opt/acme2certifier/volume`. Below an example for the `[CAhandler]` section of the openssl-handler I use during my tests: + +```cfg +[CAhandler] +handler_file: /opt/acme2certifier/examples/ca_handler/openssl_ca_handler.py +ca_cert_chain_list: ["/opt/acme2certifier/volume/root-ca-cert.pem"] +issuing_ca_key: /opt/acme2certifier/volume/ca/sub-ca-key.pk8 +issuing_ca_key_passphrase_variable: OPENSSL_PASSPHRASE +issuing_ca_cert: /opt/acme2certifier/volume/ca/sub-ca-cert.pem +issuing_ca_crl: /opt/acme2certifier/volume/ca/sub-ca-crl.pem +cert_validity_days: 30 +cert_validity_adjust: True +cert_save_path: /opt/acme2certifier/volume/ca/certs +save_cert_as_hex: True +cn_enforce: True +``` + +- create a django migration set, apply the migrations and load fixtures + +```bash +cd /opt/acme2certifier +sudo python3 manage.py makemigrations +sudo python3 manage.py migrate +sudo python3 manage.py loaddata acme_srv/fixture/status.yaml +``` + +- run the django_update script + +```bash +sudo python3 /opt/acme2certifier/tools/django_update.py +``` + +- restart the acme2certifier service + +```bash +sudo systemctl restart acme2certifier.service +``` + +- Test the server by accessing the directory ressource + +```bash +curl http://alma9-c1.bar.local/directory +``` + +```bash +{"newAccount": "http://alma9-c1.bar.local/acme_srv/newaccount", "fa8b347d3849421ebc4b234205418805": "https://community.letsencrypt.org/t/adding-random-entries-to-the-directory/33417", "keyChange": "http://alma9-c1.bar.local/acme_srv/key-change", "newNonce": "http://alma9-c1.bar.local/acme_srv/newnonce", "meta": {"home": "https://github.com/grindsa/acme2certifier", "author": "grindsa "}, "newOrder": "http://alma9-c1.bar.local/acme_srv/neworders", "revokeCert": "http://alma9-c1.bar.local/acme_srv/revokecert"} +``` + +### on alma9-c2 + +- generate a new django secret and note it down + +```bash +python3 /opt/acme2certifier/tools/django_secret_keygen.py +5@@wlvvi!hb(6qc%*77j55@jt8ib4^f1o&+pz-^z*#v3e7u3o! +``` + +- modify `/opt/acme2certifier/acme2certifier/settings.py` and + - insert a secret key created in the previous step + - update the 'ALLOWED_HOSTS'- section with both IP-Adress and fqdn of the node + - configure a connection to mariadb as shown below + +```python +SECRET_KEY = '5@@wlvvi!hb(6qc%*77j55@jt8ib4^f1o&+pz-^z*#v3e7u3o!' +... +ALLOWED_HOSTS = ['192.168.14.137', 'alma9-c2.bar.local'] +... + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.mysql', + 'NAME': 'acme2certifier', + 'USER': 'acme2certifier', + 'PASSWORD': 'a2cpasswd', + 'HOST': "alma9-c2", + 'OPTIONS': {"init_command": "SET sql_mode='STRICT_TRANS_TABLES', innodb_strict_mode=1","charset": "utf8mb4", "use_unicode": True}, + }, + +} +``` + +- restart the acme2certifier service + +```bash +sudo systemctl restart acme2certifier.service +``` + +- Test the server by accessing the directory ressource + +```bash +curl http://alma9-c2.bar.local/directory +``` + +```bash +{"newAccount": "http://alma9-c2.bar.local/acme_srv/newaccount", "fa8b347d3849421ebc4b234205418805": "https://community.letsencrypt.org/t/adding-random-entries-to-the-directory/33417", "keyChange": "http://alma9-c2.bar.local/acme_srv/key-change", "newNonce": "http://alma9-c2.bar.local/acme_srv/newnonce", "meta": {"home": "https://github.com/grindsa/acme2certifier", "author": "grindsa "}, "newOrder": "http://alma9-c2.bar.local/acme_srv/neworders", "revokeCert": "http://alma9-c2.bar.local/acme_srv/revokecert"} +``` + +## Test enrollment + +- try to enroll certificates from both nodes by using your favorite acme-client. I am using [lego](https://github.com/go-acme/lego) as this client supports multiple endpoints at once. + +- Example for enrollment from alma9-c1 + +```bash + docker run -i -p 80:80 -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://alma9-c1.bar.local -a --email "lego@example.com" -d lego01.bar.local --http run +``` + +- Example for enrollment from alma9-c2 + +```bash + docker run -i -p 80:80 -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://alma9-c2.bar.local -a --email "lego@example.com" -d lego01.bar.local --http run +``` diff --git a/docs/a2c-alma-loadbalancing.png b/docs/a2c-alma-loadbalancing.png new file mode 100644 index 00000000..23142c27 Binary files /dev/null and b/docs/a2c-alma-loadbalancing.png differ diff --git a/docs/a2c-ubuntu-loadbalancing.md b/docs/a2c-ubuntu-loadbalancing.md new file mode 100644 index 00000000..af084bab --- /dev/null +++ b/docs/a2c-ubuntu-loadbalancing.md @@ -0,0 +1,671 @@ + + +# How to build am acme2certifier cluster on Ubuntu 22.04 + +This tutorial describes the configuration of a two-node acme2certifier cluster running in active/active configuration. Although both nodes are active at the same time and provide proxy services via different ip-addresses database, configuration and runtime objects will be replicated among the nodes. + +This setup requires the switch to a different database engine as SQLite, which is the default a2c backend, is not designed to handle concurrent write access, which can happen in an active/active setup. Thus, [MariaDB](https://mariadb.org/) will be used. Configuration files and runtime objects will be replicated using [Lsyncd](https://github.com/lsyncd/lsyncd). The following diagram depicts the application stack to be used. + +![architecture](a2c-ubuntu-loadbalancing.png "architecture") + +The guide is written for **Ubuntu 22.04**, however adapting to other Linux distributions should not be difficult. There is also a guide for [Alma Linux 9](a2c-alma-loadbalancing.md) available + +## Preparation + +To set up the MariaDB Master-Master replication between multiple servers, you will need to ensure each system hostname is resolved to the correct IP address. I recommend setting up the FQDN in /etc/hosts on each server. + +```cfg +cat /etc/hosts +... +192.168.14.132 ub2204-c1.bar.local ub2204-c1 +192.168.14.133 ub2204-c2.bar.local ub2204-c2 +``` + +Furthermore, Apache2 should already be installed to create the directories to be replicated. + +```bash +sudo apt-get install -y apache2 apache2-data libapache2-mod-wsgi-py3 +``` + +## Installation and configuration of MariaDB + +The following instructions are based on [an existing tutorial](https://www.howtoforge.com/how-to-setup-mariadb-master-master-replication-on-debian-11/). + +### Setting up ub2204-c1 + +- install MariaDB-server + +```bash +sudo apt install -y mariadb-server +``` + +- start MariaDB during startup + +```bash +sudo systemctl is-enabled mariadb +sudo systemctl status mariadb +``` + +- modify `/etc/mysql/mariadb.conf.d/50-server.cnf` change the ip-binding and add the follwinng lines + +```cfg +# listen on external address +bind-address = 192.168.14.132 + +server-id = 1 +report_host = ub2204-c1 + +log_bin = /var/log/mysql/mariadb-bin +log_bin_index = /var/log/mysql/mariadb-bin.index + +relay_log = /var/log/mysql/relay-bin +relay_log_index = /var/log/mysql/relay-bin.index + +# avoiding primary key collision +log-slave-updates +auto_increment_increment=2 +auto_increment_offset=1 +``` + +- restart MariaDB-server + +```bash +sudo systemctl restart mariadb +``` + +- verify service binding + +```bash +ss -plnt +State Recv-Q Send-Q Local Address:Port Peer Address:Port Process +... +LISTEN 0 80 192.168.14.132:3306 0.0.0.0:* users:(("mariadbd",pid=815,fd=43)) +... +``` + +- open the mysql commandclient client + +```bash +sudo mysql -u root +``` + +- create the replication user + +```SQL +CREATE USER 'replusr'@'%' IDENTIFIED BY 'replpasswd'; +GRANT REPLICATION SLAVE ON *.* TO 'replusr'@'%'; +FLUSH PRIVILEGES; +``` + +- Next, run the following query to check the current binary log and its exact position of it. In this example, the binary log file for the MariaDB server is "mariadb-bin.000001" with the position "773". These outputs will be used in the next stage for setting up the "ub2204-c2" server. + +```SQL +SHOW MASTER STATUS; +``` + +```SQL ++--------------------+----------+--------------+------------------+ +| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | ++--------------------+----------+--------------+------------------+ +| mariadb-bin.000001 | 773 | | | ++--------------------+----------+--------------+------------------+ +1 row in set (0.000 sec) +``` + +### Setting up ub2204-c2 + +- install MariaDB-server + +```bash +sudo apt install -y mariadb-server +``` + +- start MariaDB during startup + +```bash +sudo systemctl is-enabled mariadb +sudo systemctl status mariadb +``` + +- modify `/etc/mysql/mariadb.conf.d/50-server.cnf` change the ip-binding and add the follwinng lines + +```cfg +# listen on external address +bind-address = 192.168.14.133 + +server-id = 2 +report_host = ub2204-c2 + +log_bin = /var/log/mysql/mariadb-bin +log_bin_index = /var/log/mysql/mariadb-bin.index + +relay_log = /var/log/mysql/relay-bin +relay_log_index = /var/log/mysql/relay-bin.index + +# avoiding primary key collision +log-slave-updates +auto_increment_increment=2 +auto_increment_offset=2 +``` + +- restart MariaDB-server + +```bash +sudo systemctl restart mariadb +``` + +- verify service binding + +```bash +ss -plnt +``` + +```bash +State Recv-Q Send-Q Local Address:Port Peer Address:Port Process +... +LISTEN 0 80 192.168.14.133:3306 0.0.0.0:* users:(("mariadbd",pid=841,fd=41)) +... +``` + +- open the mysql commandclient client + +```bash +sudo mysql -u root +``` + +- create the replication user + +```SQL +CREATE USER 'replusr'@'%' IDENTIFIED BY 'replpasswd'; +GRANT REPLICATION SLAVE ON *.* TO 'replusr'@'%'; +FLUSH PRIVILEGES; +``` + +- stop the slave and add information about the ub2204-c1 master node as well as the binlog file name ("mariadb-bin.000001") and position ("773") from ub2204-c1. + +```SQL +STOP SLAVE; +CHANGE MASTER TO MASTER_HOST='ub2204-c1', MASTER_USER='replusr', MASTER_PASSWORD='replpasswd', MASTER_LOG_FILE='mariadb-bin.000001', MASTER_LOG_POS=773; +``` + +- start the slave again and verify the slave status on the "ub2204-c2" server. You should get "Slave_IO_Running: Yes" and "Slave_SQL_Running: Yes", + +```SQL +START SLAVE; +SHOW SLAVE STATUS\G +``` + +```SQL +*************************** 1. row *************************** + Slave_IO_State: Waiting for master to send event + Master_Host: ub2204-c1 +... + Slave_IO_Running: Yes + Slave_SQL_Running: Yes +... +``` + +### Configure master-master replication on ub2204-c1 + +- open the mysql commandclient client and create the replication user + +```bash +sudo mysql -u root +``` + +- stop the slave and add information about the ub2204-c2 master node as well as the binlog file name and position. + +```SQL +STOP SLAVE; +CHANGE MASTER TO MASTER_HOST='ub2204-c2', MASTER_USER='replusr', MASTER_PASSWORD='replpasswd', MASTER_LOG_FILE='mariadb-bin.000001', MASTER_LOG_POS=773; +``` + +- start the slave again and verify the slave status + +```SQL +START SLAVE; +``` + +```SQL +SHOW SLAVE STATUS\G +*************************** 1. row *************************** + Slave_IO_State: Waiting for master to send event + Master_Host: ub2204-c1 +... + Slave_IO_Running: Yes + Slave_SQL_Running: Yes +... +``` + +### Test master-master replication + +#### test replication on ub2204-c1 + +- open the mysql commandline client + +```bash +sudo mysql -u root +``` + +- create a testdatabase and a test-table + +```SQL +CREATE DATABASE testdb; +``` + +#### test replication on ub2204-c2 + +- open the mysql commandline client + +```bash +sudo mysql -u root +``` + +- check the databases created in previous step + +```SQL +SHOW DATABASES; ++--------------------+ +| Database | ++--------------------+ +| information_schema | +| mysql | +| performance_schema | +| sys | +| testdb | ++--------------------+ +5 rows in set (0.000 sec) +``` + +```SQL +MariaDB [(none)]> +``` + +- delete database + +```SQL +DROP DATABASE testdb; +``` + +#### verify deletion on ub2204-c1 + +- back on ub2204-c1 check the databases to make sure that "testdb" is not present anymore + +```SQL +SHOW DATABASES; +``` + +```SQL ++--------------------+ +| Database | ++--------------------+ +| information_schema | +| mysql | +| performance_schema | +| sys | ++--------------------+ +4 rows in set (0.000 sec) + +``` + +## Configure directory replication via Lsyncd + +The following instructions are based on [an existing tutorial](https://docs.rackspace.com/docs/set-up-lsyncd-locally-and-over-ssh-to-sync-directories). + +To accomplish a remote synchronization using Lsyncd, each node must have password-less SSH access to its peer. Further, it is recommended to use the root-user for synchronization to ensure that permissions, ownership, and group information of the synchronized objects will be preserved. + +### on both nodes to be executed as root-user + +- generate ssh keys + +```bash +sudo ssh-keygen -t rsa -f /root/.ssh/id_lsyncd +``` + +- copy the newly created public key `/root/.ssh/id_lsyncd.pub` from each host to peer and add it to `/root/.ssh/authorized_keys` file + +- create the acme2certifier directory to be synchronized between the two hosts + +```bash +sudo mkdir -p /var/www/acme2certifier/volume +``` + +- install Lsyncd + +```bash +sudo apt-get install -y lsyncd +``` + +- create the directory storing the configuration and log files + +```bash +sudo mkdir /etc/lsyncd /var/log/lsyncd +``` + +### configuration on ub2204-c1 + +- test passwordless ssh access by logging in to ub2204-c2 + +```bash +sudo ssh -i /root/.ssh/id_lsyncd root@ub2204-c2 +exit +``` + +- create a configuration file `/etc/lsyncd/lsyncd.conf.lua` with the following content + +```lua +settings { + logfile = "/var/log/lsyncd/lsyncd.log", + statusFile = "/var/log/lsyncd/lsyncd.status", + statusInterval = 20, + nodaemon = false +} + +sync { + default.rsyncssh, + source = "/var/www/acme2certifier/volume/", + host = "ub2204-c2", + targetdir = "/var/www/acme2certifier/volume/", + rsync = { + rsh = "/usr/bin/ssh -l root -i /root/.ssh/id_lsyncd -o StrictHostKeyChecking=no", + compress = true, + owner = true, + group = true, + archive = true + } +} +``` + +- start Lsyncd and enable automatic startup + +```bash +sudo systemctl restart lsyncd +sudo systemctl enable lsyncd +``` + +### configuration on ub2204-c2 + +- test passwordless ssh access by logging in to ub2204-c1 + +```bash +sudo ssh -i /root/.ssh/id_lsyncd root@ub2204-c1 +``` + +- create a configuration file `/etc/lsyncd/lsyncd.conf.lua` with the following content + +```lua +settings { + logfile = "/var/log/lsyncd/lsyncd.log", + statusFile = "/var/log/lsyncd/lsyncd.status", + statusInterval = 20, + nodaemon = false +} + +sync { + default.rsyncssh, + source = "/var/www/acme2certifier/volume/", + host = "ub2204-c1", + targetdir = "/var/www/acme2certifier/volume/", + rsync = { + rsh = "/usr/bin/ssh -l root -i /root/.ssh/id_lsyncd -o StrictHostKeyChecking=no", + compress = true, + owner = true, + group = true, + archive = true + } +} +``` + +- start Lsyncd and enable automatic startup + +```bash +sudo systemctl restart lsyncd +sudo systemctl enable lsyncd +``` + +### Test replication + +#### test repliasyncronizationtion on ub2204-c1 + +- create a file in `/var/www/acme2certifier/volume` directory + +```bash +sudo touch /var/www/acme2certifier/volume/test.txt +``` + +#### test syncronization on ub2204-c2 + +- verify that the '/var/www/acme2certifier/volume/test.txt' has been syncronized to ub2204-c2 (please note that replication can take up to 20s) + +```bash +sudo ls -la /var/www/acme2certifier/volume +``` + +- delete the '/var/www/acme2certifier/volume/test.txt' + +```bash +sudo rm /var/www/acme2certifier/volume/test.txt +``` + +#### verify removal on ub2204-c1 + +- back on ub2204-c1 check `/var/www/acme2certifier/volume` to make sure that "test.txt" has been deleted (please note that replication can take up to 20s) + +```bash +sudo ls -la /var/www/acme2certifier/volume +``` + +In case of problem check the logfiles stored in `/var/log/lsyncd` for errors. + +## Install acme2certifier + +### on both nodes + +- Downlaod the [latest deb package](https://github.com/grindsa/acme2certifier/releases) +- install the package locally + +```bash +sudo apt-get install -y ./acme2certifier_-1_all.deb +``` + +- Copy and activete apache2 configuration file + +```bash +sudo cp /var/www/acme2certifier/examples/apache2/apache_django.conf /etc/apache2/sites-available/acme2certifier.conf +sudo a2ensite acme2certifier +``` + +- Copy and activate apache2 ssl configuration file (optional) + +```bash +sudo cp /var/www/acme2certifier/examples/apache2/apache_django_ssl.conf /etc/apache2/sites-available/acme2certifier_ssl.conf +sudo a2ensite acme2certifier_ssl +``` + +- disable the default sites + +```bash +sudo a2dissite 000-default.conf +sudo a2dissite default-ssl +``` + +- copy the django handler and the django directory structure + +```bash +sudo cp /var/www/acme2certifier/examples/db_handler/django_handler.py /var/www/acme2certifier/acme_srv/db_handler.py +sudo cp -R /var/www/acme2certifier/examples/django/* /var/www/acme2certifier/ +``` + +- move the acme2certifier configuration file `acme_srv.cfg` into the mirrored diectory and create a symbolic link + +```bash +sudo mv /var/www/acme2certifier/acme_srv/acme_srv.cfg /var/www/acme2certifier/volume/ +sudo ln -s /var/www/acme2certifier/volume/acme_srv.cfg /var/www/acme2certifier/acme_srv/ +``` + +- Enable and start the apache2 service + +```bash +sudo systemctl enable apache2.service +sudo systemctl start apache2.service +``` + +### setup on ub2204-c1 + +- open the mysql commandline client + +```bash +sudo mysql -u root +``` + +- create a testdatabase and a test-table + +```SQL +CREATE DATABASE acme2certifier CHARACTER SET UTF8; +GRANT ALL PRIVILEGES ON acme2certifier.* TO 'acme2certifier'@'%' IDENTIFIED BY 'a2cpasswd'; +FLUSH PRIVILEGES; +``` + +- generate a new django secret-key and note it down + +```bash +python3 /var/www/acme2certifier/tools/django_secret_keygen.py ++%*lei)yj9b841=2d5(u)a&7*uwi@l99$(*&ong@g*p1%q)g$e +``` + +- modify `/var/www/acme2certifier/acme2certifier/settings.py` and + - insert the secret-key created in the previous step + - update the 'ALLOWED_HOSTS'- section with both ip-address and fqdn of the node + - configure a connection to mariadb as shown below + +```python +SECRET_KEY = '+%*lei)yj9b841=2d5(u)a&7*uwi@l99$(*&ong@g*p1%q)g$e' +... +ALLOWED_HOSTS = ['192.168.14.132', 'ub2204-c1.bar.local'] +... + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.mysql', + 'NAME': 'acme2certifier', + 'USER': 'acme2certifier', + 'PASSWORD': 'a2cpasswd', + 'HOST': "ub2204-c1", + 'OPTIONS': {"init_command": "SET sql_mode='STRICT_TRANS_TABLES', innodb_strict_mode=1","charset": "utf8mb4", "use_unicode": True}, + }, + +} +``` + +- Modify the [configuration file](acme_srv.md) `/var/www/acme2certifier/volume/acme_srv.cfg`according to you needs. If your ca-handler needs runtime information (configuration files, keys, certificate-bundles etc.) to be shared between the nodes make sure that they get loaded from `/var/www/acme2certifier/volume`. Below an example for the `[CAhandler]` section of the openssl-handler I use during my tests: + +```cfg +[CAhandler] +handler_file: /var/www/acme2certifier/examples/ca_handler/openssl_ca_handler.py +ca_cert_chain_list: ["/var/www/acme2certifier/volume/root-ca-cert.pem"] +issuing_ca_key: /var/www/acme2certifier/volume/ca/sub-ca-key.pk8 +issuing_ca_key_passphrase_variable: OPENSSL_PASSPHRASE +issuing_ca_cert: /var/www/acme2certifier/volume/ca/sub-ca-cert.pem +issuing_ca_crl: /var/www/acme2certifier/volume/ca/sub-ca-crl.pem +cert_validity_days: 30 +cert_validity_adjust: True +cert_save_path: /var/www/acme2certifier/volume/ca/certs +save_cert_as_hex: True +cn_enforce: True +``` + +- create a django migration set, apply the migrations and load fixtures + +```bash +cd /var/www/acme2certifier +sudo python3 manage.py makemigrations +sudo python3 manage.py migrate +sudo python3 manage.py loaddata acme_srv/fixture/status.yaml +``` + +- run the django_update script + +```bash +sudo python3 /var/www/acme2certifier/tools/django_update.py +``` + +- restart the apache2 service + +```bash +sudo systemctl restart apache2.service +``` + +- Test the server by accessing the directory ressource + +```bash +curl http://ub2204-c1.bar.local/directory +``` + +```bash +{"newAccount": "http://ub2204-c1.bar.local/acme_srv/newaccount", "fa8b347d3849421ebc4b234205418805": "https://community.letsencrypt.org/t/adding-random-entries-to-the-directory/33417", "keyChange": "http://ub2204-c1.bar.local/acme_srv/key-change", "newNonce": "http://ub2204-c1.bar.local/acme_srv/newnonce", "meta": {"home": "https://github.com/grindsa/acme2certifier", "author": "grindsa "}, "newOrder": "http://ub2204-c1.bar.local/acme_srv/neworders", "revokeCert": "http://ub2204-c1.bar.local/acme_srv/revokecert"} +``` + +### setup on ub2204-c2 + +- generate a new django secret and note it down + +```bash +python3 /var/www/acme2certifier/tools/django_secret_keygen.py +5@@wlvvi!hb(6qc%*77j55@jt8ib4^f1o&+pz-^z*#v3e7u3o! +``` + +- modify `/var/www/acme2certifier/acme2certifier/settings.py` and + - insert a secret key created in the previous step + - update the 'ALLOWED_HOSTS'- section with both IP-Adress and fqdn of the node + - configure a connection to mariadb as shown below + +```python +SECRET_KEY = '5@@wlvvi!hb(6qc%*77j55@jt8ib4^f1o&+pz-^z*#v3e7u3o!' +... +ALLOWED_HOSTS = ['192.168.14.133', 'ub2204-c2.bar.local'] +... + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.mysql', + 'NAME': 'acme2certifier', + 'USER': 'acme2certifier', + 'PASSWORD': 'a2cpasswd', + 'HOST': "ub2204-c2", + 'OPTIONS': {"init_command": "SET sql_mode='STRICT_TRANS_TABLES', innodb_strict_mode=1","charset": "utf8mb4", "use_unicode": True}, + }, + +} +``` + +- restart the apache2 service + +```bash +sudo systemctl restart apache2.service +``` + +- Test the server by accessing the directory ressource + +```bash +curl http://ub2204-c2.bar.local/directory +``` + +```bash +{"newAccount": "http://ub2204-c2.bar.local/acme_srv/newaccount", "fa8b347d3849421ebc4b234205418805": "https://community.letsencrypt.org/t/adding-random-entries-to-the-directory/33417", "keyChange": "http://ub2204-c2.bar.local/acme_srv/key-change", "newNonce": "http://ub2204-c2.bar.local/acme_srv/newnonce", "meta": {"home": "https://github.com/grindsa/acme2certifier", "author": "grindsa "}, "newOrder": "http://ub2204-c2.bar.local/acme_srv/neworders", "revokeCert": "http://ub2204-c2.bar.local/acme_srv/revokecert"} +``` + +## Test enrollment + +- try to enroll certificates from both nodes by using your favorite acme-client. I am using [lego](https://github.com/go-acme/lego) as this client supports multiple endpoints at once. + +- Example for enrollment from ub2204-c1 + +```bash + docker run -i -p 80:80 -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://ub2204-c1.bar.local -a --email "lego@example.com" -d lego01.bar.local --http run +``` + +- Example for enrollment from ub2204-c2 + +```bash + docker run -i -p 80:80 -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://ub2204-c2.bar.local -a --email "lego@example.com" -d lego01.bar.local --http run +``` diff --git a/docs/a2c-ubuntu-loadbalancing.png b/docs/a2c-ubuntu-loadbalancing.png new file mode 100644 index 00000000..6d68e075 Binary files /dev/null and b/docs/a2c-ubuntu-loadbalancing.png differ diff --git a/docs/acme_ca.md b/docs/acme_ca.md index a90732f1..76b00c35 100644 --- a/docs/acme_ca.md +++ b/docs/acme_ca.md @@ -45,11 +45,14 @@ The handler must be configured via `acme_srv`. | handler_file | path to ca_handler file | yes | None | | account_path | path to account ressource on ca server | no | '/acme/acct' | | acme_url | url of the acme endpoint | yes | None | -| acme_account | acme account name. If not specified acme2certifer will try to lookup the account name based on the key-file | yes | None | -| acme_keyfile | Path to private key json-format. If specified in config but not existing on file-system acme2certifer will generate a new key and try to register it | +| acme_account | acme account name. If not specified acme2certifer will try to lookup the account name based on the key-file | no | None | +| acme_keyfile | Path to private key json-format. If specified in config but not existing on file-system acme2certifer will generate a new key and try to register it | no | None | +| acme_keypath | Path to private key directory. If specified in config acme2certifer store new keys in this directory | no | None | | acme_account_email | email address used to register a new account | no | None | | allowed_domainlist | list of domain-names allowed for enrollment in json format example: ["bar.local$, bar.foo.local] | no | [] | | directory_path | path to directory ressource on ca server | no | '/directory' | +| eab_profiling | enable eab-profiling | None | False | +| ssl_verify | verify certificates on SSL connections | no | True | - modify the server configuration (`acme_srv/acme_srv.cfg`) and add at least the following parameters. @@ -109,6 +112,18 @@ acme_account_email: email@example.com account_path: /account/ ``` +# Example for smallstep ca + +Below a configuration to connect to a smallstep ca under the assumption that a provisioner called `myacme` has been created. + +```cfg +acme_keyfile: acme_srv/acme/smallstep.json +acme_url: https:///acme/myacme +acme_account_email: email@example.com +account_path: / +ssl_verify: False +``` + ## Example key-file in json format This is just an example for your reference. DO NOT USE IT ON YOUR SYSTEM! @@ -129,3 +144,73 @@ You can also use existing keys generated by `certbot` which are usually stored i "dq": "cVUb7KqdUgpQO_T4jDKmb_6EdavdzPsu8wzKyLNI4MD1AtSVr-nWwY6QFCQulpdNM86nR0lmwadieuaxaeressdNW5RR0O0CJRTYHM_K1J88X8nKv-vBCiyd0QHFTEZngP51F-FtJg5yKeW7rUMYNAsCMOVaR7p8InelmiGgWpgU" } ``` + +## Passing a profileID from client to server + +The handler makes use of the [header_info_list feature](header_info.md) allowing an acme-client to specify acme-backend address to be used during certificate enrollment. This feature is disabled by default and must be activate in `acme_srv.cfg` as shown below + +```config +[Order] +... +header_info_list: ["HTTP_USER_AGENT"] +``` + +The acme-client can then specify the acme_url as part of its user-agent string. + +Example for acme.sh: + +```bash +docker exec -i acme-sh acme.sh --server http:// --issue -d --standalone --useragent acme_url= --debug 3 --output-insecure +``` + +Example for lego: + +```bash +docker run -i -v $PWD/lego:/.lego/ --rm --name lego goacme/lego -s http:// -a --email "lego@example.com" --user-agent acme_url= -d --http run +``` + +# eab profiling + +This handler can use the [eab profiling feture](eab_profiling.md) to allow individual enrollment configuration per acme-account as well as restriction of CN and SANs to be submitted within the CSR. The feature is disabled by default and must be activated in `acme_srv.cfg` + +**Important**: In case `acme_url` variables will be specified in a profile (like for 'keyid_00' in the below example), the `acme_key_path` parameter must be set in `acme_srv.cfg` to ensure that the different key_files are being stored correctly. + +```cfg +[EABhandler] +eab_handler_file: examples/eab_handler/kid_profile_handler.py +acme_key_path: + +[CAhandler] +eab_profiling: True +``` + +below an example key-file: + +```json +{ + "keyid_00": { + "hmac": "V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw", + "cahandler": { + "acme_url": ["https://acme-staging-v02.api.letsencrypt.org", "https://api.buypass.com/acme", "https://acme.ssl.com/sslcom-dv-rsa"], + "allowed_domainlist": ["www.example.com", "www.example.org", "*.acme"] + } + }, + "keyid_01": { + "hmac": "YW5vdXRoZXJfdmVyeV9sb25nX2htYWNfZm9yX2tleWlkXzAxX3doaWNoIHdpbGxfYmUgdXNlZF9kdXJpbmcgcmVncmVzc2lvbg", + "cahandler": { + "acme_url": "https://acme-staging-v02.api.letsencrypt.org", + "acme_keyfile": "/var/www/acme2certifier/volume/acme_ca/le_key.json", + "allowed_domainlist": ["www.example.com", "www.example.org", "*.acme"] + } + }, + "keyid_02": { + "hmac": "dGhpc19pc19hX3ZlcnlfbG9uZ19obWFjX3RvX21ha2Vfc3VyZV90aGF0X2l0c19tb3JlX3RoYW5fMjU2X2JpdHM", + "cahandler": { + "allowed_domainlist": ["www.example.com", "www.example.org"] + } + }, + "keyid_03": { + "hmac": "YW5kX2ZpbmFsbHlfdGhlX2xhc3RfaG1hY19rZXlfd2hpY2hfaXNfbG9uZ2VyX3RoYW5fMjU2X2JpdHNfYW5kX3Nob3VsZF93b3Jr" + } +} +``` diff --git a/docs/acme_srv.md b/docs/acme_srv.md index 5626f824..8174a7e5 100644 --- a/docs/acme_srv.md +++ b/docs/acme_srv.md @@ -16,13 +16,16 @@ | `CAhandler` | `handler_file` | path and name of ca_handler file to be loaded. If not specified `acme_srv/ca_handler.py` will be loaded | examples/ca_handler/openssl_handler.py | `acme_srv/ca_handler.py`| | `Certificate` | `revocation_reason_check_disable` | disable the check of revocation reason | True/False | False| | `Certificate` | `cert_reusage_timeframe` | in case a csr will be resend within this timeframe (in seconds) the certificate already stored in the database will be returned and no enrollment will be triggered| Integer |0 (disabled)| -| `Certificate` | `enrollment_timeout` | timeout in second for asynchronous ca_handler threat| Integer |5| +| `Certificate` | `enrollment_timeout` | timeout in seconds for asynchronous ca_handler threat| Integer |5| | `Challenge` | `challenge_validation_disable` | disable challenge validation via http or dns. THIS IS A SEVERE SECURITY ISSUE! Please enable for testing/debugging purposes only. | True/False | False| | `Challenge` | `challenge_validation_timeout` | Timeout in seconds for challenge validation | Integer | 10 | | `Challenge` | `dns_server_list` | Use own dns servers for name resolution during challenge verification| ["ip1", "ip2"] | []| +| `Challenge` | `dns_validation_pause_timer` | pause interval in seconds after failed validation of a dns challenge | 10 | 0.5 | | `Challenge` | `sectigo_sim` | provide `sectigo-email-01` challenges - Only for development and testing! | True/False | False | | `DBhandler` | `dbfile` | path and name of database file. If not specified `acme_srv/acme_srv.db` will be used. Parameter is only available for a wsgi handler and will be ignored if django handler is getting used | 'acme/database.db' | `acme_srv/acme_srv.db`| | `Directory` | `db_check` | check database connection compare schemes and report as OK/NOK in meta information | True/False | False| +| `Directory` | `home` | homepage string to be shown when fetching the directory ressource | 'string' | 'https://github.com/grindsa/acme2certifier' | +| `Directory` | `supress_product_information` | Do not show product name, author and version when fetching the directory resource | True/False | False| | `Directory` | `supress_version` | Do not show version information when fetching the directory resource | True/False | False| | `Directory` | `tos_url` | Terms of Service URL | URL | None| | `Directory` | `url_prefix` | url prefix for acme2certifier resources | '/foo' | None| @@ -36,6 +39,7 @@ | `Order` | `expiry_check_disable` | Disable order expiration | True/False | False| | `Order` | `header_info_list` | HTTP header fields to be passed to ca handler | ["HTTP_USER_AGENT", "FOO_BAR"] |[]| | `Order` | `retry_after_timeout` | Retry-After value to be send to client in case a certificate enrollment request gets pending on CA server | Integer |120| +| `Order` | `identifier_limit` | Maximum number of identifiers submitted in a single order request which translate later into SANs per certificate | Integer |20| | `Order` | [`tnauthlist_support`](tnauthlist.md) | accept [TNAuthList identifiers](https://tools.ietf.org/html/draft-ietf-acme-authority-token-tnauthlist-03) and challenges containing [tkauth-01 type](https://tools.ietf.org/html/draft-ietf-acme-authority-token-03) | True/False | False| | `Order` | `validity` | Order validity in seconds | Integer |86400| diff --git a/docs/asa.md b/docs/asa.md new file mode 100644 index 00000000..d43359cc --- /dev/null +++ b/docs/asa.md @@ -0,0 +1,83 @@ + + +# Connecting to Insta ActiveCMS + +## Prerequisites + +- ActiveCMS needs to have Active Security API activated +- you need to have user, password and an api key to access the ASA +- you need ot have permissions to revoke and enroll certificates + +## Configuration + +- modify the server configuration (`/acme_srv/acme_srv.cfg`) and add the following parameters + +```config +[CAhandler] +handler_file: examples/ca_handler/asa_ca_handler.py +api_host: http://: +api_user: +api_password: +api_key: +ca_bundle: +ca_name: +profile_name: +cert_validity_days: +``` + +- api_host - URL of Active Security API +- api_user - REST user +- api_user_variable - *optional* - name of the environment variable containing the REST username (a configured `api_user` parameter in acme_srv.cfg takes precedence) +- api_password - password for REST user +- api_password_variable - *optional* - name of the environment variable containing the password for the REST user (a configured `api_password` parameter in acme_srv.cfg takes precedence) +- api_key - key for REST user +- api_key_variable - *optional* - name of the environment variable containing the api_key for the REST access (a configured `api_key` parameter in acme_srv.cfg takes precedence) +- ca_bundle - certificate bundle needed to validate the server certificate - can be True/False or a filename (default: None) +- ca_name - name of the CA used to enroll certificates +- profile_name - profile name +- cert_validity_days - optional - polling timeout (default: 60s) + +It is also recommended to increase the enrollment timeout to avoid that acme2certifier is closing the connection to early. + +```config +[Certificate] +enrollment_timeout:15 +``` + +You can get the list of certificate authrities by running the following REST call against ASA. + +```bash +root@rlh:~# curl -u '$api_user':'$api_password' -H "x-api-key: $api_host'/list_issuers +``` + +You can get the list of profiles by running the following REST call against ASA (ca_name parameter must be [url-encoded](https://en.wikipedia.org/wiki/Percent-encoding)). + +```bash +root@rlh:~# curl -u '$api_user':'$api_password' -H "x-api-key: $api_host'/list_profiles?issuerName= +``` + +The CA handler will verify ca_name and profile_name parameters before enrollment. + +## Passing a profileID from client to server + +The handler makes use of the [header_info_list feature](header_info.md) allowing an acme-client to specify a profile_name to be used during certificate enrollment. This feature is disabled by default and must be activate in `acme_srv.cfg` as shown below + +```config +[Order] +... +header_info_list: ["HTTP_USER_AGENT"] +``` + +The acme-client can then specify the profile_name as part of its user-agent string. + +Example for acme.sh: + +```bash +docker exec -i acme-sh acme.sh --server http:// --issue -d --standalone --useragent profile_name= --debug 3 --output-insecure +``` + +Example for lego: + +```bash +docker run -i -v $PWD/lego:/.lego/ --rm --name lego goacme/lego -s http:// -a --email "lego@example.com" --user-agent profile_name= -d --http run +``` diff --git a/docs/certifier.md b/docs/certifier.md index fab9d67a..71734aa4 100644 --- a/docs/certifier.md +++ b/docs/certifier.md @@ -21,6 +21,7 @@ ca_bundle: ca_name: profile_id: polling_timeout: +eab_profiling: ``` - api_host - URL of the Certifier-REST service @@ -32,6 +33,7 @@ polling_timeout: - ca_name - name of the CA used to enroll certificates - profile_id - optional - profileId - polling_timeout - optional - polling timeout (default: 60s) +- eab_profiling - optional - [activate eab profiling](eab_profiling.md) (default: False) Depending on CA policy configuration a CSR may require approval. In such a situation acme2certfier will poll the CA server to check the CSR status. The polling interval can be configured in acme.server.cfg. @@ -72,9 +74,9 @@ The response to this call will show a dictionary containing the list of CAs incl ] ``` -## Passing a profileID from client to server +## Passing a profile_id from client to server -The handler makes use of the [header_info_list feature](header_info.md) allowing an acme-client to specify a profileID to be used during certificate enrollment. This feature is disabled by default and must be activate in `acme_srv.cfg` as shown below +The handler makes use of the [header_info_list feature](header_info.md) allowing an acme-client to specify a profile_id to be used during certificate enrollment. This feature is disabled by default and must be activate in `acme_srv.cfg` as shown below ```config [Order] @@ -87,13 +89,57 @@ The acme-client can then specify the profileID as part of its user-agent string. Example for acme.sh: ```bash -docker exec -i acme-sh acme.sh --server http:// --issue -d --standalone --useragent profileID=101 --debug 3 --output-insecure +docker exec -i acme-sh acme.sh --server http:// --issue -d --standalone --useragent profile_id=101 --debug 3 --output-insecure ``` Example for lego: ```bash -docker run -i -v $PWD/lego:/.lego/ --rm --name lego goacme/lego -s http:// -a --email "lego@example.com" --user-agent profileID=101 -d --http run +docker run -i -v $PWD/lego:/.lego/ --rm --name lego goacme/lego -s http:// -a --email "lego@example.com" --user-agent profile_id=101 -d --http run +``` + +# eab profiling + +This handler can use the [eab profiling feture](eab_profiling.md) to allow individual enrollment configuration per acme-account as well as restriction of CN and SANs to be submitted within the CSR. The feature is disabled by default and must be activated in `acme_srv.cfg` + +```cfg +[EABhandler] +eab_handler_file: examples/eab_handler/kid_profile_handler.py +key_file: + +[CAhandler] +eab_profiling: True +``` + +below an example key-file used during regression testing: + +```json +{ + "keyid_00": { + "hmac": "V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw", + "cahandler": { + "profile_id": ["p100", "p101", "p102"], + "allowed_domainlist": ["www.example.com", "www.example.org", "*.acme"] + } + }, + "keyid_01": { + "hmac": "YW5vdXRoZXJfdmVyeV9sb25nX2htYWNfZm9yX2tleWlkXzAxX3doaWNoIHdpbGxfYmUgdXNlZF9kdXJpbmcgcmVncmVzc2lvbg", + "cahandler": { + "profile_id": "102", + "allowed_domainlist": ["www.example.com", "www.example.org", "*.acme"], + "ca_name": "subca2" + } + }, + "keyid_02": { + "hmac": "dGhpc19pc19hX3ZlcnlfbG9uZ19obWFjX3RvX21ha2Vfc3VyZV90aGF0X2l0c19tb3JlX3RoYW5fMjU2X2JpdHM", + "cahandler": { + "allowed_domainlist": ["www.example.com", "www.example.org"] + } + }, + "keyid_03": { + "hmac": "YW5kX2ZpbmFsbHlfdGhlX2xhc3RfaG1hY19rZXlfd2hpY2hfaXNfbG9uZ2VyX3RoYW5fMjU2X2JpdHNfYW5kX3Nob3VsZF93b3Jr" + } +} ``` ## CA policy configuration diff --git a/docs/database_scheme.png b/docs/database_scheme.png index cbb7f313..320d095e 100644 Binary files a/docs/database_scheme.png and b/docs/database_scheme.png differ diff --git a/docs/digicert.md b/docs/digicert.md new file mode 100644 index 00000000..e3bf9687 --- /dev/null +++ b/docs/digicert.md @@ -0,0 +1,116 @@ + + +# Connecting to DigiCert CertCentral + +This handler can be used to enroll certificates from [DigiCert CertCentral](https://dev.digicert.com/en/certcentral-apis.html). + +## Prerequisites + +- you'll need: + - a DigiCert CertCentral subscription :-) + - an [API-Key](https://dev.digicert.com/en/certcentral-apis/authentication.html) for Authentication and Authorization + - an [Organization](https://dev.digicert.com/en/certcentral-apis/services-api/organizations.html) + - a [whitelisted domain](https://dev.digicert.com/en/certcentral-apis/services-api/domains.html) + +## Configuration + +- modify the server configuration (`acme_srv.cfg`) and add the first thre of the below mentioned parameters + +```confag +[CAhandler] +handler_file: examples/ca_handler/digicert_ca_handler.py +api_key: +organization_name: + +allowed_domainlist: +api_url: +organization_id: +cert_type: +signature_hash: +order_validity: +request_timeout: +eab_profiling: +``` + +- api_key - required - API key to access the API +- organization_name - required - Organization name as specified in DigiCert CertCentral +- allowed_domainlist: list of domain-names allowed for enrollment in json format (example: ["bar.local$, bar.foo.local]) +- api_url - optional - URL of the CertCentral API +- organization_id - optional - organization id - configuration prevents additional rest-lookups +- cert_type - optional - [certificte type](https://dev.digicert.com/en/certcentral-apis/services-api/orders.html) to be isused. (default: ssl_basic) +- signature_hash - optional - hash algorithm used for certificate signing - (default: sha256) +- order_validity - optional - oder validity (default: 1 year) +- request_timeout - optional - requests timeout in seconds for requests (default: 5s) +- eab_profiling - optional - [activate eab profiling](eab_profiling.md) (default: False) + +Use your favorite acme client for certificate enrollment. A list of clients used in our regression can be found in the [disclaimer section of our README file](../README.md) + +*Important:* the DigiCert API expectes a CommonName to be set. Hence, certbot cannot be used for certificate enrollment. + +## Passing a cert_type from client to server + +The handler makes use of the [header_info_list feature](header_info.md) allowing an acme-client to specify a [certificate type](https://dev.digicert.com/en/certcentral-apis/services-api/orders.html) to be used during certificate enrollment. This feature is disabled by default and must be activate in `acme_srv.cfg` as shown below + +```config +[Order] +... +header_info_list: ["HTTP_USER_AGENT"] +``` + +The acme-client can then specify the cert_type as part of its user-agent string. + +Example for acme.sh: + +```bash +docker exec -i acme-sh acme.sh --server http:// --issue -d --standalone --useragent cert_type=ssl_securesite_pro --debug 3 --output-insecure +``` + +Example for lego: + +```bash +docker run -i -v $PWD/lego:/.lego/ --rm --name lego goacme/lego -s http:// -a --email "lego@example.com" --user-agent cert_type=ssl_securesite_pro -d --http run +``` + +# eab profiling + +This handler can use the [eab profiling feture](eab_profiling.md) to allow individual enrollment configuration per acme-account as well as restriction of CN and SANs to be submitted within the CSR. The feature is disabled by default and must be activated in `acme_srv.cfg` + +```cfg +[EABhandler] +eab_handler_file: examples/eab_handler/kid_profile_handler.py +key_file: + +[CAhandler] +eab_profiling: True +``` + +below an example key-file used during regression testing: + +```json +{ + "keyid_00": { + "hmac": "V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw", + "cahandler": { + "cert_type": ["ssl_basic", "ssl_securesite_pro", "ssl_securesite_flex"], + "allowed_domainlist": ["www.example.com", "www.example.org", "*.acme"], + "organization_name": "acme2certifier" + } + }, + "keyid_01": { + "hmac": "YW5vdXRoZXJfdmVyeV9sb25nX2htYWNfZm9yX2tleWlkXzAxX3doaWNoIHdpbGxfYmUgdXNlZF9kdXJpbmcgcmVncmVzc2lvbg", + "cahandler": { + "allowed_domainlist": ["www.example.com", "www.example.org", "*.acme"], + "cert_type": "ssl_securesite_pro" + } + }, + "keyid_02": { + "hmac": "dGhpc19pc19hX3ZlcnlfbG9uZ19obWFjX3RvX21ha2Vfc3VyZV90aGF0X2l0c19tb3JlX3RoYW5fMjU2X2JpdHM", + "cahandler": { + "allowed_domainlist": ["www.example.com", "www.example.org"] + } + }, + "keyid_03": { + "hmac": "YW5kX2ZpbmFsbHlfdGhlX2xhc3RfaG1hY19rZXlfd2hpY2hfaXNfbG9uZ2VyX3RoYW5fMjU2X2JpdHNfYW5kX3Nob3VsZF93b3Jr" + } +} +``` diff --git a/docs/eab.md b/docs/eab.md index 9fd745fd..8506b2bb 100644 --- a/docs/eab.md +++ b/docs/eab.md @@ -44,13 +44,52 @@ kid and mac_key need to be stored as key/value pairs in json format. ```json { - "keyid_01": "bWFjXzAw", + "keyid_00": "bWFjXzAw", "keyid_01": "bWFjXzAx", "keyid_02": "bWFjXzAy", "keyid_03": "bWFjXzAz" } ``` +## Keyfile verification + +In the keyfile can be checked for consistency by using the `tools/eab_chk.py` utility. + +```bash + py /var/www/acme2certifier/tools/eab_chk.py --help +``` + +```bash +usage: eab_chk.py [-h] -c CONFIGFILE [-d] [-v] [-vv] [-k KEYID | -s] + +eab_chk.py - verify eab keyfile + +options: + -h, --help show this help message and exit + -c CONFIGFILE, --configfile CONFIGFILE + configfile + -d, --debug debug mode + -v, --verbose verbose + -vv, --veryverbose show enrollment profile + -k KEYID, --keyid KEYID + keyid to filter + -s, --summary summary +``` + +Below the example output by using the above mentioned json keyfile + +```bash + py /var/www/acme2certifier/tools/eab_chk.py -c /var/www/acme2certifier/acme_srv/acme_srv.cfg -v +``` + +```bash +Summary: 4 entries in kid_file +keyid_00: bWFjXzAw +keyid_01: bWFjXzAx +keyid_02: bWFjXzAy +keyid_03: bWFjXzAz +``` + ## create a customized eab handler Creating your own eab-handler is pretty straightforward. All you need to do is to create your own handler.py with a "EABhandler" class containing a __mac_key_get__ method to lookup the `mac_key` based on a given `kid`. @@ -90,3 +129,4 @@ class EABhandler(object): self.logger.debug('EABhandler.mac_key_get({})'.format(kid)) mac_key = # code to lookup the mac_key... return mac_key +``` diff --git a/docs/eab_profiling.md b/docs/eab_profiling.md new file mode 100644 index 00000000..02fa0fbe --- /dev/null +++ b/docs/eab_profiling.md @@ -0,0 +1,241 @@ + + +# Enrollment profiling via external account binding + +Starting with version 0.34 acme2certifier supports the configuration of account specific enrollment configuration. Depending on the handler to be used the feature allows the definition of individual authentication credentials, enrollment profiles or certificate authoritzies. + +Currently the following ca-handlers had been modified and do support this feature: + +- [generic ACME](acme_ca.md) +- [EJBCA](ejbca.md) +- [Insta ActiveCMS](asa.md) +- [Insta certifier/NetGuard Certificate manager](certifier.md) +- [Microsoft Certificate Enrollment Web Services](mscertsrv.md) +- [Microsoft Windows Client Certificate Enrollment Protocol (MS-WCCE) via RPC/DCOM](mswcce.md) +- [XCA](xca.md) + +In case you need support for a different ca-handler feel free to raise an [issue](https://github.com/grindsa/acme2certifier/issues/new). + +## Configuration + +This feature requires [external account binding](eab.md) to be enabled and a specific EAB-handler to be configured. + +```cfg +[EABhandler] +eab_handler_file: examples/eab_handler/kid_profile_handler.py +key_file: volume/kid_profiles.json +``` + +The `key_file` allows the specification enrollmenmt parameters per (external) acme-account. Main identifier is the key_id to be used during account registration. Any parameter used in the [CAhandler] configuration section of a handler can be customized. Below an example configuration to be used for [Insta Certifier](certifier.md) with some explanation: + +```json +{ + "keyid_00": { + "hmac": "hmac-key", + "cahandler": { + "profile_id": "profile_1", + "allowed_domainlist": ["*.example.com", "*.example.org", "*.example.fi"], + "ca_name": "non_default_ca", + "api_user": "non_default_api_user", + "api_password": "api_password" + } + }, + "keyid_01": { + "hmac": "hmac-key", + "cahandler": { + "profile_id": ["profile_1", "profile_2", "profile_3"], + "allowed_domainlist": ["*.example.fi", "*.acme"] + } + }, + "keyid_02": { + "hmac": "hmac-key" + } +} +``` + +- Acme-accounts created with keyid "keyid_00" will always use profile-id "profile_1" and specific api-user credentials for enrollment from certificate authority "non_default_ca". Further, the SAN/Common names to be used in enrollment requests are restricted to the domains "example.com", "example.org" and "example.fi". +- Acme-accounts created with keyid "keyid_01" and can specify 3 different profile_ids by using the [header_info feature](header_info.md). Enrollment requests having other profile_ids will be rejected. In case no profile_id get specified the first profile_id in the list ("profile_1") will be used. SAN/CNs to be used are restricted to "example.fi" and ".local" All other enrollment paramters will be taken from acme_srv.cfg +- Acme-accounts created with keyid "keyid_02" do not have any restriction. Enrolment parameters will be taken from the [CAhandler] section in ´acme_srv.cfg` + +Starting from v0.36 acme2certifier does support profile configuration in yaml format. Below a configuration example providing the same level of functionality than the above json configuration + +```yaml +--- +{ +--- +keyid_00: + hmac: "hmac-key" + cahandler: + profile_id: "profile_1" + allowed_domainlist: + - "*.example.com" + - "*.example.org" + - "*.example.fi" + ca_name: "non_default_ca" + api_user: "non_default_api_user" + api_password: "api_password" +keyid_01: + hmac: "hmac-key" + cahandler: + profile_id: + - "profile_1" + - "profile_2" + - "profile_3" + allowed_domainlist: + - "*.example.fi" + - "*.acme" +keyid_02: + hmac: "hmac-key" +``` + +## subject profiling + +Starting from v0.36 the eab-profiling feature can be used to check and white-list the certificate subject DN. + +Attribute names must follow [RFC3039](https://www.rfc-editor.org/rfc/rfc3039.html#section-3.1.2); every RDN can be white-listed as: + +- string - attribute in CSR DN must match this value +- list - attribute in CSR DN must match one of the list entries +- "*" - any value matches as long as the attribute is present + +The below example configuration will only allow CSR matching the following ciriterias: + +- serial number can be of any value but must be included +- organizationalUnitName must be either "acme1" or "acme2" +- organizationName must be "acme corp" +- countryName must be "AC" +- additional CSR DN such as localityName or stateOrProvinceName are not allowed + +```json +... +{ + "keyid_00": { + "hmac": "hmac-key", + "cahandler": { + "template_name": ["template", "acme"], + "allowed_domainlist": ["www.example.com", "www.example.org", "*.acme"], + "subject": { + "serialNumber": "*", + "organizationName": "acme corp", + "organizationalUnitName": ["acme1", "acme2"], + "countryName": "AC" + } + } + } +} +... +``` + +## Profile verification + +In the keyfile can be checked for consistency by using the `tools/eab_chk.py` utility. + +```bash + py /var/www/acme2certifier/tools/eab_chk.py --help +``` + +```bash +usage: eab_chk.py [-h] -c CONFIGFILE [-d] [-v] [-vv] [-k KEYID | -s] + +eab_chk.py - verify eab keyfile + +options: + -h, --help show this help message and exit + -c CONFIGFILE, --configfile CONFIGFILE + configfile + -d, --debug debug mode + -v, --verbose verbose + -vv, --veryverbose show enrollment profile + -k KEYID, --keyid KEYID + keyid to filter + -s, --summary summary +``` + +Below the example output by using the above mentioned keyfile + +- show a summary only + +```bash +py /var/www/acme2certifier/tools/eab_chk.py -c /var/www/acme2certifier/acme_srv/acme_srv.cfg +``` + +```bash +Summary: 4 entries in kid_file +``` + +- show keyids and hmac + +```bash + py /var/www/acme2certifier/tools/eab_chk.py -c /var/www/acme2certifier/acme_srv/acme_srv.cfg -v +``` + +```bash +Summary: 4 entries in kid_file +keyid_00: V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw +keyid_01: YW5vdXRoZXJfdmVyeV9sb25nX2htYWNfZm9yX2tleWlkXzAxX3doaWNoIHdpbGxfYmUgdXNlZF9kdXJpbmcgcmVncmVzc2lvbg +keyid_02: dGhpc19pc19hX3ZlcnlfbG9uZ19obWFjX3RvX21ha2Vfc3VyZV90aGF0X2l0c19tb3JlX3RoYW5fMjU2X2JpdHM +keyid_03: YW5kX2ZpbmFsbHlfdGhlX2xhc3RfaG1hY19rZXlfd2hpY2hfaXNfbG9uZ2VyX3RoYW5fMjU2X2JpdHNfYW5kX3Nob3VsZF93b3Jr +``` + +- show profiles + +```bash +py /var/www/acme2certifier/tools/eab_chk.py -c /var/www/acme2certifier/acme_srv/acme_srv.cfg -vv +``` + +```bash +Summary: 4 entries in kid_file +keyid_00: + cahandler: + allowed_domainlist: + - www.example.com + - www.example.org + - '*.example.fi' + - '*.bar.local' + profile_id: + - '101' + - '102' + profile_name: + - ACME_2 + - ACME + template_name: + - TLS_Server + - acme + hmac: V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw +keyid_01: + cahandler: + allowed_domainlist: + - '*.example.fi' + - '*.acme' + - '*.bar.local' + profile_id: '101' + profile_name: ACME_2 + template_name: TLS_Server + hmac: YW5vdXRoZXJfdmVyeV9sb25nX2htYWNfZm9yX2tleWlkXzAxX3doaWNoIHdpbGxfYmUgdXNlZF9kdXJpbmcgcmVncmVzc2lvbg +keyid_02: + cahandler: + ca_name: RSA Root CA + hmac: dGhpc19pc19hX3ZlcnlfbG9uZ19obWFjX3RvX21ha2Vfc3VyZV90aGF0X2l0c19tb3JlX3RoYW5fMjU2X2JpdHM +keyid_03: + hmac: YW5kX2ZpbmFsbHlfdGhlX2xhc3RfaG1hY19rZXlfd2hpY2hfaXNfbG9uZ2VyX3RoYW5fMjU2X2JpdHNfYW5kX3Nob3VsZF93b3Jr +``` + +- filter output to a single keyid + +```bash +py /var/www/acme2certifier/tools/eab_chk.py -c /var/www/acme2certifier/acme_srv/acme_srv.cfg -k keyid_01 +``` + +```bash +Summary: 1 entries in kid_file +keyid_01: + cahandler: + allowed_domainlist: + - '*.example.fi' + - '*.acme' + - '*.bar.local' + profile_id: '101' + profile_name: ACME_2 + template_name: TLS_Server + hmac: YW5vdXRoZXJfdmVyeV9sb25nX2htYWNfZm9yX2tleWlkXzAxX3doaWNoIHdpbGxfYmUgdXNlZF9kdXJpbmcgcmVncmVzc2lvbg +``` diff --git a/docs/ejbca.md b/docs/ejbca.md index 981e3153..047eaf8d 100644 --- a/docs/ejbca.md +++ b/docs/ejbca.md @@ -8,11 +8,11 @@ This handler can be used to enroll certificates from the [Open Source version of - [EJBCA](https://www.ejbca.org) needs to have the RESTv1-service enabled - you'll need: - - a [client certificate and key in p12](https://doc.primekey.com/ejbca/ejbca-operations/ejbca-ca-concept-guide/authentication-methods) format to authenticate towards the rest-service + - a [client certificate and key in p12](https://docs.keyfactor.com/ejbca/latest/authentication-methods) format to authenticate towards the rest-service - the name of the CA issuing the certificates from EJBA admin UI - a username and enrolment code - - a [certificate profile name](https://doc.primekey.com/ejbca/ejbca-operations/ejbca-ca-concept-guide/certificate-profiles-overview) - - an [end-entity profile name](https://download.primekey.com/docs/EJBCA-Enterprise/6_14_1/End_Entity_Profiles.html) + - a [certificate profile name](https://docs.keyfactor.com/ejbca/latest/certificate-profiles-overview) + - an [end-entity profile name](https://docs.keyfactor.com/ejbca/latest/end-entity-profiles-overview) ## Configuration @@ -30,6 +30,7 @@ username: enrollment_code: ca_name: request_timeout: +eab_profiling: ``` - api_host - URL of the EJBCA-Rest service @@ -45,6 +46,7 @@ request_timeout: - ee_profile_name - name of the end entity profile - ca_name - name of the CA used to enroll certificates - request_timeout - optional - requests timeout in seconds for requests (default: 5s) +- eab_profiling - optional - [activate eab profiling](eab_profiling.md) (default: False) You can test the connection by running the following curl command against your EJBCA server. @@ -63,3 +65,71 @@ The response to this call will show a dictionary containing status und version n ``` Use your favorite acme client for certificate enrollment. A list of clients used in our regression can be found in the [disclaimer section of our README file](../README.md) + +## Passing a profile_id from client to server + +The handler makes use of the [header_info_list feature](header_info.md) allowing an acme-client to specify a certificate profile to be used during certificate enrollment. This feature is disabled by default and must be activate in `acme_srv.cfg` as shown below + +```config +[Order] +... +header_info_list: ["HTTP_USER_AGENT"] +``` + +The acme-client can then specify the profileID as part of its user-agent string. + +Example for acme.sh: + +```bash +docker exec -i acme-sh acme.sh --server http:// --issue -d --standalone --useragent cert_profile_name=acme_clt --debug 3 --output-insecure +``` + +Example for lego: + +```bash +docker run -i -v $PWD/lego:/.lego/ --rm --name lego goacme/lego -s http:// -a --email "lego@example.com" --user-agent cert_profile_name=acme_clt -d --http run +``` + +# eab profiling + +This handler can use the [eab profiling feture](eab_profiling.md) to allow individual enrollment configuration per acme-account as well as restriction of CN and SANs to be submitted within the CSR. The feature is disabled by default and must be activated in `acme_srv.cfg` + +```cfg +[EABhandler] +eab_handler_file: examples/eab_handler/kid_profile_handler.py +key_file: + +[CAhandler] +eab_profiling: True +``` + +below an example key-file used during regression testing: + +```json +{ + "keyid_00": { + "hmac": "V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw", + "cahandler": { + "cert_profile_name": ["acmeca2", "acmeca1"], + "allowed_domainlist": ["www.example.com", "www.example.org", "*.acme"] + } + }, + "keyid_01": { + "hmac": "YW5vdXRoZXJfdmVyeV9sb25nX2htYWNfZm9yX2tleWlkXzAxX3doaWNoIHdpbGxfYmUgdXNlZF9kdXJpbmcgcmVncmVzc2lvbg", + "cahandler": { + "cert_profile_name": "acmeca2", + "allowed_domainlist": ["www.example.com", "www.example.org", "*.acme"], + "ca_name": "acmeca" + } + }, + "keyid_02": { + "hmac": "dGhpc19pc19hX3ZlcnlfbG9uZ19obWFjX3RvX21ha2Vfc3VyZV90aGF0X2l0c19tb3JlX3RoYW5fMjU2X2JpdHM", + "cahandler": { + "allowed_domainlist": ["www.example.com", "www.example.org"] + } + }, + "keyid_03": { + "hmac": "YW5kX2ZpbmFsbHlfdGhlX2xhc3RfaG1hY19rZXlfd2hpY2hfaXNfbG9uZ2VyX3RoYW5fMjU2X2JpdHNfYW5kX3Nob3VsZF93b3Jr" + } +} +``` diff --git a/docs/entrust.md b/docs/entrust.md new file mode 100644 index 00000000..9fbc2837 --- /dev/null +++ b/docs/entrust.md @@ -0,0 +1,114 @@ + + +# Connecting to Entrust ECS Enterprise + +This handler can be used to enroll certificates from Entrust ECS Enterprise API. + +## Prerequisites + +- you'll need: + - Username and Password for HTTP-BASIC authentication + - if configured - a client certificate for mutual TLS authentication towards the Entrust RESt API + - an pre-validated Organization name + +## Configuration + +- modify the server configuration (`acme_srv.cfg`) and add the first thre of the below mentioned parameters + +```confag +[CAhandler] +handler_file: examples/ca_handler/entrust_ca_handler.py +username: +password: +certtype: +organization_name: + +client_cert: +cert_passphrase: +cert_validity_days: +allowed_domainlist: +request_timeout: +eab_profiling: +``` + +- username - required - username access the API +- password - required - password to access the PI +- organization_name - required - Organization name as specified in DigiCert CertCentral +- client_cert - optional - client certificate to access the API (to be stored in either pem or pkcs#12 format) +- client_key - optional - client private key to access the API (must be stored in pem format) +- client_passphrase - passphrase to access the client_cert (if stored in pkcs#2 format) +- cert_type - optional - certificate type to be isused. (default: STANDARD_SSL) +- cert_validity_days - certificate validity in days (default: 365) +- allowed_domainlist: list of domain-names allowed for enrollment in json format (example: ["bar.local$, bar.foo.local]) +- request_timeout - optional - requests timeout in seconds for requests (default: 5s) +- eab_profiling - optional - [activate eab profiling](eab_profiling.md) (default: False) + +Use your favorite acme client for certificate enrollment. A list of clients used in our regression can be found in the [disclaimer section of our README file](../README.md) + +## Passing a cert_type from client to server + +The handler makes use of the [header_info_list feature](header_info.md) allowing an acme-client to specify a certificate type to be used during certificate enrollment. This feature is disabled by default and must be activate in `acme_srv.cfg` as shown below + +```config +[Order] +... +header_info_list: ["HTTP_USER_AGENT"] +``` + +The acme-client can then specify the cert_type as part of its user-agent string. + +Example for acme.sh: + +```bash +docker exec -i acme-sh acme.sh --server http:// --issue -d --standalone --useragent cert_type=ADVANTAGE_SSL --debug 3 --output-insecure +``` + +Example for lego: + +```bash +docker run -i -v $PWD/lego:/.lego/ --rm --name lego goacme/lego -s http:// -a --email "lego@example.com" --user-agent cert_type=ADVANTAGE_SSL -d --http run +``` + +# eab profiling + +This handler can use the [eab profiling feture](eab_profiling.md) to allow individual enrollment configuration per acme-account as well as restriction of CN and SANs to be submitted within the CSR. The feature is disabled by default and must be activated in `acme_srv.cfg` + +```cfg +[EABhandler] +eab_handler_file: examples/eab_handler/kid_profile_handler.py +key_file: + +[CAhandler] +eab_profiling: True +``` + +below an example key-file used during regression testing: + +```json +{ + "keyid_00": { + "hmac": "V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw", + "cahandler": { + "cert_type": ["ADVANTAGE_SSL", "STANDARD_PLUS_SSL", "WILDCARD_SSL"], + "allowed_domainlist": ["www.example.com", "www.example.org", "*.acme"], + "organization_name": "acme2certifier" + } + }, + "keyid_01": { + "hmac": "YW5vdXRoZXJfdmVyeV9sb25nX2htYWNfZm9yX2tleWlkXzAxX3doaWNoIHdpbGxfYmUgdXNlZF9kdXJpbmcgcmVncmVzc2lvbg", + "cahandler": { + "allowed_domainlist": ["www.example.com", "www.example.org", "*.acme"], + "cert_type": "ADVANTAGE_SSL" + } + }, + "keyid_02": { + "hmac": "dGhpc19pc19hX3ZlcnlfbG9uZ19obWFjX3RvX21ha2Vfc3VyZV90aGF0X2l0c19tb3JlX3RoYW5fMjU2X2JpdHM", + "cahandler": { + "allowed_domainlist": ["www.example.com", "www.example.org"] + } + }, + "keyid_03": { + "hmac": "YW5kX2ZpbmFsbHlfdGhlX2xhc3RfaG1hY19rZXlfd2hpY2hfaXNfbG9uZ2VyX3RoYW5fMjU2X2JpdHNfYW5kX3Nob3VsZF93b3Jr" + } +} +``` diff --git a/docs/external_database_support.md b/docs/external_database_support.md new file mode 100644 index 00000000..890528bf --- /dev/null +++ b/docs/external_database_support.md @@ -0,0 +1,220 @@ + + +# Support for External Databases + +Acme2certifier supports external databases by using the [Django Python framework](https://www.djangoproject.com/). The default SQLite backend is not designed to handle concurrent write access, which can easily occur in an environment with a high transaction frequency. + +All [databases supported by Django](https://docs.djangoproject.com/en/5.0/ref/databases/) should work in theory; MariaDB and PostgreSQL will be tested during [release regression](https://github.com/grindsa/acme2certifier/blob/master/.github/workflows/django_tests..yml). + +This guide is written for **Ubuntu 22.04**; however, adapting it to other Linux distributions should not be difficult. + +## Preparation + +### When Using MariaDB + +The steps below assume that MariaDB is already installed and running on your system. + +- Open the MySQL command-line client: + +```bash +sudo mysql -u root +``` + +- create the acme2certifier database and database user + +```SQL +CREATE DATABASE acme2certifier CHARACTER SET UTF8; +GRANT ALL PRIVILEGES ON acme2certifier.* TO 'acme2certifier'@'%' IDENTIFIED BY 'a2cpasswd'; +FLUSH PRIVILEGES; +``` + +- Install missing Python modules: + +```bash +apt-get install python3-django python3-mysqldb python3-pymysql +``` + +### When using PostgreSQL + +It is assumed that PostgreSQL is already installed and running. + +- Open the PostgreSQL command-line client: + +```bash +sudo psql -U postgres +``` + +- Create the acme2certifier database and database user: + +```SQL +CREATE DATABASE acme2certifier; +CREATE USER acme2certifier WITH PASSWORD 'a2cpasswd'; +ALTER ROLE acme2certifier SET client_encoding TO 'utf8'; +ALTER ROLE acme2certifier SET default_transaction_isolation TO 'read committed'; +ALTER ROLE acme2certifier SET timezone TO 'UTC'; +GRANT ALL PRIVILEGES ON DATABASE acme2certifier TO acme2certifier; +GRANT ALL ON schema public TO acme2certifier; +GRANT USAGE ON schema public TO acme2certifier; +GRANT postgres TO acme2certifier; +``` + +- Install missing python modules + +```bash +sudo apt-get install python3-django python3-psycopg2 +``` + +## Install and Configure acme2certifier + +- Downlaod the [latest deb package](https://github.com/grindsa/acme2certifier/releases) +- Install the package locally + +```bash +sudo apt-get install -y ./acme2certifier_-1_all.deb +``` + +- Copy and activete Apache2 configuration file + +```bash +sudo cp /var/www/acme2certifier/examples/apache2/apache_django.conf /etc/apache2/sites-available/acme2certifier.conf +sudo a2ensite acme2certifier +``` + +- Copy and activate the Apache2 SSL configuration file (optional): + +```bash +sudo cp /var/www/acme2certifier/examples/apache2/apache_django_ssl.conf /etc/apache2/sites-available/acme2certifier_ssl.conf +sudo a2ensite acme2certifier_ssl +``` + +- Disable the default sites: + +```bash +sudo a2dissite 000-default.conf +sudo a2dissite default-ssl +``` + +- Copy the Django handler and the Django directory structure: + +```bash +sudo cp /var/www/acme2certifier/examples/db_handler/django_handler.py /var/www/acme2certifier/acme_srv/db_handler.py +sudo cp -R /var/www/acme2certifier/examples/django/* /var/www/acme2certifier/ +``` + +- Enable and start the Apache2 service: + +```bash +sudo systemctl enable apache2.service +sudo systemctl start apache2.service +``` + +- Generate a new Django secret key and note it down: + +```bash +python3 /var/www/acme2certifier/tools/django_secret_keygen.py ++%*lei)yj9b841=2d5(u)a&7*uwi@l99$(*&ong@g*p1%q)g$e +``` + +- Modify `/var/www/acme2certifier/acme2certifier/settings.py` and: + - Insert the secret-key created in the previous step + - Update the 'ALLOWED_HOSTS'- section with both ip-address and fqdn of the node + - Configure a connection to mariadb as shown below + +```python +SECRET_KEY = '+%*lei)yj9b841=2d5(u)a&7*uwi@l99$(*&ong@g*p1%q)g$e' +ALLOWED_HOSTS = ['192.168.14.132', 'ub2204-c1.bar.local'] +(...) +``` + +### Connecting to MariaDB + +- Modify `/var/www/acme2certifier/acme2certifier/settings.py` and configure your database connection as below: + +```python +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.mysql', + 'NAME': 'acme2certifier', + 'USER': 'acme2certifier', + 'PASSWORD': 'a2cpasswd', + 'HOST': "ub2204-c1", + 'OPTIONS': {"init_command": "SET sql_mode='STRICT_TRANS_TABLES', innodb_strict_mode=1","charset": "utf8mb4", "use_unicode": True}, + }, + +} +``` + +### Connecting to PostGres + +- Modify `/var/www/acme2certifier/acme2certifier/settings.py` and configure your databdatabase connection as below: + +```python +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.postgresql_psycopg2', + 'NAME': 'acme2certifier', + 'USER': 'acme2certifier', + 'PASSWORD': 'a2cpasswd', + 'HOST': 'postgresdbsrv', + 'PORT': '', + } +} +``` + +## Finilize acme2cerifier configuration + +- Create a Django migration set, apply the migrations, and load fixtures: the [configuration file](acme_srv.md) `/var/www/acme2certifier/volume/acme_srv.cfg`according to your needs. If your CA handler needs runtime information (configuration files, keys, certificate bundles, etc.) to be shared between the nodes, ensure they are loaded from `/var/www/acme2certifier/volume`. Below an example for the `[CAhandler]` section of the openssl-handler I use during my tests: + +```cfg +[CAhandler] +handler_file: /var/www/acme2certifier/examples/ca_handler/openssl_ca_handler.py +ca_cert_chain_list: ["/var/www/acme2certifier/volume/root-ca-cert.pem"] +issuing_ca_key: /var/www/acme2certifier/volume/ca/sub-ca-key.pk8 +issuing_ca_key_passphrase_variable: OPENSSL_PASSPHRASE +issuing_ca_cert: /var/www/acme2certifier/volume/ca/sub-ca-cert.pem +issuing_ca_crl: /var/www/acme2certifier/volume/ca/sub-ca-crl.pem +cert_validity_days: 30 +cert_validity_adjust: True +cert_save_path: /var/www/acme2certifier/volume/ca/certs +save_cert_as_hex: True +cn_enforce: True +``` + +- Create a Django migration set, apply the migrations, and load fixtures: + +```bash +cd /var/www/acme2certifier +sudo python3 manage.py makemigrations +sudo python3 manage.py migrate +sudo python3 manage.py loaddata acme_srv/fixture/status.yaml +``` + +- Run the Django update script: + +```bash +sudo python3 /var/www/acme2certifier/tools/django_update.py +``` + +- Restart the apache2 service + +```bash +sudo systemctl restart apache2.service +``` + +- Test the server by accessing the directory ressource + +```bash +curl http://ub2204-c1.bar.local/directory +``` + +```bash +{"newAccount": "http://ub2204-c1.bar.local/acme_srv/newaccount", "fa8b347d3849421ebc4b234205418805": "https://community.letsencrypt.org/t/adding-random-entries-to-the-directory/33417", "keyChange": "http://ub2204-c1.bar.local/acme_srv/key-change", "newNonce": "http://ub2204-c1.bar.local/acme_srv/newnonce", "meta": {"home": "https://github.com/grindsa/acme2certifier", "author": "grindsa "}, "newOrder": "http://ub2204-c1.bar.local/acme_srv/neworders", "revokeCert": "http://ub2204-c1.bar.local/acme_srv/revokecert"} +``` + +## Test enrollment + +- Try to enroll certificates by using your favorite acme-client. I am using [lego](https://github.com/go-acme/lego). + +```bash + docker run -i -p 80:80 -v $PWD/lego:/.lego/ --rm --name lego --network acme goacme/lego -s http://ub2204-c1.bar.local -a --email "lego@example.com" -d lego01.bar.local --http run +``` diff --git a/docs/install_apache2_wsgi.md b/docs/install_apache2_wsgi.md index 30182d00..8fbf72cb 100644 --- a/docs/install_apache2_wsgi.md +++ b/docs/install_apache2_wsgi.md @@ -5,12 +5,12 @@ A [readymade shell script](../examples/install_scripts/a2c-ubuntu22-apache2.sh) performing the below tasks will can be found in `examples/install_scripts` directory. 1. Install apache2 and the corresponding wsgi module -$ sudo apt-get install -y apache2 libapache2-mod-wsgi-py3 python3-pip apache2-data +$ sudo apt-get install -y apache2 libapache2-mod-wsgi-py3 python3-pip apache2-data curl krb5-user libgssapi-krb5-2 libkrb5-3 python3-gssapi 2. check if the wsgi module is activated in your apache configuration ```bash -$ sudo apache2ctl -M | grep -i wsgi +sudo apache2ctl -M | grep -i wsgi  wsgi_module (shared) ``` @@ -21,24 +21,28 @@ if the wsgi_module is not enabled please check the internet how to do... 4. install the missing modules via pip ```bash -$ sudo pip3 install -r requirements.txt +sudo pip3 install -r requirements.txt ``` 5. copy the file `examples/apache2/apache_wsgi.conf` to `/etc/apache2/sites-available/acme2certifier.conf` and modify it according to you needs. -6. in case you would like to activate TLS copy the file `examples/acme_wsgi_ssl.conf` to `/etc/apache2/sites-available/acme2certifier.conf` and modify it according to your needs. Do not forget to place the key-bundle. This - -file must contain the following certificate data in pem format: +6. in case you would like to activate TLS copy the file `examples/acme_wsgi_ssl.conf` to `/etc/apache2/sites-available/acme2certifier.conf` and modify it according to your needs. Do not forget to place the key-bundle. This file must contain the following certificate data in pem format: - the private key - the end-entity certificate - intermediate CA certificates, sorted from leaf to root (root CA certificate should not be included for security reasons) +Further, the ssl module needs to be activated + +```bash +sudo a2enmod ssl +``` + 7. activate the virtual server(s) ```bash -$ sudo a2ensite acme2certifier.conf -$ sudo a2ensite acme2certifier_ssl.conf +sudo a2ensite acme2certifier.conf +sudo a2ensite acme2certifier_ssl.conf ``` 8. create a directory `/var/www/acme2certifier` @@ -46,19 +50,19 @@ $ sudo a2ensite acme2certifier_ssl.conf 10. copy the directories `examples/ca_hander/`, `examples/eab_handler/`, `examples/hooks/` and `tools` to `/var/www/acme2certifier/` ```bash -$ sudo mkdir /var/www/acme2certifier/examples -$ sudo cp -R examples/ca_handler/ /var/www/acme2certifier/examples/ca_handler -$ sudo cp -R examples/eab_handler/ /var/www/acme2certifier/examples/eab_handler -$ sudo cp -R examples/hooks/ /var/www/acme2certifier/examples/hooks -$ sudo cp -R examples/acme_srv.cfg /var/www/acme2certifier/examples/ -$ sudo cp -R tools/ /var/www/acme2certifier/tools +sudo mkdir /var/www/acme2certifier/examples +sudo cp -R examples/ca_handler/ /var/www/acme2certifier/examples/ca_handler +sudo cp -R examples/eab_handler/ /var/www/acme2certifier/examples/eab_handler +sudo cp -R examples/hooks/ /var/www/acme2certifier/examples/hooks +sudo cp -R examples/acme_srv.cfg /var/www/acme2certifier/examples/ +sudo cp -R tools/ /var/www/acme2certifier/tools ``` 11. create a directory `/var/www/acme2certifier/acme_srv` 12. copy the content of the `acme_srv` directory to `/var/www/acme2certifier/acme_srv` ```bash -$ sudo cp -R acme_srv/ /var/www/acme2certifier/acme_srv +sudo cp -R acme_srv/ /var/www/acme2certifier/acme_srv ``` 13. create a configuration file `acme_srv.cfg` in /var/www/acme2certfier/acme or use the example stored in the examples directory @@ -68,26 +72,26 @@ $ sudo cp -R acme_srv/ /var/www/acme2certifier/acme_srv 17. activate the wsgi database handler ```bash -$ sudo cp /var/www/acme2certifier/examples/db_handler/wsgi_handler.py /var/www/acme_srv/acme2certfier/db_handler.py +sudo cp /var/www/acme2certifier/examples/db_handler/wsgi_handler.py /var/www/acme_srv/acme2certfier/db_handler.py ``` 18. ensure that the all files and directories under /var/www/acme2certifier are owned by the user running the webserver (www-data is just an example!) ```bash -$ sudo chown -R www-data.www-data /var/www/acme2certifier/ +sudo chown -R www-data.www-data /var/www/acme2certifier/ ``` 19. set correct permissions to acme subdirectory ```bash -$ sudo chmod a+x /var/www/acme2certifier/acme_srv +sudo chmod a+x /var/www/acme2certifier/acme_srv ``` 20. delete default apache configuration file and restart the apache2 service ```bash -$ sudo rm /etc/apache2/sites-enabled/000-default.conf -$ sudo systemctl reload apache2 +sudo rm /etc/apache2/sites-enabled/000-default.conf +sudo systemctl reload apache2 ``` 21. Check access to the directory resource to verify that everything works so far diff --git a/docs/install_deb.md b/docs/install_deb.md index 271d8d70..ec8a2e28 100644 --- a/docs/install_deb.md +++ b/docs/install_deb.md @@ -10,22 +10,22 @@ The debian package is generic and supports running acme2certifier with either ap 2. Install acme2certifier and apache2 packages ```bash -$ sudo apt-get install -y apache2 apache2-data libapache2-mod-wsgi-py3 -$ sudo apt-get install -y ../acme2certifier_-1_all.deb +sudo apt-get install -y apache2 apache2-data libapache2-mod-wsgi-py3 +sudo apt-get install -y ../acme2certifier_-1_all.deb ``` 3. Copy and activete apache2 configuration file ```bash -$ sudo cp /var/www/acme2certifier/examples/apache2/apache_wsgi.conf /etc/apache2/sites-available/acme2certifier.conf -$ sudo a2ensite acme2certifier +sudo cp /var/www/acme2certifier/examples/apache2/apache_wsgi.conf /etc/apache2/sites-available/acme2certifier.conf +sudo a2ensite acme2certifier ``` 4. Copy and activate apache2 ssl configuration file (optional) ```bash -$ sudo cp /var/www/acme2certifier/examples/apache2/apache_wsgi_ssl.conf /etc/apache2/sites-available/acme2certifier_ssl.conf -$ sudo a2ensite acme2certifier_ssl +sudo cp /var/www/acme2certifier/examples/apache2/apache_wsgi_ssl.conf /etc/apache2/sites-available/acme2certifier_ssl.conf +sudo a2ensite acme2certifier_ssl ``` 5. Create a configuration file `acme_srv.cfg` in `/var/www/acme2certifier/acme_srv/` or use the example stored in the examples directory @@ -35,14 +35,14 @@ $ sudo a2ensite acme2certifier_ssl 8. Enable and start the apache2 service ```bash -$ systemctl enable apache2.service -$ systemctl start apache2.service +sudo systemctl enable apache2.service +sudo systemctl start apache2.service ``` 9. Test the server by accessing the directory resource ```bash -$ curl http:///directory +curl http:///directory {"newAccount": "http://127.0.0.1:8000/acme_srv/newaccount", "fa8b347d3849421ebc4b234205418805": "https://community.letsencrypt.org/t/adding-random-entries-to-the-directory/33417", "keyChange": "http://127.0.0.1:8000/acme_srv/key-change", "newNonce": "http://127.0.0.1:8000/acme_srv/newnonce", "meta": {"home": "https://github.com/grindsa/acme2certifier", "author": "grindsa "}, "newOrder": "http://127.0.0.1:8000/acme_srv/neworders", "revokeCert": "http://127.0.0.1:8000/acme_srv/revokecert"} ``` @@ -54,32 +54,32 @@ $ curl http:///directory 2. Install acme2certifier and nginx packages ```bash -$ sudo apt-get install -y python3-pip nginx uwsgi uwsgi-plugin-python3 -$ sudo apt-get install -y ../acme2certifier_-1_all.deb +sudo apt-get install -y python3-pip nginx uwsgi uwsgi-plugin-python3 +sudo apt-get install -y ../acme2certifier_-1_all.deb ``` 3. Adapt the nginx configuration file to Ubuntu 22.04 and activate the configuration ```bash -$ sed -i "s/run\/uwsgi\/acme.sock/var\/www\/acme2certifier\/acme.sock/g" examples/nginx/nginx_acme_srv.conf -$ sudo cp examples/nginx/nginx_acme_srv.conf /etc/nginx/sites-available/acme_srv.conf -$ sudo rm /etc/nginx/sites-enabled/default -$ sudo ln -s /etc/nginx/sites-available/acme_srv.conf /etc/nginx/sites-enabled/acme_srv.conf +sudo sed -i "s/run\/uwsgi\/acme.sock/var\/www\/acme2certifier\/acme.sock/g" examples/nginx/nginx_acme_srv.conf +sudo cp examples/nginx/nginx_acme_srv.conf /etc/nginx/sites-available/acme_srv.conf +sudo rm /etc/nginx/sites-enabled/default +sudo ln -s /etc/nginx/sites-available/acme_srv.conf /etc/nginx/sites-enabled/acme_srv.conf ``` 4. Adapt and copy uwsgi configuration files ```bash -$ sed -i "s/\/run\/uwsgi\/acme.sock/acme.sock/g" examples/nginx/acme2certifier.ini -$ sed -i "s/nginx/www-data/g" examples/nginx/acme2certifier.ini -$ echo "plugins=python3" >> examples/nginx/acme2certifier.ini -$ sudo cp examples/nginx/acme2certifier.ini /var/www/acme2certifier +sudo sed -i "s/\/run\/uwsgi\/acme.sock/acme.sock/g" examples/nginx/acme2certifier.ini +sudo sed -i "s/nginx/www-data/g" examples/nginx/acme2certifier.ini +sudo echo "plugins=python3" >> examples/nginx/acme2certifier.ini +sudo sudo cp examples/nginx/acme2certifier.ini /var/www/acme2certifier ``` 5. Create acme2certifier systemd service file ```bash -cat < acme2certifier.service +sudo cat < acme2certifier.service [Unit] Description=uWSGI instance to serve acme2certifier After=network.target @@ -99,27 +99,27 @@ EOT 6. Copy systemd service file ```bash -$ sudo mv acme2certifier.service /etc/systemd/system/acme2certifier.service +sudo mv acme2certifier.service /etc/systemd/system/acme2certifier.service ``` 7. Enable and start acme2certifier service ```bash -$ sudo systemctl start acme2certifier -$ sudo systemctl enable acme2certifier +sudo systemctl start acme2certifier +sudo systemctl enable acme2certifier ``` 8. Enable and start nginx ```bash -$ sudo systemctl start nginx -$ sudo systemctl enable nginx +sudo systemctl start nginx +sudo systemctl enable nginx ``` 9. Test the server by accessing the directory resource ```bash -$ curl http:///directory +curl http:///directory {"newAccount": "http://127.0.0.1:8000/acme_srv/newaccount", "fa8b347d3849421ebc4b234205418805": "https://community.letsencrypt.org/t/adding-random-entries-to-the-directory/33417", "keyChange": "http://127.0.0.1:8000/acme_srv/key-change", "newNonce": "http://127.0.0.1:8000/acme_srv/newnonce", "meta": {"home": "https://github.com/grindsa/acme2certifier", "author": "grindsa "}, "newOrder": "http://127.0.0.1:8000/acme_srv/neworders", "revokeCert": "http://127.0.0.1:8000/acme_srv/revokecert"} ``` diff --git a/docs/install_nginx_wsgi.md b/docs/install_nginx_wsgi.md index 6c52c6a6..4391cb7e 100644 --- a/docs/install_nginx_wsgi.md +++ b/docs/install_nginx_wsgi.md @@ -9,30 +9,30 @@ A [readymade shell script](../examples/install_scripts/a2c-centos9-nginx.sh) per 1. download the archive and unpack it into a temporary directory. ```bash -$ cd /tmp -$ curl https://codeload.github.com/grindsa/acme2certifier/tar.gz/refs/heads/master -o a2c-master.tgz -$ tar xvfz a2c-master.tgz -$ cd /tmp/acme2certifier-master +cd /tmp +curl https://codeload.github.com/grindsa/acme2certifier/tar.gz/refs/heads/master -o a2c-master.tgz +tar xvfz a2c-master.tgz +cd /tmp/acme2certifier-master ``` 2. Install missing packages ```bash -$ sudo yum install -y epel-release -$ sudo yum update -y -$ sudo yum install -y python-pip nginx python3-uwsgidecorators.x86_64 tar uwsgi-plugin-python3 policycoreutils-python-utils +sudo yum install -y epel-release +sudo yum update -y +sudo yum install -y python-pip nginx python3-uwsgidecorators.x86_64 tar uwsgi-plugin-python3 policycoreutils-python-utils ``` 3. Setup your project directory ```bash -$ mkdir /opt/acme2certifier +sudo mkdir /opt/acme2certifier ``` 4. Install the missing python modules ```bash -$ pip install -r /opt/acme2certifier/requirements.txt +sudo pip install -r /opt/acme2certifier/requirements.txt ``` 5. create a configuration file `acme_srv.cfg` in `/opt/acme2certifier/acme_srv/` or use the example stored in the examples directory @@ -42,91 +42,91 @@ $ pip install -r /opt/acme2certifier/requirements.txt 9. activate the wsgi database handler ```bash -$ cp /opt/acme2certifier/examples/db_handler/wsgi_handler.py /opt/acme2certifier/acme_srv/db_handler.py +sudo cp /opt/acme2certifier/examples/db_handler/wsgi_handler.py /opt/acme2certifier/acme_srv/db_handler.py ``` 10. copy the application file "acme2certifer_wsgi.py" from examples directory ```bash -$ cp /opt/acme2certifier/examples/acme2certifier_wsgi.py /opt/acme2certifier/ +sudo cp /opt/acme2certifier/examples/acme2certifier_wsgi.py /opt/acme2certifier/ ``` 11. set the correct permissions to the acme_srv-subdirectory ```bash -$ chmod a+x /opt/acme2certifier/acme_srv +sudo chmod a+x /opt/acme2certifier/acme_srv ``` 12. set the ownership of the acme_srv subdirectory to the user running nginx ```bash -$ chown -R nginx /opt/acme2certifier/acme_srv +sudo chown -R nginx /opt/acme2certifier/acme_srv ``` 13. Test acme2certifier by starting the application ```bash cd /opt/acme2certifier -$ uwsgi --http-socket :8000 --plugin python3 --wsgi-file acme2certifier_wsgi.py +sudo uwsgi --http-socket :8000 --plugin python3 --wsgi-file acme2certifier_wsgi.py ``` 14. Check access to directory resource in a parallel session to verify that everything works so far ```bash -$ curl http://127.0.0.1:8000/directory +curl http://127.0.0.1:8000/directory {"newAccount": "http://127.0.0.1:8000/acme_srv/newaccount", "fa8b347d3849421ebc4b234205418805": "https://community.letsencrypt.org/t/adding-random-entries-to-the-directory/33417", "keyChange": "http://127.0.0.1:8000/acme_srv/key-change", "newNonce": "http://127.0.0.1:8000/acme_srv/newnonce", "meta": {"home": "https://github.com/grindsa/acme2certifier", "author": "grindsa "}, "newOrder": "http://127.0.0.1:8000/acme_srv/neworders", "revokeCert": "http://127.0.0.1:8000/acme_srv/revokecert"}$ ``` 15. create an uWSGI config file or use the one stored in examples/nginx directory ```bash -$ cp examples/nginx/acme2certifier.ini /opt/acme2certifier +sudo cp examples/nginx/acme2certifier.ini /opt/acme2certifier ``` 16. activate python3 module in uWSGI config file ```bash -$ echo "plugins = python3" >> examples/nginx/acme2certifier.ini +sudo echo "plugins = python3" >> examples/nginx/acme2certifier.ini ``` 17. Create a Systemd Unit File for uWSGI or use the one stored in excample/nginx directory ```bash -$ cp examples/nginx/uwsgi.service /etc/systemd/system/ -$ systemctl enable uwsgi.service +sudo cp examples/nginx/uwsgi.service /etc/systemd/system/ +sudo systemctl enable uwsgi.service ``` 18. start uWSGI as service ```bash -$ systemctl start uwsgi +sudo systemctl start uwsgi ``` 19. configure NGINX as reverse proxy or use example stored in examples/nginx directory and modify it according to your needs ```bash -$ cp examples/nginx/nginx_acme.conf /etc/nginx/conf.d/acme.conf +sudo cp examples/nginx/nginx_acme.conf /etc/nginx/conf.d/acme.conf ``` 20. restart nginx ```bash -$ systemctl restart nginx +sudo systemctl restart nginx ``` 21. adapt SELinux configuration by applying a customized policy allowing nginx to communicate with uwsgi by using Unix sockets ```bash -$ sudo checkmodule -M -m -o acme2certifier.mod examples/nginx/acme2certifier.te -$ sudo semodule_package -o acme2certifier.pp -m acme2certifier.mod -$ sudo semodule -i acme2certifier.pp +sudo checkmodule -M -m -o acme2certifier.mod examples/nginx/acme2certifier.te +sudo semodule_package -o acme2certifier.pp -m acme2certifier.mod +sudo semodule -i acme2certifier.pp ``` 20. test the server by accessing the directory resource ```bash -$ curl http:///directory +curl http:///directory ``` The above command should result in an error as the Selinx configuration needs to be adapted. diff --git a/docs/install_nginx_wsgi_ub22.md b/docs/install_nginx_wsgi_ub22.md index 2712e9a6..4edd2383 100644 --- a/docs/install_nginx_wsgi_ub22.md +++ b/docs/install_nginx_wsgi_ub22.md @@ -7,7 +7,7 @@ A [readymade shell script](../examples/install_scripts/a2c-ubuntu22-nginx.sh) pe 1. Install nginx and the corresponding wsgi module ```bash -$ sudo apt-get install -y python3-pip nginx uwsgi uwsgi-plugin-python3 curl +sudo apt-get install -y python3-pip nginx uwsgi uwsgi-plugin-python3 curl krb5-user libgssapi-krb5-2 libkrb5-3 python3-gssapi ``` 2. download the acme2certifier from [Github](https://github.com/grindsa/acme2certifier/archive/refs/heads/master.tar.gz) and unpack it. @@ -15,29 +15,29 @@ $ sudo apt-get install -y python3-pip nginx uwsgi uwsgi-plugin-python3 curl 3. install the missing python modules via pip ```bash -$ sudo pip3 install -r requirements.txt +sudo pip3 install -r requirements.txt ``` 4. Copy files and directories you need to run acme2certifier ```bash -$ sudo cp examples/acme2certifier_wsgi.py /var/www/acme2certifier/acme2certifier_wsgi.py -$ sudo cp -R examples/ca_handler/ /var/www/acme2certifier/examples/ca_handler -$ sudo cp -R examples/eab_handler/ /var/www/acme2certifier/examples/eab_handler -$ sudo cp -R examples/hooks/ /var/www/acme2certifier/examples/hooks -$ sudo cp -R examples/nginx/ /var/www/acme2certifier/examples/nginx -$ sudo cp examples/acme_srv.cfg /var/www/acme2certifier/examples/ -$ sudo cp -R acme_srv/ /var/www/acme2certifier/acme_srv -$ sudo cp -R tools/ /var/www/acme2certifier/tools -$ sudo cp examples/db_handler/wsgi_handler.py /var/www/acme2certifier/acme_srv/db_handler.py +sudo cp examples/acme2certifier_wsgi.py /var/www/acme2certifier/acme2certifier_wsgi.py +sudo cp -R examples/ca_handler/ /var/www/acme2certifier/examples/ca_handler +sudo cp -R examples/eab_handler/ /var/www/acme2certifier/examples/eab_handler +sudo cp -R examples/hooks/ /var/www/acme2certifier/examples/hooks +sudo cp -R examples/nginx/ /var/www/acme2certifier/examples/nginx +sudo cp examples/acme_srv.cfg /var/www/acme2certifier/examples/ +sudo cp -R acme_srv/ /var/www/acme2certifier/acme_srv +sudo cp -R tools/ /var/www/acme2certifier/tools +sudo cp examples/db_handler/wsgi_handler.py /var/www/acme2certifier/acme_srv/db_handler.py ``` 5. Adapt the nginx configuration file (uwsgi socket file is located in `/var/www/acme2certifier`) and activate the configuration ```bash -$ sed -i "s/run\/uwsgi\/acme.sock/var\/www\/acme2certifier\/acme.sock/g" examples/nginx/nginx_acme_srv.conf -$ sudo cp examples/nginx/nginx_acme_srv.conf /etc/nginx/sites-available/acme_srv.conf -$ sudo ln -s /etc/nginx/sites-available/acme_srv.conf /etc/nginx/sites-enabled/acme_srv.conf +sudo sed -i "s/run\/uwsgi\/acme.sock/var\/www\/acme2certifier\/acme.sock/g" examples/nginx/nginx_acme_srv.conf +sudo cp examples/nginx/nginx_acme_srv.conf /etc/nginx/sites-available/acme_srv.conf +sudo ln -s /etc/nginx/sites-available/acme_srv.conf /etc/nginx/sites-enabled/acme_srv.conf ``` 6. A adapt the uwsgi configuration file in place it in `/var/www/acme2certifier`: @@ -46,10 +46,10 @@ $ sudo ln -s /etc/nginx/sites-available/acme_srv.conf /etc/nginx/sites-enabled/a - uwsgi plugin for python3 must be activated ```bash -$ sed -i "s/\/run\/uwsgi\/acme.sock/acme.sock/g" examples/nginx/acme2certifier.ini -$ sed -i "s/nginx/www-data/g" examples/nginx/acme2certifier.ini -$ echo "plugins=python3" >> examples/nginx/acme2certifier.ini -$ sudo cp examples/nginx/acme2certifier.ini /var/www/acme2certifier +sudo sed -i "s/\/run\/uwsgi\/acme.sock/acme.sock/g" examples/nginx/acme2certifier.ini +sudo sed -i "s/nginx/www-data/g" examples/nginx/acme2certifier.ini +sudo echo "plugins=python3" >> examples/nginx/acme2certifier.ini +sudo cp examples/nginx/acme2certifier.ini /var/www/acme2certifier ``` 7. Pick the correct ca handler from `the examples/ca_handler` directory and copy it to `/var/www/acme2certifier/acme_srv/ca_handler.py` @@ -58,13 +58,13 @@ $ sudo cp examples/nginx/acme2certifier.ini /var/www/acme2certifier 9. ensure that the all files and directories under /var/www/acme2certifier are owned by the user running the webserver (www-data is just an example!) ```bash -$ sudo chown -R www-data.www-data /var/www/acme2certifier/ +sudo chown -R www-data.www-data /var/www/acme2certifier/ ``` 10. set correct permissions to acme subdirectory ```bash -$ sudo chmod a+x /var/www/acme2certifier/acme_srv +sudo chmod a+x /var/www/acme2certifier/acme_srv ``` 11. Create acme2certifier uwsgi service and place it under `/etc/systemd/system/` @@ -86,26 +86,26 @@ ExecStart=uwsgi --ini acme2certifier.ini WantedBy=multi-user.target EOT -$ sudo cp acme2certifier.service /etc/systemd/system/acme2certifier.service +sudo cp acme2certifier.service /etc/systemd/system/acme2certifier.service ``` 12. Start and activate the acme2certifier service ```bash -$ sudo systemctl start acme2certifier -$ sudo systemctl enable acme2certifier +sudo systemctl start acme2certifier +sudo systemctl enable acme2certifier ``` 13. Restart nginx ```bash -$ sudo systemctl restart nginx +sudo systemctl restart nginx ``` 14. Check access to the directory resource to verify that nginx and uwsgi services are up and running ```bash -$ curl http://127.0.0.1/directory +curl http://127.0.0.1/directory {"newAccount": "http://127.0.0.1/acme_srv/newaccount", "fa8b347d3849421ebc4b234205418805": "https://community.letsencrypt.org/t/adding-random-entries-to-the-directory/33417", "keyChange": "http://127.0.0.1/acme_srv/key-change", "newNonce": "http://127.0.0.1/acme_srv/newnonce", "meta": {"home": "https://github.com/grindsa/acme2certifier", "author": "grindsa "}, "newOrder": "http://127.0.0.1/acme_srv/neworders", "revokeCert": "http://127.0.0.1/acme_srv/revokecert"} ``` diff --git a/docs/install_rpm.md b/docs/install_rpm.md index 3af460b6..5443d77d 100644 --- a/docs/install_rpm.md +++ b/docs/install_rpm.md @@ -1,5 +1,5 @@ - + # RPM installation on AlmaLinux/Redhat EL/CentOS Stream 9 1. Download the latest [RPM package](https://github.com/grindsa/acme2certifier/releases). @@ -7,26 +7,45 @@ 2. Install "Extra Packages for Enterprise Linux (EPEL)" ```bash -$ sudo yum install -y epel-release -$ sudo yum update -y +sudo yum install -y epel-release +sudo yum update -y ``` 3. Install the RPM packages ```bash -$ sudo yum -y localinstall /tmp/acme2certifier/acme2certifier-0.23.1-1.0.noarch.rpm +sudo yum -y localinstall /tmp/acme2certifier/acme2certifier-0.23.1-1.0.noarch.rpm ``` +In case you install on Redhat 8.x you need to upgrade following packages + +- [python3-cryptography](https://cryptography.io/en/latest/) to version 36.0.1 or higher +- [python3-dns](https://www.dnspython.org/) to version 2.1 or higher. +- [python3-jwcrypto package](https://jwcrypto.readthedocs.io/en/latest/) to version 0.8 or higher. + +Backports of these packages being part of RHEL9 can be found in the [the a2c rpm repository](https://github.com/grindsa/sbom/raw/main/rpm-repo/RPMs/rhel8) + +- [python3-cryptography-36.0.1-4.el8.x86_64.rpm](https://github.com/grindsa/sbom/raw/main/rpm-repo/RPMs/rhel8/python3-cryptography-36.0.1-4.el8.x86_64.rpm) +- [python3-dns-2.1.0-6.el8.noarch.rpm](https://github.com/grindsa/sbom/raw/main/rpm-repo/RPMs/rhel8/python3-dns-2.1.0-6.el8.noarch.rpm) +- [python3-jwcrypto-0.8-4.el8.noarch.rpm](https://github.com/grindsa/sbom/raw/main/rpm-repo/RPMs/rhel8/python3-jwcrypto-0.8-4.el8.noarch.rpm) + +Depending on your ca_handler you may need additional modules: + +- [python3-impacket-0.11.0-1.el8.noarch.rpm](https://github.com/grindsa/sbom/raw/main/rpm-repo/RPMs/rhel8/python3-impacket-0.11.0-2grindsa.el8.noarch.rpm) when using [MS wcce handler](https://github.com/grindsa/acme2certifier/blob/master/docs/mswcce.md) +- [python3-ntlm-auth-1.5.0-2.el8.noarch.rpm](https://github.com/grindsa/sbom/raw/main/rpm-repo/RPMs/rhel8/python3-ntlm-auth-1.5.0-2.el8.noarch.rpm) when using [MS wse handler](https://github.com/grindsa/acme2certifier/blob/master/docs/mscertsrv.md) +- [python3-requests_ntlm-1.1.0-14.el8.noarch.rpm](https://github.com/grindsa/sbom/raw/main/rpm-repo/RPMs/rhel8/python3-requests_ntlm-1.1.0-14.el8.noarch.rpm) when using [MS wse handler](https://github.com/grindsa/acme2certifier/blob/master/docs/mscertsrv.md) +- [python3-requests-pkcs12-1.16-1.el8.noarch.rpm](https://github.com/grindsa/sbom/raw/main/rpm-repo/RPMs/rhel8/python3-requests-pkcs12-1.16-1.el8.noarch.rpm) when using [EST](https://github.com/grindsa/acme2certifier/blob/master/docs/est.md) or [EJBCA](https://github.com/grindsa/acme2certifier/blob/master/docs/ejbca.md) handler + 4. Copy NGINX configuration file ```bash -$ cp /opt/acme2certifier/examples/nginx/nginx_acme_srv.conf /etc/nginx/conf.d +cp /opt/acme2certifier/examples/nginx/nginx_acme_srv.conf /etc/nginx/conf.d ``` 5. Copy NGINX ssl configuration file (optional) ```bash -$ cp /opt/acme2certifier/examples/nginx/nginx_acme_srv_ssl.conf /etc/nginx/conf.d +cp /opt/acme2certifier/examples/nginx/nginx_acme_srv_ssl.conf /etc/nginx/conf.d ``` 5. Create a configuration file `acme_srv.cfg` in `/opt/acme2certifier/acme_srv/` or use the example stored in the examples directory @@ -35,15 +54,15 @@ $ cp /opt/acme2certifier/examples/nginx/nginx_acme_srv_ssl.conf /etc/nginx/conf. 8. Enable and start the acme2certifier service ```bash -$ systemctl enable acme2certifier.service -$ systemctl start acme2certifier.service +sudo systemctl enable acme2certifier.service +sudo systemctl start acme2certifier.service ``` 9. Enable and start the nginx service ```bash -$ systemctl enable nginx.service -$ systemctl start nginx.service +sudo systemctl enable nginx.service +sudo systemctl start nginx.service ``` 10. Test the server by accessing the directory resource diff --git a/docs/mscertsrv.md b/docs/mscertsrv.md index cfb14315..c5566ca8 100644 --- a/docs/mscertsrv.md +++ b/docs/mscertsrv.md @@ -2,11 +2,11 @@ # CA handler for Microsoft Certification Authority Web Enrollment Service -This CA handler uses Microsofts [Certification Authority Web Enrollment service](https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-r2-and-2012/hh831649(v=ws.11)) for certificate enrollment and the python library [magnuswatn](https://github.com/magnuswatn/)/[certsrv](https://github.com/magnuswatn/certsrv) for communication with the enrollment service. +This CA handler uses Microsofts [Certification Authority Web Enrollment service](https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-r2-and-2012/hh831649(v=ws.11)) for certificate enrollment and modified version of the python library [magnuswatn](https://github.com/magnuswatn/)/[certsrv](https://github.com/magnuswatn/certsrv) for communication with the enrollment service. When using the handler please be aware of the following limitations: -- Authentication towards Web Enrollment Service is limited to "basic" or "ntlm". There is currently no support for ClientAuth +- Authentication towards Web Enrollment Service is limited to "basic" "ntlm" or "gssapi" Kkerberos). There is currently no support for ClientAuth - Communication is limited to https - Revocation operations are not supported @@ -16,6 +16,7 @@ When using the handler please be aware of the following limitations: 2. You need to have a set of credentials with permissions to access the service and enrollment templates 3. Authentication method (basic or ntlm) to the service must be configured correctly. 4. (optional): In case you are installing from RPM and plan to use ntlm as authentication scheme you need two additonal python modules [python3-request-ntlm](https://pypi.org/project/requests_ntlm/) and [python3-ntlm-auth](https://pypi.org/project/ntlm-auth/) which are neither part of Standard nor the EPEL repo. If you have no clue from where to get these packaages feel free to use the ones being part of [the a2c github repository](https://github.com/grindsa/sbom/tree/main/rpm-repo/RPMs) +5. (optional): In case you are installing from RPM and plan to use gssapi as authentication scheme you need two additonal python modules [python3-request-gssapi](https://pypi.org/project/requests-gssapi/) and [gssapi](https://pypi.org/project/gssapi/). If you have no clue from where to get these packaages feel free to use the ones being part of [the a2c github repository](https://github.com/grindsa/sbom/tree/main/rpm-repo/RPMs) It is helpful to verify the service access before starting the configuration of acme2certifier @@ -31,6 +32,14 @@ root@rlh:~# curl -I --ntlm --user : -k https:///certsrv/ root@rlh:~# curl -I --user : -k https:///certsrv/ ``` +- service access by using gssapi authentication + +```bash +root@rlh:~# export KRB5_CONFIG=/krb5.conf +root@rlh:~# kinit +root@rlh:~# curl --negotiate -u: : -k https:///certsrv/ +``` + Access to the service is possible if you see the status code 200 returned as part of the response ```bash @@ -69,6 +78,9 @@ password: ca_bundle: auth_method: template: +allowed_domainlist: ["example.com", "*.example2.com"] +krb5_config: /krb5.conf +eab_profiling: False ``` - host - hostname of the system providing the Web enrollment service @@ -78,5 +90,77 @@ template: - password - password - password_variable - *optional* - name of the environment variable containing the password used for service access (a configured `password` parameter in acme_srv.cfg takes precedence) - ca_bundle - CA certificate bundle in pem format needed to validate the server certificate -- auth_method - authentication method (either "basic" or "ntlm") +- auth_method - authentication method (either "basic", "ntlm" or "gssapi") +- krb5_config - *optional* - path to individual krb5.conf - template - certificate template used for enrollment +- allowed_domainlist - *optional* - list of domain-names allowed for enrollment in json format example: ["bar.local$, bar.foo.local] +- eab_profiling - optional - [activate eab profiling](eab_profiling.md) (default: False) + +## Passing a template from client to server + +The handler makes use of the [header_info_list feature](header_info.md) allowing an acme-client to specify a template name to be used during certificate enrollment. This feature is disabled by default and must be activate in `acme_srv.cfg` as shown below + +```config +[Order] +... +header_info_list: ["HTTP_USER_AGENT"] +``` + +The acme-client can then specify the temmplate name as part of its user-agent string. + +Example for acme.sh: + +```bash +docker exec -i acme-sh acme.sh --server http:// --issue -d --standalone --useragent template=foo --debug 3 --output-insecure +``` + +Example for lego: + +```bash +docker run -i -v $PWD/lego:/.lego/ --rm --name lego goacme/lego -s http:// -a --email "lego@example.com" --user-agent template=foo -d --http run +``` + +# eab profiling + +This handler can use the [eab profiling feture](eab_profiling.md) to allow individual enrollment configuration per acme-account as well as restriction of CN and SANs to be submitted within the CSR. The feature is disabled by default and must be activated in `acme_srv.cfg` + +```cfg +[EABhandler] +eab_handler_file: examples/eab_handler/kid_profile_handler.py +key_file: + +[CAhandler] +eab_profiling: True +``` + +below an example key-file used during regression testing: + +```json +{ + "keyid_00": { + "hmac": "V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw", + "cahandler": { + "template": ["WebServerModified", "WebServer"], + "allowed_domainlist": ["www.example.com", "www.example.org", "*.local"], + "unknown_key": "unknown_value" + } + }, + "keyid_01": { + "hmac": "YW5vdXRoZXJfdmVyeV9sb25nX2htYWNfZm9yX2tleWlkXzAxX3doaWNoIHdpbGxfYmUgdXNlZF9kdXJpbmcgcmVncmVzc2lvbg", + "cahandler": { + "template": "WebServerModified", + "allowed_domainlist": ["www.example.com", "www.example.org", "*.local"], + "unknown_key": "unknown_value" + } + }, + "keyid_02": { + "hmac": "dGhpc19pc19hX3ZlcnlfbG9uZ19obWFjX3RvX21ha2Vfc3VyZV90aGF0X2l0c19tb3JlX3RoYW5fMjU2X2JpdHM", + "cahandler": { + "allowed_domainlist": ["www.example.com", "www.example.org"] + } + }, + "keyid_03": { + "hmac": "YW5kX2ZpbmFsbHlfdGhlX2xhc3RfaG1hY19rZXlfd2hpY2hfaXNfbG9uZ2VyX3RoYW5fMjU2X2JpdHNfYW5kX3Nob3VsZF93b3Jr" + } +} +``` diff --git a/docs/mswcce.md b/docs/mswcce.md index 42c4df21..5483001d 100644 --- a/docs/mswcce.md +++ b/docs/mswcce.md @@ -16,14 +16,42 @@ When using the handler please be aware of the following limitations: 3. (optional): In case you are installing from RPM or DEB and plan to use kerberos authentication you need an updated [impacket modules of version 0.11 or higher](https://github.com/fortra/impacket) as older versions have issues with the handling of utf8-encoded passwords. If you have no clue from where to get these packaages feel free to use the one being part of [the a2c github repository](https://github.com/grindsa/sbom/tree/main/rpm-repo/RPMs) 4. You need to have a set of credentials with permissions to access the service and enrollment templates -## Installation +## Local Installation -- install the [impacket](https://github.com/SecureAuthCorp/impacket) via pip (the module is already part of the docker images) +- install the [impacket](https://github.com/fortra/impacket) module + +*IMPORTANT*: + +Some malware scanners like Microsoft Defender classify the impacket module as hacking-tool (see [forta/impacket#1762](https://github.com/fortra/impacket/issues/1762) or [forta/impacket#1271](https://github.com/fortra/impacket/issues/1271#issuecomment-1058729047)). Main reason for the alarms are not the library itself but rather the example script coming along with it. To avoid hazzle with your CSIRT team I suggest to install a strip-down version of impacket which which do not contain the scripts flagged by the scanners. Packages for [RH8](https://github.com/grindsa/sbom/raw/main/rpm-repo/RPMs/rhel8/python3-impacket-0.11.0-2grindsa.el8.noarch.rpm) and [RH9](https://github.com/grindsa/sbom/raw/main/rpm-repo/RPMs/rhel9/python3-impacket-0.11.0-2grindsa.el9.noarch.rpm) can be found in my [SBOM repo](https://github.com/grindsa/sbom/tree/main/rpm-repo) + +In case you install impacket from pip or form sources I suggest to: + +- download the impacket package: + +```bash +pip3 download impacket --no-deps +``` + +- unpack the archive + +```bash + tar xvfz impacket-0.11.0.tar.gz +``` + +- delete all files and subdirectories in `examples` sub-directory + +```bash +rm -rf impacket-0.11.0/examples/* +``` + +- install the package ```bash -root@rlh:~# pip install impacket +python3 setup.py install ``` +## Configuration + - modify the server configuration (acme_srv/acme_srv.cfg) and add the following parameters ```config @@ -37,7 +65,10 @@ domain_controller: ca_name: ca_bundle: template: