package validation import ( "testing" kapi "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/util/intstr" "github.com/openshift/origin/pkg/route/api" ) const ( testExpiredCAUnknownCertificate = `-----BEGIN CERTIFICATE----- MIIDIjCCAgqgAwIBAgIBBjANBgkqhkiG9w0BAQUFADCBoTELMAkGA1UEBhMCVVMx CzAJBgNVBAgMAlNDMRUwEwYDVQQHDAxEZWZhdWx0IENpdHkxHDAaBgNVBAoME0Rl ZmF1bHQgQ29tcGFueSBMdGQxEDAOBgNVBAsMB1Rlc3QgQ0ExGjAYBgNVBAMMEXd3 dy5leGFtcGxlY2EuY29tMSIwIAYJKoZIhvcNAQkBFhNleGFtcGxlQGV4YW1wbGUu Y29tMB4XDTE2MDExMzE5NDA1N1oXDTI2MDExMDE5NDA1N1owfDEYMBYGA1UEAxMP d3d3LmV4YW1wbGUuY29tMQswCQYDVQQIEwJTQzELMAkGA1UEBhMCVVMxIjAgBgkq hkiG9w0BCQEWE2V4YW1wbGVAZXhhbXBsZS5jb20xEDAOBgNVBAoTB0V4YW1wbGUx EDAOBgNVBAsTB0V4YW1wbGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM0B u++oHV1wcphWRbMLUft8fD7nPG95xs7UeLPphFZuShIhhdAQMpvcsFeg+Bg9PWCu v3jZljmk06MLvuWLfwjYfo9q/V+qOZVfTVHHbaIO5RTXJMC2Nn+ACF0kHBmNcbth OOgF8L854a/P8tjm1iPR++vHnkex0NH7lyosVc/vAgMBAAGjDTALMAkGA1UdEwQC MAAwDQYJKoZIhvcNAQEFBQADggEBADjFm5AlNH3DNT1Uzx3m66fFjqqrHEs25geT yA3rvBuynflEHQO95M/8wCxYVyuAx4Z1i4YDC7tx0vmOn/2GXZHY9MAj1I8KCnwt Jik7E2r1/yY0MrkawljOAxisXs821kJ+Z/51Ud2t5uhGxS6hJypbGspMS7OtBbw7 8oThK7cWtCXOldNF6ruqY1agWnhRdAq5qSMnuBXuicOP0Kbtx51a1ugE3SnvQenJ nZxdtYUXvEsHZC/6bAtTfNh+/SwgxQJuL2ZM+VG3X2JIKY8xTDui+il7uTh422lq wED8uwKl+bOj6xFDyw4gWoBxRobsbFaME8pkykP1+GnKDberyAM= -----END CERTIFICATE-----` testExpiredCertPrivateKey = `-----BEGIN RSA PRIVATE KEY----- MIICWwIBAAKBgQDNAbvvqB1dcHKYVkWzC1H7fHw+5zxvecbO1Hiz6YRWbkoSIYXQ EDKb3LBXoPgYPT1grr942ZY5pNOjC77li38I2H6Pav1fqjmVX01Rx22iDuUU1yTA tjZ/gAhdJBwZjXG7YTjoBfC/OeGvz/LY5tYj0fvrx55HsdDR+5cqLFXP7wIDAQAB AoGAfE7P4Zsj6zOzGPI/Izj7Bi5OvGnEeKfzyBiH9Dflue74VRQkqqwXs/DWsNv3 c+M2Y3iyu5ncgKmUduo5X8D9To2ymPRLGuCdfZTxnBMpIDKSJ0FTwVPkr6cYyyBk 5VCbc470pQPxTAAtl2eaO1sIrzR4PcgwqrSOjwBQQocsGAECQQD8QOra/mZmxPbt bRh8U5lhgZmirImk5RY3QMPI/1/f4k+fyjkU5FRq/yqSyin75aSAXg8IupAFRgyZ W7BT6zwBAkEA0A0ugAGorpCbuTa25SsIOMxkEzCiKYvh0O+GfGkzWG4lkSeJqGME keuJGlXrZNKNoCYLluAKLPmnd72X2yTL7wJARM0kAXUP0wn324w8+HQIyqqBj/gF Vt9Q7uMQQ3s72CGu3ANZDFS2nbRZFU5koxrggk6lRRk1fOq9NvrmHg10AQJABOea pgfj+yGLmkUw8JwgGH6xCUbHO+WBUFSlPf+Y50fJeO+OrjqPXAVKeSV3ZCwWjKT4 9viXJNJJ4WfF0bO/XwJAOMB1wQnEOSZ4v+laMwNtMq6hre5K8woqteXICoGcIWe8 u3YLAbyW/lHhOCiZu2iAI8AbmXem9lW6Tr7p/97s0w== -----END RSA PRIVATE KEY-----` testCertificate = `-----BEGIN CERTIFICATE----- MIICwjCCAiugAwIBAgIBATANBgkqhkiG9w0BAQsFADBjMQswCQYDVQQGEwJVUzEL MAkGA1UECAwCQ0ExETAPBgNVBAoMCFNlY3VyaXR5MRswGQYDVQQLDBJPcGVuU2hp ZnQzIHRlc3QgQ0ExFzAVBgNVBAMMDmhlYWRlci50ZXN0IENBMB4XDTE2MDMxMjA0 MjEwM1oXDTM2MDMxMjA0MjEwM1owWDEUMBIGA1UEAwwLaGVhZGVyLnRlc3QxCzAJ BgNVBAgMAkNBMQswCQYDVQQGEwJVUzERMA8GA1UECgwIU2VjdXJpdHkxEzARBgNV BAsMCk9wZW5TaGlmdDMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQD0 XEAzUMflZy8zluwzqMKnu8jYK3yUoEGLN0Bw0A/7ydno1g0E92ee8M9p59TCCWA6 nKnt1DEK5285xAKs9AveutSYiDkpf2px59GvCVx2ecfFBTECWHMAJ/6Y7pqlWOt2 hvPx5rP+jVeNLAfK9d+f57FGvWXrQAcBnFTegS6J910kbvDgNP4Nerj6RPAx2UOq 6URqA4j7qZs63nReeu/1t//BQHNokKddfxw2ZXcL/5itgpPug16thp+ugGVdjcFs aasLJOjErUS0D+7bot98FL0TSpxWqwtCF117bSLY7UczZFNAZAOnZBFmSZBxcJJa TZzkda0Oiqo0J3GPcZ+rAgMBAAGjDTALMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQEL BQADgYEACkdKRUm9ERjgbe6w0fw4VY1s5XC9qR1m5AwLMVVwKxHJVG2zMzeDTHyg 3cjxmfZdFU9yxmNUCh3mRsi2+qjEoFfGRyMwMMx7cduYhsFY3KA+Fl4vBRXAuPLR eCI4ErCPi+Y08vOto9VVXg2f4YFQYLq1X6TiXD5RpQAN0t8AYk4= -----END CERTIFICATE-----` testPrivateKey = `-----BEGIN RSA PRIVATE KEY----- MIIEpAIBAAKCAQEA9FxAM1DH5WcvM5bsM6jCp7vI2Ct8lKBBizdAcNAP+8nZ6NYN BPdnnvDPaefUwglgOpyp7dQxCudvOcQCrPQL3rrUmIg5KX9qcefRrwlcdnnHxQUx AlhzACf+mO6apVjrdobz8eaz/o1XjSwHyvXfn+exRr1l60AHAZxU3oEuifddJG7w 4DT+DXq4+kTwMdlDqulEagOI+6mbOt50Xnrv9bf/wUBzaJCnXX8cNmV3C/+YrYKT 7oNerYafroBlXY3BbGmrCyToxK1EtA/u26LffBS9E0qcVqsLQhdde20i2O1HM2RT QGQDp2QRZkmQcXCSWk2c5HWtDoqqNCdxj3GfqwIDAQABAoIBAEfl+NHge+CIur+w MXGFvziBLThFm1NTz9U5fZFz9q/8FUzH5m7GqMuASVb86oHpJlI4lFsw6vktXXGe tbbT28Y+LJ1wv3jxT42SSwT4eSc278uNmnz5L2UlX2j6E7CA+E8YqCBN5DoKtm8I PIbAT3sKPgP1aE6OuUEFEYeidOIMvjco2aQH0338sl6cObkQFEgnWf2ncun3KGnb s+dMO5EdYLo0rOdDXY88sElfqiNYYl/FRu9O3OfqHvScA5uo9FlIhukcrRkbjFcq j/7k4tt0iLs9B2j+4ihBWYo5eRFIde4Izj6a6ArEk0ShEUvwlZBuGMM/vs+jvbDK l3+0NpECgYEA/+qxwvOGjmlYNKFK/rzxd51EnfCISnV+tb17pNyRmlGToi1/LmmV +jcJfcwlf2o8mTFn3xAdD3fSaHF7t8Li7xDwH2S+sSuFE/8bhgHUvw1S7oILMYyO hO6sWG+JocMhr8IejaAnQxav9VvP01YDfw/XBB0O1EIuzzr2KHq+AGMCgYEA9HCY JGTcv7lfs3kcCAkDtjl8NbjNRMxRErG0dfYS+6OSaXOOMg1TsaSNEgjOGyUX+yQ4 4vtKcLwHk7+qz3ZPbhS6m7theZG9jUwMrQRGyCE7z3JUy8vmV/N+HP0V+boT+4KM Tai3+I3hf9+QMHYx/Z/VA0K6f27LwP+kEL9C8hkCgYEAoiHeXNRL+w1ihHVrPdgW YuGQBz/MGOA3VoylON1Eoa/tCGIqoQzjp5IWwUwEtaRon+VdGUTsJFCVTPYYm2Ms wqjIeBsrdLNNrE2C8nNWhXO7hr98t/eEk1NifOStHX6yaNdi4/cC6M4GzDtOf2WO 8YDniAOg0Xjcjw2bxil9FmECgYBuUeq4cjUW6okArSYzki30rhka/d7WsAffEgjK PFbw7zADG74PZOhjAksQ2px6r9EU7ZInDxbXrmUVD6n9m/3ZRs25v2YMwfP0s1/9 LjLr2+PsikMu/0VkaGaAmtCyNoMSPicoXX86VH5zgejHlnCVcO9oW1NkdBLNdhML 4+ZI8QKBgQDb+SH7i50Yu3adwvPkDSp3ACCzPoHXno79a7Y5S2JzpFtNq+cNLWEb HP8gHJSZnaGrLKmjwNeQNsARYajKmDKO5HJ9g5H5Hae8enOb2yie541dneDT8rID 4054dMQJnijd8620yf8wiNy05ZPOQQ0JvA/rW3WWZc5PGm8c2PsVjg== -----END RSA PRIVATE KEY-----` testCACertificate = `-----BEGIN CERTIFICATE----- MIIClDCCAf2gAwIBAgIJAPU57OGhuqJtMA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNV BAYTAlVTMQswCQYDVQQIDAJDQTERMA8GA1UECgwIU2VjdXJpdHkxGzAZBgNVBAsM Ek9wZW5TaGlmdDMgdGVzdCBDQTEXMBUGA1UEAwwOaGVhZGVyLnRlc3QgQ0EwHhcN MTYwMzEyMDQyMTAzWhcNMzYwMzEyMDQyMTAzWjBjMQswCQYDVQQGEwJVUzELMAkG A1UECAwCQ0ExETAPBgNVBAoMCFNlY3VyaXR5MRswGQYDVQQLDBJPcGVuU2hpZnQz IHRlc3QgQ0ExFzAVBgNVBAMMDmhlYWRlci50ZXN0IENBMIGfMA0GCSqGSIb3DQEB AQUAA4GNADCBiQKBgQCsdVIJ6GSrkFdE9LzsMItYGE4q3qqSqIbs/uwMoVsMT+33 pLeyzeecPuoQsdO6SEuqhUM1ivUN4GyXIR1+aW2baMwMXpjX9VIJu5d4FqtGi6SD RfV+tbERWwifPJlN+ryuvqbbDxrjQeXhemeo7yrJdgJ1oyDmoM5pTiSUUmltvQID AQABo1AwTjAdBgNVHQ4EFgQUOVuieqGfp2wnKo7lX2fQt+Yk1C4wHwYDVR0jBBgw FoAUOVuieqGfp2wnKo7lX2fQt+Yk1C4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0B AQsFAAOBgQA8VhmNeicRnKgXInVyYZDjL0P4WRbKJY7DkJxRMRWxikbEVHdySki6 jegpqgJqYbzU6EiuTS2sl2bAjIK9nGUtTDt1PJIC1Evn5Q6v5ylNflpv6GxtUbCt bGvtpjWA4r9WASIDPFsxk/cDEEEO6iPxgMOf5MdpQC2y2MU0rzF/Gg== -----END CERTIFICATE-----` testDestinationCACertificate = testCACertificate testValidInFutureCert = `-----BEGIN CERTIFICATE----- MIIDjzCCAnegAwIBAgIJAJcdKWMFNUEGMA0GCSqGSIb3DQEBCwUAMF0xCzAJBgNV BAYTAlVTMQswCQYDVQQIDAJDQTERMA8GA1UECgwIU2VjdXJpdHkxEzARBgNVBAsM ClNlbGZTaWduZXIxGTAXBgNVBAMMEHNlbGYuc2lnbmVyLnRlc3QwIBcNMzgwMTAx MDgwMDAyWhgPMjA1ODAxMDEwODAwMDJaMF0xCzAJBgNVBAYTAlVTMQswCQYDVQQI DAJDQTERMA8GA1UECgwIU2VjdXJpdHkxEzARBgNVBAsMClNlbGZTaWduZXIxGTAX BgNVBAMMEHNlbGYuc2lnbmVyLnRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw ggEKAoIBAQDBAtP5vHkVS9qZNmI9QKj7B/ATt2+Fw+f4xD+6Q2+1sOkLH3x6+D85 5A+xAAvQdz5qf+yfvtNOhWqmIG5Zh0TzaiA5lw2U0YL4FT4Z4nbYAPMO45lctvRH nXBeSO7N/JiFBlvMPqP4gsimstEgiNm225KlQRHOqMfOEAC15pyUrE643Gs0DCVR L1tZuwdfBUpybxAPDWpgx7CNTc0beuNXooroMU1dCdM+BjYHYfSCnoNwa4qp130e 6vRWnzlhfXbFTsCVCe4y6edF/+M3PegIx0+PhkgeSOxd2+nBsiatrG5ZyiP5iaRK 2278nFERyUQ1SbhicDrhlU9TQAMcTMAvAgMBAAGjUDBOMB0GA1UdDgQWBBQ28jRf N/CCqVyOU8mOZpG8ow86WjAfBgNVHSMEGDAWgBQ28jRfN/CCqVyOU8mOZpG8ow86 WjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQC+Nu8pEUB7agGHUU/e 1NHI84guwKKA2qNnkQZKn6h49AA/bPjKr9SFQHNxFFMyrVInt1Ez9sRNviArQc+w DToHY+T/3WUVcQIQnRW3m4r6UUsxKZjtrSBD2Dhr6nL9hVVtGIfimuuxxJt1JItJ UaOY+Kq4gtWOJMcV5xTEaPmkphAgwoZzjZj7Z9SZwVLGopJa8kB3EvlkxUO3DmSp 9Lq3AhHRYgwWcjcd9UC9NyXQ9hBTV2iPBSvc2I4vmYQwnOutBEeNM0IPQQk7f2VL fKSS26HocZpiN0e7vO0XoJfh4VkOIn7BGNwxiDr9cIRL4ZHhZ0/kRQuXCHHYbTdq 9mKv -----END CERTIFICATE-----` testValidInFutureKey = `-----BEGIN PRIVATE KEY----- MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDBAtP5vHkVS9qZ NmI9QKj7B/ATt2+Fw+f4xD+6Q2+1sOkLH3x6+D855A+xAAvQdz5qf+yfvtNOhWqm IG5Zh0TzaiA5lw2U0YL4FT4Z4nbYAPMO45lctvRHnXBeSO7N/JiFBlvMPqP4gsim stEgiNm225KlQRHOqMfOEAC15pyUrE643Gs0DCVRL1tZuwdfBUpybxAPDWpgx7CN Tc0beuNXooroMU1dCdM+BjYHYfSCnoNwa4qp130e6vRWnzlhfXbFTsCVCe4y6edF /+M3PegIx0+PhkgeSOxd2+nBsiatrG5ZyiP5iaRK2278nFERyUQ1SbhicDrhlU9T QAMcTMAvAgMBAAECggEAWYJvPd0bJjY0XWNsMc3fz/NBclNao+VTmfmhOEd38gHm QaNLflfMMpPCdyp3UClMx+UlnnvH0R1sdTiLFHf4EQ7BfRPBV6fGHjjzwNtWlBv0 nI4OnIG4TdIEv6UBIoQnU2G8hr7yGhjE5xH8jCMLHJM9see4U2fQqY6gVbtqGEP1 w29IhoYcCPsqIhBYlmOaxvEBA12SKjZEaLT4dTImcvNsYuNAHbKpS1m6nA7KaqLN hkFJ5oKPlsMT2bFCaHzB7Es/90FgkLk3EULx9G5uV+26FcovhSKI/j4kkBZ57BZG rGuMScjxGLolY7dv0PlQvSzDmsA4EEzEQECy5kJFAQKBgQDv7jhEBsuKs9t6UOBF QBsmAsTs5I9UoQd5ZBy1QoOxmN5aLjNNfFd86LBomC/oF0AZpEKfHA+Ha8ttdJNX vjkSIbfJKYfd4J/A4J7Wna3RPExu0wqN3g2xiPNeyYmzd8H2ER1t850YzFbT8f7M pSQbbqWkjLzRw3wUBVQao/PlrwKBgQDN8CPWZuKzIhSsBLKtG41evnSCMOoSWRRQ VmLnxIa7x8Ng/v8T39S4Tzpx50uq0ZAoegmI5aMvJEwayMShZdHt++DIjNfnayXS yQ6Cr+FqObeZX1B25eChiyN/O/RPx1zJ6eW0FUKlTheYIv4u+D0AwzmyaySeAEyo ZhiOnS3tgQKBgD9y3NhIf70fURQonRZTHJrRsqf+zVSQ/PwCGIFqpI7roSlx/Ekq b6xtkHEohcq3k1D0mlWfQxAJ1pMMeAaFHGyKFCMTY4WuaDDGddrFefjSHFhWYP0h Ure3Qry3ST33lohvADxaZxnut6t23G3b4g+LFCzOtwQ10PMucY5V+yKrAoGAfAyc OckN46Oy2g+WZYoENT76RXYbeWPpRZ9TwpJyKmjheur/UcRxiXhIF1ahEMtdT9R7 K9hP3NS7dyLatvHza6xesc+NOlwjk34C3Jv/Z5JO0vdEK+q6zfRXNIwz1V6cuQ/I ixqHY7XPppfljvt/G5d9iMjbbMV3Z7TgM//gK4ECgYBkSU6B77LnXtb0QPTsBdq6 7hvEPH4lhnpcXRemfq3Q0/GYeACSoAPUGxy8LwT50pagaIf6ZG1esMFiALFsJWer XdzRo+/NffATcVvoof1Gnjhe/qt0kby66wR42JJMK/q4BKAN0kitfkzOPC4HVoF4 DOGy/dMN+k0W2RgJ5JKR3g== -----END PRIVATE KEY-----` testSelfSignedCert = `-----BEGIN CERTIFICATE----- MIIDjTCCAnWgAwIBAgIJAKM4rr3VRQARMA0GCSqGSIb3DQEBCwUAMF0xCzAJBgNV BAYTAlVTMQswCQYDVQQIDAJDQTERMA8GA1UECgwIU2VjdXJpdHkxEzARBgNVBAsM ClNlbGZTaWduZXIxGTAXBgNVBAMMEHNlbGYuc2lnbmVyLnRlc3QwHhcNMTYxMTAx MjEzNzU4WhcNMzYxMTAxMjEzNzU4WjBdMQswCQYDVQQGEwJVUzELMAkGA1UECAwC Q0ExETAPBgNVBAoMCFNlY3VyaXR5MRMwEQYDVQQLDApTZWxmU2lnbmVyMRkwFwYD VQQDDBBzZWxmLnNpZ25lci50ZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB CgKCAQEAvF0Rw580En6xCPvoLoMBUzI9HD5D7UFycpOG/qL5ZtmhzYR62WBKhc/C ysWxRL3+GFD9m5zoDuB2qGMohBfsIVF2TX7oqgovKkX7BDO92vrDtGJo/QJnUhku pASTmAgPMacxwvSQM5yJgb5GNtkvoulXbE31S5VDamcsH+ej0VKYKKXPtbFDBMxx NysoUCCb1SiPBicgx9V69VlU6UeataNHz0oyxH9ijCYShePbk0TQRXlyTzdMIaL0 AeWLlngmlVYP1RoZXGNupX5R8EAdrc5nRV5+epkJDzOHfxE3bbSM8fzPcI7KyHkp sA3PBPf8uUFfGNGpt4ubc4Kp0yL1vwIDAQABo1AwTjAdBgNVHQ4EFgQUNvPQ5ChF G8UpyLlnVlrXmN9Oi0QwHwYDVR0jBBgwFoAUNvPQ5ChFG8UpyLlnVlrXmN9Oi0Qw DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAhOCb94qvpwad4ZyGfeV9 aE/9wIGT/xs0KnV7wS1OopGnglcgogns5Vcs2rzBrcN04n5EYZ+V7naMjReVhpBv gJ26YYfnitrGkWazncGW1BYI7fXAdU2cBJ+LLCbZX1zz9BqBW5ldvbk/XWTg4ols 29j8kpLwA2UEApE25xWmXBBHyDIzvNzyiwswrdo26BUZdHCA/pplPFpz6UEYLYEX Bv95o5CLf2CQIxC6uE7BENrQo7ItwHvJoYlkdkYil3V/Qx25YafulH+wbL6ccN6F fjEOS33MDf9AIbgSgiPlGSwkikVjy73ADWWdQCOJhrMUnSnqE05gCRd5qIggACf1 0A== -----END CERTIFICATE-----` testSelfSignedKey = `-----BEGIN PRIVATE KEY----- MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC8XRHDnzQSfrEI ++gugwFTMj0cPkPtQXJyk4b+ovlm2aHNhHrZYEqFz8LKxbFEvf4YUP2bnOgO4Hao YyiEF+whUXZNfuiqCi8qRfsEM73a+sO0Ymj9AmdSGS6kBJOYCA8xpzHC9JAznImB vkY22S+i6VdsTfVLlUNqZywf56PRUpgopc+1sUMEzHE3KyhQIJvVKI8GJyDH1Xr1 WVTpR5q1o0fPSjLEf2KMJhKF49uTRNBFeXJPN0whovQB5YuWeCaVVg/VGhlcY26l flHwQB2tzmdFXn56mQkPM4d/ETdttIzx/M9wjsrIeSmwDc8E9/y5QV8Y0am3i5tz gqnTIvW/AgMBAAECggEBAKkJqJByRau3UC5syj87R6wesKKw6gp3qjpSVFodbU20 TrT9h7Wd6SLOgNOxt9Sl3+p4fC7zD3mSTEnuuoRYZ4q67Ty8gBVgkFUSeiKaQG3M jmZJzkgHqSsO+EEu7jkIOoJntYtsKCB5ARmS5LYCD/LWDqNeDpymtdo9/mYfXW7R cwCIbv0mXjybx4YUKLvVAstszmvr4uZXPqBlceaBv4jTx2xZlzCM6WAgMbjJM3vS 3BLFcICy3fhXSzEtaAefTnFVRzXAUZjgKn73JpHsPqScfFw4Q/eR/AN/jpjPkrsx scRFqpRFEVO3/9A+PoFzL3ofaD6pTPVdCYdQCtA14iECgYEA4XHWGNUO7+HhAxb8 2XhtkuvDN3HH/QswCqI5zyXnYoE47OD3stLD1YsDl2wm+XCl5/N5u0qx2Hh0956q Zwk2BBZnHU4yfLsCieSiyDff8ulJMX1Xh0Ssk3bmDucMjatmfWXrMsMVhB+Tm+oA yhMGe3rKKk4aGMfEQ2vAbFRwuDECgYEA1eSk7bqJeRn4Y0iW0I4w09CJ9DlmzR/S 3VDEmbHcny4noEHRNPMacjDvNuj04XOlbsm4R785M4WRgoZxQXDpXSfL23UFbmPU yxxNYw3dc10q2u+PjzXc6bzv/qYsNuc6SmNeUT1puI9SnEEYT7+6CaeHeJB4W1RL B2pSEqmXAO8CgYEAonH7WmNTYwh4sVhEE5OSKPaW8QGcoDoKgO8KBriCNNl2IkGs Wf9Cu0Fy8g4tOzmvYiZvhcQ5yAhsB+0dTic189YMsPIisPuzxZaosOqKBSeR5QYz JrYWQB/Bf+V+hyqFLEBfLHGjtFNockU4EmOJHTqKJ9elOEvhoM8olSZ3HlECgYAw 114F3uOHYLPEUA4IH3/sziDCQN1Fl6+507ig8+lR++MWiBDyi1SNoLjvC/DnDlZH Xw6Sa4rvRd+9M1/nNpZDLFQzj5wm4er0Wkkdhkv8DNk9Vxir9fu07+zJdD6CZvh7 hgdCe8iJWUje30pi43/itnuLv0mMaUocrl2BX3JYxwKBgQC5+usY3fF/q8wLYGgo BRjkyMvkeRgidMwJMnimflZ7X9Svfh4gw7JYub8Vksys5RYQ/3wSZuwy2dxamCxr H6e+rtFlOu/BZSBUUgcOJ4xSDUilztVSMGHK7AxhBGlBHzPRwY8bjQfMaODs9pD8 qOFcy/8ogwZdP9nTV73O2wG56g== -----END PRIVATE KEY-----` testExpiredCertNoKey = `-----BEGIN CERTIFICATE----- MIIDIjCCAgqgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBoTELMAkGA1UEBhMCVVMx CzAJBgNVBAgMAlNDMRUwEwYDVQQHDAxEZWZhdWx0IENpdHkxHDAaBgNVBAoME0Rl ZmF1bHQgQ29tcGFueSBMdGQxEDAOBgNVBAsMB1Rlc3QgQ0ExGjAYBgNVBAMMEXd3 dy5leGFtcGxlY2EuY29tMSIwIAYJKoZIhvcNAQkBFhNleGFtcGxlQGV4YW1wbGUu Y29tMB4XDTE1MDExMjE0MTk0MVoXDTE2MDExMjE0MTk0MVowfDEYMBYGA1UEAwwP d3d3LmV4YW1wbGUuY29tMQswCQYDVQQIDAJTQzELMAkGA1UEBhMCVVMxIjAgBgkq hkiG9w0BCQEWE2V4YW1wbGVAZXhhbXBsZS5jb20xEDAOBgNVBAoMB0V4YW1wbGUx EDAOBgNVBAsMB0V4YW1wbGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMrv gu6ZTTefNN7jjiZbS/xvQjyXjYMN7oVXv76jbX8gjMOmg9m0xoVZZFAE4XyQDuCm 47VRx5Qrf/YLXmB2VtCFvB0AhXr5zSeWzPwaAPrjA4ebG+LUo24ziS8KqNxrFs1M mNrQUgZyQC6XIe1JHXc9t+JlL5UZyZQC1IfaJulDAgMBAAGjDTALMAkGA1UdEwQC MAAwDQYJKoZIhvcNAQEFBQADggEBAFCi7ZlkMnESvzlZCvv82Pq6S46AAOTPXdFd TMvrh12E1sdVALF1P1oYFJzG1EiZ5ezOx88fEDTW+Lxb9anw5/KJzwtWcfsupf1m V7J0D3qKzw5C1wjzYHh9/Pz7B1D0KthQRATQCfNf8s6bbFLaw/dmiIUhHLtIH5Qc yfrejTZbOSP77z8NOWir+BWWgIDDB2//3AkDIQvT20vmkZRhkqSdT7et4NmXOX/j jhPti4b2Fie0LeuvgaOdKjCpQQNrYthZHXeVlOLRhMTSk3qUczenkKTOhvP7IS9q +Dzv5hqgSfvMG392KWh5f8xXfJNs4W5KLbZyl901MeReiLrPH3w= -----END CERTIFICATE-----` testIntCACertificateChain = `-----BEGIN CERTIFICATE----- MIIFqjCCA5KgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwYDELMAkGA1UEBhMCVVMx CzAJBgNVBAgMAkNBMREwDwYDVQQKDAhTZWN1cml0eTEbMBkGA1UECwwST3BlblNo aWZ0MyB0ZXN0IENBMRQwEgYDVQQDDAtyb290LmNhLm9yZzAeFw0xNjExMDMwMDE3 MTNaFw0zNjExMDMwMDE3MTNaMGgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTER MA8GA1UECgwIU2VjdXJpdHkxGzAZBgNVBAsMEk9wZW5TaGlmdDMgdGVzdCBDQTEc MBoGA1UEAwwTaW50ZXJtZWRpYXRlLmNhLm9yZzCCAiIwDQYJKoZIhvcNAQEBBQAD ggIPADCCAgoCggIBALrPYF7ah6vwSknXQj9IeoCXGnsMtin0UCFb5jsvDnoKrYqh 46/XMfiPGz/gr6wqkAis2n31/7H2oHUxgI5AjnWOzpyRRl2/NurVXYDaLCKiMsTm nt54d90VG5Yl4oFwzT7Az2xBBeJMTUyW4tB+66RCenlAq3AxO3Sp50Z4N1Cm34qI hg0/Wbs6VuzdKsyU5Tux0LrplF656A9BkpcOqvJmO6g9dKTA4KmhRyC+fxAk0p8d +WLuvumYQ19ta2ZjJxdCoVpaNMIsQ+ZyUTuq2VtIFLJVl/7Q5oZX1LDurtf0Ho/O TQq4L4sWQjYFXTCibU+logeg+qhPtO3kSuXcJBlaO1NqteA8sVQ2AQY48HNIr8VN ZsGFX+gmAZYesL62kFckKm39fsbuYQ/4mPHdgzYCuiNGFceoHcA/RBc42A4F7v9X Owm/OVccOnQTAZsZUUKj5cq16Is8K8j7hYJPIyfR2RIE7X52C1U7KLyra+Ld20ix JO1j59TmyQhBElEz1OZq3qX2TbpHG1sVjHyhZmbAjJDwpXCwZOPt/Icg9Qs6125X Rrr1zyTU/jr3TBBmdcBn4BFvtkWvAGndzNC1kun05vwEfqyQIfY/hbAWyZlPkWqP DETVGCN7ZQ21BPSaDsT29mD519FyMAbPAZxlou+yk//VeSgRh+N58SFKU/G/AgMB AAGjZjBkMB0GA1UdDgQWBBSJpW4a7QM2MkPIdhDrAIEEGc2RgzAfBgNVHSMEGDAW gBRS9nnAAIUE7lGEcTXwhJ6lsndnSTASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1Ud DwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAcKzpwgek+Bq+xLo77wQAL84V ezU1d+/bHWn/1pICbBpAmK6uuyeAKal/gZv7LVcpue4Wk+/WbAx8jUXi53pN7Qp+ oYMLF4eXiqolOO9lgSEoYyiO6qjXWKuiFlGOYsDzLeEWv6FhP3gpMXvMNidSFmLt qsUcsEtlFU9+Aub6msOsjKdsSQQMnj0Pfd4m35D6T3ZqW7swaEcvd72kbT6rkI2T aVt6dfEQS1qQrMOBYTr/5DUxkCaysYOGAd/eqfK3h00JcsllpoM1F8nYKSqrilLI Zts8rZg7GFbF76vJTEsYagrarhEg76p4Hdl2ZRr54+JA5Y7IEJBtA7UscXFiYR03 +2+1x9bYIcXR3uDa2WK20NsbDznO8rfbrX5m/X9McT7fbn+TE9MjKGaOMqwGoZdS 1hxwUeDqu6hf5qdETkqCaKCjIGBb8fg1cKmQXAAKTIS+6iI3iaF/bRTTa3gICZN7 FDdPRjMJDZ/k4cicAipzjKx2NQkiA59Q8z2aa5ahTWF2kz0YcdHtVDjIeDDR/KzT EodWld0L6StnRQ1kAIif0wAuQ//JVOBpCi93wykYPbdJ15A8qmqiS4bAbFdKCXph sP3gunYZT8RCrfAqJG/Is1RgChq2USckxvD4h8Q65J4VVRDkxvuLpjSh8ZJlI1xG r2RUXNnvSmi8ubzDBls= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFpjCCA46gAwIBAgIJANRKflwkpS0cMA0GCSqGSIb3DQEBCwUAMGAxCzAJBgNV BAYTAlVTMQswCQYDVQQIDAJDQTERMA8GA1UECgwIU2VjdXJpdHkxGzAZBgNVBAsM Ek9wZW5TaGlmdDMgdGVzdCBDQTEUMBIGA1UEAwwLcm9vdC5jYS5vcmcwHhcNMTYx MTAzMDAxNzEyWhcNMzYxMTAzMDAxNzEyWjBgMQswCQYDVQQGEwJVUzELMAkGA1UE CAwCQ0ExETAPBgNVBAoMCFNlY3VyaXR5MRswGQYDVQQLDBJPcGVuU2hpZnQzIHRl c3QgQ0ExFDASBgNVBAMMC3Jvb3QuY2Eub3JnMIICIjANBgkqhkiG9w0BAQEFAAOC Ag8AMIICCgKCAgEAojn1uV7bB37377bjZdwFvZpdk69fUgYGM2MlT/bdKGgLFXIx 8kUSjk8H84RiiZiPlyE+orTOdzv8umicW92qGF1y+rlLIAgTCdpEaiRvELCD4hsl 5fLK2686SbB1lQZzhi1ounFph7q0R6plfG762xdnGMLnsXDaYYz1kWWyDbJbd5DL grttZxfDsRwIDwiHVEsu5thOkL/C06/ipHQC9iDgnaeIeAp2UhLUblitgoeBLKLH +zu4cgKvQnSosIBIT11mQGrPe3B72/HBXSNAl7yuiCYnTantnLQxEHV4y9iQzmZ+ /F9ryZuBWMU49KKA952C5InDtjAjZjgdoqPRmiHMDoYqlnZdoMgYZPmEGhCnNMni pvB6qSwFa6l1xC4nlcYjyfkZzdg30P7dZwbtwG52e8tXHxwTm9LKbb3sCj2EAZSo 6h87NKxZX4o1WZbwPaNPVEVrlev7mdJsjZt9Qthzurm1Vcs9b1kDwEmyty4ssmPW F+UhPxSDZR28utTzFv99g94qmnjxzBoiAip2wAGdU4tzc1Cvh1njQYXhElJZpjlU RBQAeRvhKRQjnuripuZvTs29sIzLRuBKuY2u4xkDXVpvl3H+3CoFsN9oQ38qyZo/ uEeMHLuSMVDQycKHXJolMZOTHdB2O6CbhmYOkViG2cGHBpswLZ4IlgJ6ARsCAwEA AaNjMGEwHQYDVR0OBBYEFFL2ecAAhQTuUYRxNfCEnqWyd2dJMB8GA1UdIwQYMBaA FFL2ecAAhQTuUYRxNfCEnqWyd2dJMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQAcDKBGtSxnt/hZpRjrti2NDlwcn9SS ojkkKHnu4GdtO+8AHPfCHfUA5Ba1ydiddpxcR3tvjPCsfWTtmpoQ4wVFPGsMELqu elC/H3jEZxn1I+FdLFRB3QvBFQ3VvtbS6NemvMupWBxmimlOmp0woMW3wfH9MnPt EF5OFkcjhRKq1/bkzpKLkBpCQ/IIAm9ATgJmc9rADQxXbGvwHVpjORLOD55jOAl0 m5nFvawpKnJUVGKQ40MbHAz6tI5crSFJnA7VUWPfeCuQT04X9t3GNARUYnFxNBex /K7A/Of6CPqMNlXgeYieQyVJ/rbNtDLXne8uZhSUGd55B35QJ1HUxOJ/KcTC1Fw9 1jUBMkyco1wBvv/xtBUulzKpMOh7Dq5ABGa+lh9mANP822CmLO1DrQDmsjPiTEU0 n81Ir0FXVt12gXYtmWqDyILPrbcKImuiSojoH3rAD2sdnTNmgFQcBWQj/6TG+5Tm tSefyc9/CCsmIw0zrOVLfxs23k/Wts1acqTldWP5dY3MEyWrVOW6XakgYvPHdZa2 AkefO2oUf6dnu9JScZiEztIcr8IMfY7q+YOQKjDuH3gG2+SE6PPC46ajq0MoFeJU qA0au8ygoLaCLhYK+HnzGRVAYqc4hb4LKNhIbAveHLOTUKNeAFADxq8REsPkpeM7 G0k/6pTJTZwfsA== -----END CERTIFICATE-----` testCertificateWithIntCA = `-----BEGIN CERTIFICATE----- MIIGbzCCBFegAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwaDELMAkGA1UEBhMCVVMx CzAJBgNVBAgMAkNBMREwDwYDVQQKDAhTZWN1cml0eTEbMBkGA1UECwwST3BlblNo aWZ0MyB0ZXN0IENBMRwwGgYDVQQDDBNpbnRlcm1lZGlhdGUuY2Eub3JnMB4XDTE2 MTEwMzAwMTcxNFoXDTM2MTEwMzAwMTcxNFowYDELMAkGA1UEBhMCVVMxCzAJBgNV BAgMAkNBMREwDwYDVQQKDAhTZWN1cml0eTEbMBkGA1UECwwST3BlblNoaWZ0MyB0 ZXN0IENBMRQwEgYDVQQDDAt3d3cuY2EudGVzdDCCAiIwDQYJKoZIhvcNAQEBBQAD ggIPADCCAgoCggIBAJjnlw48H8YdfeFR2mKym1a77wbGL4MAysLA/V7bmQdiHbQh wMEINrEsWTIOnldT5+P1iNA10/wDz21XWXPSc+hp+O6wr+n/QjFUv5arKfeM2Nc3 7A+j8lTi83XXryLUNYrRVwX7qggBzCjWT1bKHYdZoi5YAvC/jsTrVtWdx/q67h66 jnKPxvLZVWov28azVfvrK9sP67osKIaT79lOS7jCJhgtpaQ3ds7BUR9SvoKgZnje 1cMNvxggqMwIRNxr9c1uu1irVu6XkT84oT2Q/shiKsjUpZBYaWEnYvQtT9Qp4yuH qV5Cs3IDonvK1E37UnwZJZdcfYFjoaahE8WD8Dn2BydbV+DGT9NMhx/5mVTQmYPm y1yItE1v+Bv3JZO6oiQcos2peS9XgM/EjGkQyOGOslr5qTgp2rOp8i1kMxObxAuo ddadqPHGTqcm4Tm1YQUlGNFA1N25GKKPtTC/Fv/BglY6RaCKzL7uW/AVfKBbCzPS r1hHfPYZu5jaBy4EEcV3K6ix3wjf/gA6YeAt96ltFOBCUC2me0Za5Es3PfzTPdfs vIlE+NpqAMGMauNs2swCHblLWmCElZmuQNbyfdH6APSK3sDLWAI0SfZTZKy9n944 lq8JYvGsFjE6D5zN60Q1xybhqku4tUvRJkvxN28TzEd2U6BoP1BU1r7OJWAjAgMB AAGjggEpMIIBJTAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIGQDAzBglghkgB hvhCAQ0EJhYkT3BlblNTTCBHZW5lcmF0ZWQgU2VydmVyIENlcnRpZmljYXRlMB0G A1UdDgQWBBQASym2L5vYZKo9PnqDiSRyOHQ5zDCBiwYDVR0jBIGDMIGAgBSJpW4a 7QM2MkPIdhDrAIEEGc2Rg6FkpGIwYDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNB MREwDwYDVQQKDAhTZWN1cml0eTEbMBkGA1UECwwST3BlblNoaWZ0MyB0ZXN0IENB MRQwEgYDVQQDDAtyb290LmNhLm9yZ4ICEAAwDgYDVR0PAQH/BAQDAgWgMBMGA1Ud JQQMMAoGCCsGAQUFBwMBMA0GCSqGSIb3DQEBCwUAA4ICAQBojUFZQKM8uItkQKcQ oNA7prsl3Kq4bFMzhRgwHRyNigEkd3sYzD6BK1KmuAD3GFq8++RrXY99VZhDll0g q9Ri/3hOuWZfYC/FXWth1/civgKTp1u1OX9W/8ezzXcTqQ1bLROaHHebaRtmhhwf Ltqx/WldLHfEph7+xsUOf0KbpnIR3U5/EPGyIbd6HdPY8q4x83WLQU6zwwSAeAdF kgum2JOdlvmkGTAUE3SHgwWltoem0Se9K/Za9g+N1emaTBdAK22bcwK3ypiiv1V9 6hsSSPwYgDW2LHNQSp0kORZOH4NYrWFbQaofgDelL6pA9yn3d+03ANdxyyURROTe 5uinwTpCoQZRsqcqGUYi0Yg4CYSjBfTAYev8DYAPsrC7oQnDb/0cMlVySCRdsx0t M7zb8gxpIwoGXQHaJJfaGvfpQLy9bg+5nwkhDvstMq6Co5da8YVC6prsWhJnz3rs j24WPpiLJDgfUZ9S1y+4N8enlLFRQ0VwvGySsqYPenuHA9v8LHDV3iVIL0gvKNI7 ymKGlQBFj8kERKljuA7ihAWLwGC2S1wgjUVcDyufV2GoEtzKLXQ6SeuucYsXqWH9 iP3E3dsMBWrtdVjLwFOsglJVTTv8JUkCzl2AOxFpgeorfi1hyBoS5qDBkET6xXhC OyxyJrGdmLclqzBEW1Zv3j5ywA== -----END CERTIFICATE-----` testPrivateKeyWithIntCA = `-----BEGIN RSA PRIVATE KEY----- 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 -----END RSA PRIVATE KEY-----` testExpiredCertificateWithIntCA = `-----BEGIN CERTIFICATE----- MIIGdzCCBF+gAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwaDELMAkGA1UEBhMCVVMx CzAJBgNVBAgMAkNBMREwDwYDVQQKDAhTZWN1cml0eTEbMBkGA1UECwwST3BlblNo aWZ0MyB0ZXN0IENBMRwwGgYDVQQDDBNpbnRlcm1lZGlhdGUuY2Eub3JnMCIYDzE5 OTAwMjI4MTAxMDMwWhgPMjAwMDAyMjcxMDExMTJaMGQxCzAJBgNVBAYTAlVTMQsw CQYDVQQIDAJDQTERMA8GA1UECgwIU2VjdXJpdHkxGzAZBgNVBAsMEk9wZW5TaGlm dDMgdGVzdCBDQTEYMBYGA1UEAwwPZXhwaXJlZC5jYS50ZXN0MIICIjANBgkqhkiG 9w0BAQEFAAOCAg8AMIICCgKCAgEAymVeWMYj4O5H5kYBoza3XdnHXVTtwBpX/nNQ R5fMBtLGzjpYHIKrJSb5cqLrbxvdwVQhyWn1ORBvPVyT5aPocnKeKgcUGeAZDj37 ZcqB7INMIbk1bUZlGvlDHk7u0fxHtFr+pOu6UOyTbmHlQayaJ+7aPqI2zpP3CGM4 EFyyv8wd9nDb3fzMEPhlNLqVWhuUUUlTz3aLULAfOfsU0XPWmW246oLSfDZX4eUp dxPPWQW2L17T+6lMUFdtdS9QH+wZL5ceGyMCxfGKBHz2y7XVLVKEb6u9l7rIIumy /5avsLhhUmHPNJlAmVzmKjZFCJ4rlCdIp0PpT54MysNcdHxyYTRA9An1HWcSI87f t8IGcBBEvpk0g3e5KE9guppwWuUxVh+UoBwux1pFwTbrBMcAVjssy8gAJ42oa/nx CNrm1vFmr/BziDNXEzDDKlbnVLDkggPufpriGIwNbxWNRVLEdP3cq+mZ1MC61xSa u87m0YV2dcxbtyF2eW7O8l8eT4N0bcvAa0UxyQGZJN5TF1rC4FTvQaZ7El/G6Xol V/hi76yO807h1b+aBaf5AJGyJjoVGjehV7Qh4L0oR6klNH+g766+gAvjbMn49mpo d6eh0Nz3BrRa/ur50L9wwp07n64X/BOif1tu2yyk7prWypJ864jRr/L0LCLClB/H uOUArRECAwEAAaOCASkwggElMAkGA1UdEwQCMAAwEQYJYIZIAYb4QgEBBAQDAgZA MDMGCWCGSAGG+EIBDQQmFiRPcGVuU1NMIEdlbmVyYXRlZCBTZXJ2ZXIgQ2VydGlm aWNhdGUwHQYDVR0OBBYEFMb6xBVJB2jTowuspCFkRwOgt2QjMIGLBgNVHSMEgYMw gYCAFImlbhrtAzYyQ8h2EOsAgQQZzZGDoWSkYjBgMQswCQYDVQQGEwJVUzELMAkG A1UECAwCQ0ExETAPBgNVBAoMCFNlY3VyaXR5MRswGQYDVQQLDBJPcGVuU2hpZnQz IHRlc3QgQ0ExFDASBgNVBAMMC3Jvb3QuY2Eub3JnggIQADAOBgNVHQ8BAf8EBAMC BaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggIBAELf51eR qbkdec/xJoGFNy0Z7W4aIzlYBpdakB9lH4RmcIm8oFJJmt4LXfGKAYQ5WuWv8Evj S4qMiMO1Lul/zBzvv8srFJy0+OFqDf/+dVOaZ0AEl4RQ4oT0tw9HGhde4YZICXZ/ nFjI/GmbhBFpZ6ZFRq6lCNG95fldLdFuCzJnpvOnKuzjSjpa6mmFIMvMqpEm9cUb gs/LfBpZU4s7fYufnBUlaon2YLIvYtF5uLyKk+rFqwaakb14Dl8k+BW252sIu9UV iKYul+Ham8r6EMBQ4eeHZVKXGztwg/x+wCRJriWjz9mWZCStlx9NjOV972hoBClf jRA6IiVp7xgb5G0v4kv7tXtjOS1AY7v4k78cHkNytAZDtRNAyFXx5ZU1Tvej9ECS 1iwOlpanjc5Moi2gG9ga4E+DFLnMBVWzuQJGTZt2znuC1JWQgiDBLVVst2xMqSMc A5s8mE+vA3LXVXNoBBpxS33cQQaphUfwuftrymJ6VPs/YASOXyT7m0O8512dsV8G AP0Ju9SYA5ZMeGTUGRRKDM9NBrqfoUJ85SpjeZoHaltURRJPBEkh8ZFyUFNSfdaO orbhEj5JaB5XEsNKST9cP+9e3l2fsrcB7cQspxnRzkJSzhpBWKgQHce0+6l2PVbp +wlvPN8TwYpdQ/skn6pz9kx0V2FQaQFisF+x -----END CERTIFICATE-----` testExpiredCertificateKey = `-----BEGIN RSA PRIVATE KEY----- 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 -----END RSA PRIVATE KEY-----` testFutureValidCertificateWithIntCA = `-----BEGIN CERTIFICATE----- MIIGgTCCBGmgAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwaDELMAkGA1UEBhMCVVMx CzAJBgNVBAgMAkNBMREwDwYDVQQKDAhTZWN1cml0eTEbMBkGA1UECwwST3BlblNo aWZ0MyB0ZXN0IENBMRwwGgYDVQQDDBNpbnRlcm1lZGlhdGUuY2Eub3JnMCAYDzIw MzYwMjI4MTAxMDMwWhcNMzYxMTAzMDAxNzE3WjBwMQswCQYDVQQGEwJVUzELMAkG A1UECAwCQ0ExETAPBgNVBAoMCFNlY3VyaXR5MRswGQYDVQQLDBJPcGVuU2hpZnQz IHRlc3QgQ0ExJDAiBgNVBAMMG3ZhbGlkLmluLnRoZS5mdXR1cmUuY2EudGVzdDCC AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAN6DzbjCo4EvQ9NKIBCMZXAb 0OnhLkDJa5P4O4sjRuOFAbl/e6SZ05olK7uNgbuis5aebzKC8nb+UuS4b8GXTWkL TS5sbGUsrIZ6PDCA+cvEj4ZwYPjqNCurimLNyQYyroNy+pRxtkSfV+9TS7zndRxo aWZECQ4ApXageNu7Afg9M9/ainQR0w5TyJ2kKB6O0+0dF/7re30tD7FX+wHfN6/z owbM5qGEPcFINGYZPik8ZGkVsv98BFI3MTHjlgQ5a44Rmg3jVhdCuI2sy41pm2pM 2x1pUGqj6UjxbwXq7yKOle0W6dni3TpR57Pq5/jfpsMITGtYM++J/i2LxjTTsIpI 9Qe6gHRapYA8Ab1ro9QHgAe6LVUt39ki7O6EVGBq08405tnna5uvDm3/Bl7qYq6O erhRKATRyj/Vf1PJ7823NvOgQzvwx6w6c2kJJQIPcYppUfsUpYgIRQuy8759jAMA RESXQfCK/W6ub1P0dYSKBejf5cf1QhrVfxqkun222qyHk9PDNt/FTzG9V/Y9w4y8 uTnUWXHDLVHHtrOCyLEZLsdaZbZnt7g1Q+zuaJ/0CTnkMsksroLfZLwbuPJdRezR z8MbgLodjDgwKh8RpXdXPdIanP0SgZsTjpGlAYUr/GA4l9x/lf8GfG6KTRMC9dKi jIpB5MNxkYrkP2NuFdvlAgMBAAGjggEpMIIBJTAJBgNVHRMEAjAAMBEGCWCGSAGG +EIBAQQEAwIGQDAzBglghkgBhvhCAQ0EJhYkT3BlblNTTCBHZW5lcmF0ZWQgU2Vy dmVyIENlcnRpZmljYXRlMB0GA1UdDgQWBBQ9aWYDwIp0t7yQTTyfA77g5OcRtDCB iwYDVR0jBIGDMIGAgBSJpW4a7QM2MkPIdhDrAIEEGc2Rg6FkpGIwYDELMAkGA1UE BhMCVVMxCzAJBgNVBAgMAkNBMREwDwYDVQQKDAhTZWN1cml0eTEbMBkGA1UECwwS T3BlblNoaWZ0MyB0ZXN0IENBMRQwEgYDVQQDDAtyb290LmNhLm9yZ4ICEAAwDgYD VR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA0GCSqGSIb3DQEBCwUA A4ICAQAtneFpJw97r8GkNK5oY86PKStfj9e1W8v3EfHc9YkhkZ7qDKXvSuY0UC0T abhhgL2IDF3zmnH71RY+WMNmDCbJWZoOe2NXjo3TxG38fLqk9C2ayi860TasPQNM rcZ0E+FiDxm582wrmBdD+GpgrNlwiQ2Z5U897IDZv7LiPI7rSYF3OvI/xxz2Q7ZT VDJBH22Fg7UY3JqVRMU/4ff3jiWuelbepSyk7LqxYQuAcBR2nTA/8UGw1YplESm0 YWEHwE8GykJB5LVXQsVNo/MlEU3vwa5YnseFWdtkg3JKyK9dv6QE3LAnbw0kwx5R HUBXN0N57aODaQbx1amSHqAmNnpZtfoZfJhdZR0RVvUeIv7D9HjIpJio+pEcNJwY xyVVqbD/tYc4tUFeAtHl9jM1Ob2p/nHj/yOjCy3GTY/eUPNLgGs0DX4aFo4WTDdd GKEd0EKjqXLFYFHUWuNAh2+0J7xAXR8oP7sOdg5DiclCZMT874YOlS5Ps6E/PnvR sgOg6zar/gx5Rp8ext2NVkXgTww2fzVgf0+FF1GrhjdugsGLjyqfFEspZ85Yrkdo hYnY5k0G+POAuJKmPgUd7W1QltLnRRvsFyEse+qkTj7cxj4ZwsJ8YJuM8yO5/+ol XzV329s9fh8ILFaY4196hzqNsEX5ZHYxc/AtcoMMniDPATyK1w== -----END CERTIFICATE-----` testFutureValidCertificateKey = `-----BEGIN RSA PRIVATE KEY----- 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 -----END RSA PRIVATE KEY-----` testInvalidCANoCert1 = `-----BEGIN CERTIFICATE REQUEST----- MIICnTCCAYUCAQAwWDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMREwDwYDVQQK DAhTZWN1cml0eTETMBEGA1UECwwKT3BlblNoaWZ0MzEUMBIGA1UEAwwLcm91dGVy LnRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDS7tHwWAJ0PBuU u8RJ5i98FoDmXgaL0uiLR+n46FACiRW0tKA0WvXX9afSFSa5nb+Z9GHxMBsIe1lu noM+k2lBScW8PnGTW5mzkEHVzGb9zmM8lSE6gcRjZwPPre3bnWnemXU1Loa6IV+W p9w8x/SqlZAlS+Vab+5opC8dSXM4OG1qIb0JqPrXPx8e7RaLr53fmbEm3iIT/wjk GWfQFAUToswERt2Jx5Ojri5qe+VDwlfOXt6GjWDPJsYroufDXxWmboZZtYxsVZnY xWgnwHVaHaTdbogafXWWyfLhSdNpjUX9bnXWSh+VR5m7SxjgjqqYK8EpqNyxay+E mBdaVgWPAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAQEAnVnDhysDJY3MPqIYYXwE Yg9pkV4j5MStP2sSR+oWgqBP1BGZn2yaK2Bb8jGeBw53uuH0S+NifnVVXi1Q7rmV P8SLmCRvWDbeRgQC4fWgrzEkB8kePTGuvZM6/wLTiw3i1AxcG8Z8aDVNRrJq0im5 dAz9X4YF0m9ZweqB9LeYd/UXbI2ZMHBkOgY08Co1X7+DpfohzCOflix1vjuygViR 1MXW8UIYFktyyhSeL7eshW0BhqfMoku+btO4LZ/IZHDZsF3gd5NOPoNX28m0E74y xhfvmedJE9ck2tEbxQk8BcdCXCN4HFePO8gpCYeC7r309E/QwFjU9+xw6qrpW5uP GA== -----END CERTIFICATE REQUEST-----` testInvalidCANoCert2 = testSelfSignedKey testInvalidCAMalformedCert = `-----BEGIN CERTIFICATE----- MIIDjTCCAnWgAwIBAgIJAKM4rr3VRQARMA0GCSqGSIb3DQEBCwUAMF0xCzAJBgNV The+rest+of+the+certificate+info+is+invalid+and+badly+malformed/ 0A== -----END CERTIFICATE-----` ) func createRouteSpecTo(name string, kind string) api.RouteTargetReference { svc := api.RouteTargetReference{ Name: name, Kind: kind, } return svc } // TestValidateRouteBad ensures not specifying a required field results in error and a fully specified // route passes successfully func TestValidateRoute(t *testing.T) { tests := []struct { name string route *api.Route expectedErrors int }{ { name: "No Name", route: &api.Route{ ObjectMeta: kapi.ObjectMeta{ Namespace: "foo", }, Spec: api.RouteSpec{ Host: "host", To: createRouteSpecTo("serviceName", "Service"), }, }, expectedErrors: 1, }, { name: "No namespace", route: &api.Route{ ObjectMeta: kapi.ObjectMeta{ Name: "name", }, Spec: api.RouteSpec{ Host: "host", To: createRouteSpecTo("serviceName", "Service"), }, }, expectedErrors: 1, }, { name: "No host", route: &api.Route{ ObjectMeta: kapi.ObjectMeta{ Name: "name", Namespace: "foo", }, Spec: api.RouteSpec{ To: createRouteSpecTo("serviceName", "Service"), }, }, expectedErrors: 0, }, { name: "Invalid DNS 952 host", route: &api.Route{ ObjectMeta: kapi.ObjectMeta{ Name: "name", Namespace: "foo", }, Spec: api.RouteSpec{ Host: "**", To: createRouteSpecTo("serviceName", "Service"), }, }, expectedErrors: 1, }, { name: "No service name", route: &api.Route{ ObjectMeta: kapi.ObjectMeta{ Name: "name", Namespace: "foo", }, Spec: api.RouteSpec{ Host: "host", To: createRouteSpecTo("", "Service"), }, }, expectedErrors: 1, }, { name: "No service kind", route: &api.Route{ ObjectMeta: kapi.ObjectMeta{ Name: "name", Namespace: "foo", }, Spec: api.RouteSpec{ Host: "host", To: createRouteSpecTo("serviceName", ""), }, }, expectedErrors: 1, }, { name: "Zero port", route: &api.Route{ ObjectMeta: kapi.ObjectMeta{ Name: "name", Namespace: "foo", }, Spec: api.RouteSpec{ Host: "www.example.com", To: createRouteSpecTo("serviceName", "Service"), Port: &api.RoutePort{ TargetPort: intstr.FromInt(0), }, }, }, expectedErrors: 1, }, { name: "Empty string port", route: &api.Route{ ObjectMeta: kapi.ObjectMeta{ Name: "name", Namespace: "foo", }, Spec: api.RouteSpec{ Host: "www.example.com", To: createRouteSpecTo("serviceName", "Service"), Port: &api.RoutePort{ TargetPort: intstr.FromString(""), }, }, }, expectedErrors: 1, }, { name: "Valid route", route: &api.Route{ ObjectMeta: kapi.ObjectMeta{ Name: "name", Namespace: "foo", }, Spec: api.RouteSpec{ Host: "www.example.com", To: createRouteSpecTo("serviceName", "Service"), }, }, expectedErrors: 0, }, { name: "Valid route with path", route: &api.Route{ ObjectMeta: kapi.ObjectMeta{ Name: "name", Namespace: "foo", }, Spec: api.RouteSpec{ Host: "www.example.com", To: createRouteSpecTo("serviceName", "Service"), Path: "/test", }, }, expectedErrors: 0, }, { name: "Invalid route with path", route: &api.Route{ ObjectMeta: kapi.ObjectMeta{ Name: "name", Namespace: "foo", }, Spec: api.RouteSpec{ Host: "www.example.com", To: createRouteSpecTo("serviceName", "Service"), Path: "test", }, }, expectedErrors: 1, }, { name: "Passthrough route with path", route: &api.Route{ ObjectMeta: kapi.ObjectMeta{ Name: "name", Namespace: "foo", }, Spec: api.RouteSpec{ Host: "www.example.com", Path: "/test", To: createRouteSpecTo("serviceName", "Service"), TLS: &api.TLSConfig{ Termination: api.TLSTerminationPassthrough, }, }, }, expectedErrors: 1, }, { name: "No wildcard policy", route: &api.Route{ ObjectMeta: kapi.ObjectMeta{ Name: "nowildcard", Namespace: "foo", }, Spec: api.RouteSpec{ Host: "no.wildcard.test", To: createRouteSpecTo("serviceName", "Service"), }, }, expectedErrors: 0, }, { name: "wildcard policy none", route: &api.Route{ ObjectMeta: kapi.ObjectMeta{ Name: "nowildcard2", Namespace: "foo", }, Spec: api.RouteSpec{ Host: "none.wildcard.test", To: createRouteSpecTo("serviceName", "Service"), WildcardPolicy: api.WildcardPolicyNone, }, }, expectedErrors: 0, }, { name: "wildcard policy subdomain", route: &api.Route{ ObjectMeta: kapi.ObjectMeta{ Name: "wildcardpolicy", Namespace: "foo", }, Spec: api.RouteSpec{ Host: "subdomain.wildcard.test", To: createRouteSpecTo("serviceName", "Service"), WildcardPolicy: api.WildcardPolicySubdomain, }, }, expectedErrors: 0, }, { name: "Invalid wildcard policy", route: &api.Route{ ObjectMeta: kapi.ObjectMeta{ Name: "badwildcard", Namespace: "foo", }, Spec: api.RouteSpec{ Host: "bad.wildcard.test", To: createRouteSpecTo("serviceName", "Service"), WildcardPolicy: "bad-wolf", }, }, expectedErrors: 1, }, { name: "Invalid host for wildcard policy", route: &api.Route{ ObjectMeta: kapi.ObjectMeta{ Name: "badhost", Namespace: "foo", }, Spec: api.RouteSpec{ To: createRouteSpecTo("serviceName", "Service"), WildcardPolicy: api.WildcardPolicySubdomain, }, }, expectedErrors: 1, }, { name: "Empty host for wildcard policy", route: &api.Route{ ObjectMeta: kapi.ObjectMeta{ Name: "emptyhost", Namespace: "foo", }, Spec: api.RouteSpec{ Host: "", To: createRouteSpecTo("serviceName", "Service"), WildcardPolicy: api.WildcardPolicySubdomain, }, }, expectedErrors: 1, }, } for _, tc := range tests { errs := ValidateRoute(tc.route) if len(errs) != tc.expectedErrors { t.Errorf("Test case %s expected %d error(s), got %d. %v", tc.name, tc.expectedErrors, len(errs), errs) } } } func TestValidateTLS(t *testing.T) { tests := []struct { name string route *api.Route expectedErrors int }{ { name: "No TLS Termination", route: &api.Route{ Spec: api.RouteSpec{ TLS: &api.TLSConfig{ Termination: "", }, }, }, expectedErrors: 1, }, { name: "Passthrough termination OK", route: &api.Route{ Spec: api.RouteSpec{ TLS: &api.TLSConfig{ Termination: api.TLSTerminationPassthrough, }, }, }, expectedErrors: 0, }, { name: "Reencrypt termination OK with certs", route: &api.Route{ Spec: api.RouteSpec{ TLS: &api.TLSConfig{ Termination: api.TLSTerminationReencrypt, Certificate: "def", Key: "ghi", CACertificate: "jkl", DestinationCACertificate: "abc", }, }, }, expectedErrors: 0, }, { name: "Reencrypt termination OK without certs", route: &api.Route{ Spec: api.RouteSpec{ TLS: &api.TLSConfig{ Termination: api.TLSTerminationReencrypt, DestinationCACertificate: "abc", }, }, }, expectedErrors: 0, }, { name: "Reencrypt termination no dest cert", route: &api.Route{ Spec: api.RouteSpec{ TLS: &api.TLSConfig{ Termination: api.TLSTerminationReencrypt, Certificate: "def", Key: "ghi", CACertificate: "jkl", }, }, }, expectedErrors: 1, }, { name: "Edge termination OK with certs", route: &api.Route{ Spec: api.RouteSpec{ TLS: &api.TLSConfig{ Termination: api.TLSTerminationEdge, Certificate: "abc", Key: "abc", CACertificate: "abc", }, }, }, expectedErrors: 0, }, { name: "Edge termination OK without certs", route: &api.Route{ Spec: api.RouteSpec{ TLS: &api.TLSConfig{ Termination: api.TLSTerminationEdge, }, }, }, expectedErrors: 0, }, { name: "Edge termination, dest cert", route: &api.Route{ Spec: api.RouteSpec{ TLS: &api.TLSConfig{ Termination: api.TLSTerminationEdge, DestinationCACertificate: "abc", }, }, }, expectedErrors: 1, }, { name: "Passthrough termination, cert", route: &api.Route{ Spec: api.RouteSpec{ TLS: &api.TLSConfig{Termination: api.TLSTerminationPassthrough, Certificate: "test"}, }, }, expectedErrors: 1, }, { name: "Passthrough termination, key", route: &api.Route{ Spec: api.RouteSpec{ TLS: &api.TLSConfig{Termination: api.TLSTerminationPassthrough, Key: "test"}, }, }, expectedErrors: 1, }, { name: "Passthrough termination, ca cert", route: &api.Route{ Spec: api.RouteSpec{ TLS: &api.TLSConfig{Termination: api.TLSTerminationPassthrough, CACertificate: "test"}, }, }, expectedErrors: 1, }, { name: "Passthrough termination, dest ca cert", route: &api.Route{ Spec: api.RouteSpec{ TLS: &api.TLSConfig{Termination: api.TLSTerminationPassthrough, DestinationCACertificate: "test"}, }, }, expectedErrors: 1, }, { name: "Invalid termination type", route: &api.Route{ Spec: api.RouteSpec{ TLS: &api.TLSConfig{ Termination: "invalid", }, }, }, expectedErrors: 1, }, } for _, tc := range tests { errs := validateTLS(tc.route, nil) if len(errs) != tc.expectedErrors { t.Errorf("Test case %s expected %d error(s), got %d. %v", tc.name, tc.expectedErrors, len(errs), errs) } } } func TestValidatePassthroughInsecureEdgeTerminationPolicy(t *testing.T) { insecureTypes := map[api.InsecureEdgeTerminationPolicyType]bool{ "": false, api.InsecureEdgeTerminationPolicyNone: false, api.InsecureEdgeTerminationPolicyAllow: true, api.InsecureEdgeTerminationPolicyRedirect: false, "support HTTPsec": true, "or maybe HSTS": true, } for key, expected := range insecureTypes { route := &api.Route{ Spec: api.RouteSpec{ TLS: &api.TLSConfig{ Termination: api.TLSTerminationPassthrough, InsecureEdgeTerminationPolicy: key, }, }, } route.Spec.TLS.InsecureEdgeTerminationPolicy = key errs := validateTLS(route, nil) if !expected && len(errs) != 0 { t.Errorf("Test case for Passthrough termination with insecure=%s got %d errors where none where expected. %v", key, len(errs), errs) } if expected && len(errs) == 0 { t.Errorf("Test case for Passthrough termination with insecure=%s got no errors where some where expected.", key) } } } // TestValidateRouteBad ensures not specifying a required field results in error and a fully specified // route passes successfully func TestValidateRouteUpdate(t *testing.T) { tests := []struct { name string route *api.Route change func(route *api.Route) expectedErrors int }{ { route: &api.Route{ ObjectMeta: kapi.ObjectMeta{ Name: "bar", Namespace: "foo", ResourceVersion: "1", }, Spec: api.RouteSpec{ Host: "host", To: api.RouteTargetReference{ Name: "serviceName", Kind: "Service", }, }, }, change: func(route *api.Route) { route.Spec.Host = "" }, expectedErrors: 1, }, { route: &api.Route{ ObjectMeta: kapi.ObjectMeta{ Name: "bar", Namespace: "foo", ResourceVersion: "1", }, Spec: api.RouteSpec{ Host: "host", To: api.RouteTargetReference{ Name: "serviceName", Kind: "Service", }, }, }, change: func(route *api.Route) { route.Spec.Host = "other" }, expectedErrors: 1, }, { route: &api.Route{ ObjectMeta: kapi.ObjectMeta{ Name: "bar", Namespace: "foo", ResourceVersion: "1", }, Spec: api.RouteSpec{ Host: "host", To: api.RouteTargetReference{ Name: "serviceName", Kind: "Service", }, }, }, change: func(route *api.Route) { route.Name = "baz" }, expectedErrors: 1, }, } for i, tc := range tests { copied, err := kapi.Scheme.Copy(tc.route) if err != nil { t.Fatal(err) } newRoute := copied.(*api.Route) tc.change(newRoute) errs := ValidateRouteUpdate(newRoute, tc.route) if len(errs) != tc.expectedErrors { t.Errorf("%d: expected %d error(s), got %d. %v", i, tc.expectedErrors, len(errs), errs) } } } func TestValidateInsecureEdgeTerminationPolicy(t *testing.T) { tests := []struct { name string insecure api.InsecureEdgeTerminationPolicyType expectedErrors int }{ { name: "empty insecure option", insecure: "", expectedErrors: 0, }, { name: "foobar insecure option", insecure: "foobar", expectedErrors: 1, }, { name: "insecure option none", insecure: api.InsecureEdgeTerminationPolicyNone, expectedErrors: 0, }, { name: "insecure option allow", insecure: api.InsecureEdgeTerminationPolicyAllow, expectedErrors: 0, }, { name: "insecure option redirect", insecure: api.InsecureEdgeTerminationPolicyRedirect, expectedErrors: 0, }, { name: "insecure option other", insecure: "something else", expectedErrors: 1, }, } for _, tc := range tests { route := &api.Route{ Spec: api.RouteSpec{ TLS: &api.TLSConfig{ Termination: api.TLSTerminationEdge, InsecureEdgeTerminationPolicy: tc.insecure, }, }, } errs := validateTLS(route, nil) if len(errs) != tc.expectedErrors { t.Errorf("Test case %s expected %d error(s), got %d. %v", tc.name, tc.expectedErrors, len(errs), errs) } } } func TestValidateEdgeReencryptInsecureEdgeTerminationPolicy(t *testing.T) { tests := []struct { name string route *api.Route }{ { name: "Reencrypt termination", route: &api.Route{ Spec: api.RouteSpec{ TLS: &api.TLSConfig{ Termination: api.TLSTerminationReencrypt, DestinationCACertificate: "dca", }, }, }, }, { name: "Reencrypt termination DestCACert", route: &api.Route{ Spec: api.RouteSpec{ TLS: &api.TLSConfig{ Termination: api.TLSTerminationReencrypt, DestinationCACertificate: testDestinationCACertificate, }, }, }, }, { name: "Edge termination", route: &api.Route{ Spec: api.RouteSpec{ TLS: &api.TLSConfig{ Termination: api.TLSTerminationEdge, }, }, }, }, } insecureTypes := map[api.InsecureEdgeTerminationPolicyType]bool{ api.InsecureEdgeTerminationPolicyNone: false, api.InsecureEdgeTerminationPolicyAllow: false, api.InsecureEdgeTerminationPolicyRedirect: false, "support HTTPsec": true, "or maybe HSTS": true, } for _, tc := range tests { for key, expected := range insecureTypes { tc.route.Spec.TLS.InsecureEdgeTerminationPolicy = key errs := validateTLS(tc.route, nil) if !expected && len(errs) != 0 { t.Errorf("Test case %s with insecure=%s got %d errors where none were expected. %v", tc.name, key, len(errs), errs) } if expected && len(errs) == 0 { t.Errorf("Test case %s with insecure=%s got no errors where some were expected.", tc.name, key) } } } } // TestExtendedValidateRoute ensures that a route's certificate and keys // are valid. func TestExtendedValidateRoute(t *testing.T) { tests := []struct { name string route *api.Route expectedErrors int }{ { name: "No TLS Termination", route: &api.Route{ Spec: api.RouteSpec{ TLS: &api.TLSConfig{ Termination: "", }, }, }, expectedErrors: 1, }, { name: "Passthrough termination OK", route: &api.Route{ Spec: api.RouteSpec{ TLS: &api.TLSConfig{ Termination: api.TLSTerminationPassthrough, }, }, }, expectedErrors: 0, }, { name: "Reencrypt termination OK with certs", route: &api.Route{ Spec: api.RouteSpec{ Host: "www.example.com", TLS: &api.TLSConfig{ Termination: api.TLSTerminationReencrypt, Certificate: testCertificate, Key: testPrivateKey, CACertificate: testCACertificate, DestinationCACertificate: testDestinationCACertificate, }, }, }, expectedErrors: 0, }, { name: "Reencrypt termination OK with bad config", route: &api.Route{ Spec: api.RouteSpec{ TLS: &api.TLSConfig{ Termination: api.TLSTerminationReencrypt, Certificate: "def", Key: "ghi", CACertificate: "jkl", DestinationCACertificate: "abc", }, }, }, expectedErrors: 4, }, { name: "Reencrypt termination OK without certs", route: &api.Route{ Spec: api.RouteSpec{ TLS: &api.TLSConfig{ Termination: api.TLSTerminationReencrypt, DestinationCACertificate: testDestinationCACertificate, }, }, }, expectedErrors: 0, }, { name: "Reencrypt termination bad config without certs", route: &api.Route{ Spec: api.RouteSpec{ TLS: &api.TLSConfig{ Termination: api.TLSTerminationReencrypt, DestinationCACertificate: "abc", }, }, }, expectedErrors: 1, }, { name: "Reencrypt termination no dest cert", route: &api.Route{ Spec: api.RouteSpec{ Host: "www.example.com", TLS: &api.TLSConfig{ Termination: api.TLSTerminationReencrypt, Certificate: testCertificate, Key: testPrivateKey, CACertificate: testCACertificate, }, }, }, expectedErrors: 1, }, { name: "Edge termination OK with certs without host", route: &api.Route{ Spec: api.RouteSpec{ TLS: &api.TLSConfig{ Termination: api.TLSTerminationEdge, Certificate: testCertificate, Key: testPrivateKey, CACertificate: testCACertificate, }, }, }, expectedErrors: 0, }, { name: "Edge termination OK with certs", route: &api.Route{ Spec: api.RouteSpec{ Host: "www.example.com", TLS: &api.TLSConfig{ Termination: api.TLSTerminationEdge, Certificate: testCertificate, Key: testPrivateKey, CACertificate: testCACertificate, }, }, }, expectedErrors: 0, }, { name: "Edge termination bad config with certs", route: &api.Route{ Spec: api.RouteSpec{ Host: "www.example.com", TLS: &api.TLSConfig{ Termination: api.TLSTerminationEdge, Certificate: "abc", Key: "abc", CACertificate: "abc", }, }, }, expectedErrors: 3, }, { name: "Edge termination mismatched key and cert", route: &api.Route{ Spec: api.RouteSpec{ Host: "www.example.com", TLS: &api.TLSConfig{ Termination: api.TLSTerminationEdge, Certificate: testCertificate, Key: testExpiredCertPrivateKey, CACertificate: testCACertificate, }, }, }, expectedErrors: 1, }, { name: "Edge termination expired cert unknown CA", route: &api.Route{ Spec: api.RouteSpec{ Host: "www.example.com", TLS: &api.TLSConfig{ Termination: api.TLSTerminationEdge, Certificate: testExpiredCAUnknownCertificate, Key: testExpiredCertPrivateKey, }, }, }, expectedErrors: 0, }, { name: "Edge termination expired cert mismatched CA", route: &api.Route{ Spec: api.RouteSpec{ Host: "www.example.com", TLS: &api.TLSConfig{ Termination: api.TLSTerminationEdge, Certificate: testExpiredCAUnknownCertificate, Key: testExpiredCertPrivateKey, CACertificate: testCACertificate, }, }, }, expectedErrors: 1, }, { name: "Edge termination expired cert key mismatch", route: &api.Route{ Spec: api.RouteSpec{ Host: "www.example.com", TLS: &api.TLSConfig{ Termination: api.TLSTerminationEdge, Certificate: testExpiredCAUnknownCertificate, Key: testPrivateKey, CACertificate: testCACertificate, }, }, }, expectedErrors: 2, }, { name: "Edge termination OK without certs", route: &api.Route{ Spec: api.RouteSpec{ TLS: &api.TLSConfig{ Termination: api.TLSTerminationEdge, }, }, }, expectedErrors: 0, }, { name: "Edge termination, dest cert", route: &api.Route{ Spec: api.RouteSpec{ TLS: &api.TLSConfig{ Termination: api.TLSTerminationEdge, DestinationCACertificate: "abc", }, }, }, expectedErrors: 2, }, { name: "Passthrough termination, cert", route: &api.Route{ Spec: api.RouteSpec{ TLS: &api.TLSConfig{Termination: api.TLSTerminationPassthrough, Certificate: "test"}, }, }, expectedErrors: 3, }, { name: "Passthrough termination, key", route: &api.Route{ Spec: api.RouteSpec{ TLS: &api.TLSConfig{Termination: api.TLSTerminationPassthrough, Key: "test"}, }, }, expectedErrors: 1, }, { name: "Passthrough termination, ca cert", route: &api.Route{ Spec: api.RouteSpec{ TLS: &api.TLSConfig{Termination: api.TLSTerminationPassthrough, CACertificate: "test"}, }, }, expectedErrors: 2, }, { name: "Passthrough termination, dest ca cert", route: &api.Route{ Spec: api.RouteSpec{ TLS: &api.TLSConfig{Termination: api.TLSTerminationPassthrough, DestinationCACertificate: "test"}, }, }, expectedErrors: 2, }, { name: "Invalid termination type", route: &api.Route{ Spec: api.RouteSpec{ TLS: &api.TLSConfig{ Termination: "invalid", }, }, }, expectedErrors: 1, }, { name: "Double escaped newlines", route: &api.Route{ Spec: api.RouteSpec{ TLS: &api.TLSConfig{ Termination: api.TLSTerminationReencrypt, Certificate: "d\\nef", Key: "g\\nhi", CACertificate: "j\\nkl", DestinationCACertificate: "j\\nkl", }, }, }, expectedErrors: 4, }, { name: "example cert", route: &api.Route{ Spec: api.RouteSpec{ Host: "www.example.com", TLS: &api.TLSConfig{ Termination: api.TLSTerminationEdge, Certificate: testCertificate, Key: testPrivateKey, CACertificate: testCACertificate, }, }, }, expectedErrors: 0, }, { name: "Expired cert", route: &api.Route{ Spec: api.RouteSpec{ Host: "www.example.com", TLS: &api.TLSConfig{ Termination: api.TLSTerminationEdge, Certificate: testCertificate, Key: testPrivateKey, CACertificate: testCACertificate, }, }, }, expectedErrors: 0, }, { name: "Expired cert reencrypt", route: &api.Route{ Spec: api.RouteSpec{ Host: "www.example.com", TLS: &api.TLSConfig{ Termination: api.TLSTerminationReencrypt, Certificate: testCertificate, Key: testPrivateKey, CACertificate: testCACertificate, DestinationCACertificate: testCACertificate, }, }, }, expectedErrors: 0, }, { name: "Expired cert invalid key", route: &api.Route{ Spec: api.RouteSpec{ Host: "www.example.com", TLS: &api.TLSConfig{ Termination: api.TLSTerminationEdge, Certificate: testExpiredCertNoKey, }, }, }, expectedErrors: 1, }, { name: "Expired cert mismatched key", route: &api.Route{ Spec: api.RouteSpec{ Host: "www.example.com", TLS: &api.TLSConfig{ Termination: api.TLSTerminationEdge, Certificate: testExpiredCertNoKey, Key: testPrivateKey, }, }, }, expectedErrors: 1, }, { name: "Expired cert invalid key reencrypt", route: &api.Route{ Spec: api.RouteSpec{ Host: "www.example.com", TLS: &api.TLSConfig{ Termination: api.TLSTerminationReencrypt, Certificate: testExpiredCertNoKey, DestinationCACertificate: testExpiredCertNoKey, }, }, }, expectedErrors: 1, }, { name: "Expired cert with a different route host", route: &api.Route{ Spec: api.RouteSpec{ Host: "think.different.test", TLS: &api.TLSConfig{ Termination: api.TLSTerminationEdge, Certificate: testCertificate, Key: testPrivateKey, CACertificate: testCACertificate, }, }, }, expectedErrors: 0, }, { name: "self-signed cert", route: &api.Route{ Spec: api.RouteSpec{ Host: "self.signer.test", TLS: &api.TLSConfig{ Termination: api.TLSTerminationReencrypt, Certificate: testSelfSignedCert, Key: testSelfSignedKey, DestinationCACertificate: testSelfSignedCert, }, }, }, expectedErrors: 0, }, { name: "self-signed cert with different host", route: &api.Route{ Spec: api.RouteSpec{ Host: "different.co.us", TLS: &api.TLSConfig{ Termination: api.TLSTerminationEdge, Certificate: testSelfSignedCert, Key: testSelfSignedKey, }, }, }, expectedErrors: 0, }, { name: "future validity date 2038 cert", route: &api.Route{ Spec: api.RouteSpec{ Host: "self.signer.test", TLS: &api.TLSConfig{ Termination: api.TLSTerminationEdge, Certificate: testValidInFutureCert, Key: testValidInFutureKey, }, }, }, expectedErrors: 0, }, { name: "future validity date 2038 cert with different host", route: &api.Route{ Spec: api.RouteSpec{ Host: "www.in.the.future.test", TLS: &api.TLSConfig{ Termination: api.TLSTerminationEdge, Certificate: testValidInFutureCert, Key: testValidInFutureKey, }, }, }, expectedErrors: 0, }, { name: "cert with intermediate CA", route: &api.Route{ Spec: api.RouteSpec{ Host: "www.ca.test", TLS: &api.TLSConfig{ Termination: api.TLSTerminationEdge, Certificate: testCertificateWithIntCA, Key: testPrivateKeyWithIntCA, CACertificate: testIntCACertificateChain, }, }, }, expectedErrors: 0, }, { name: "cert with intermediate CA and diff host", route: &api.Route{ Spec: api.RouteSpec{ Host: "different.ca.test", TLS: &api.TLSConfig{ Termination: api.TLSTerminationEdge, Certificate: testCertificateWithIntCA, Key: testPrivateKeyWithIntCA, CACertificate: testIntCACertificateChain, }, }, }, expectedErrors: 0, }, { name: "expired cert with intermediate CA", route: &api.Route{ Spec: api.RouteSpec{ Host: "expired.ca.test", TLS: &api.TLSConfig{ Termination: api.TLSTerminationEdge, Certificate: testExpiredCertificateWithIntCA, Key: testExpiredCertificateKey, CACertificate: testIntCACertificateChain, }, }, }, expectedErrors: 0, }, { name: "expired cert with intermediate CA and diff host", route: &api.Route{ Spec: api.RouteSpec{ Host: "still.expired.test", TLS: &api.TLSConfig{ Termination: api.TLSTerminationEdge, Certificate: testExpiredCertificateWithIntCA, Key: testExpiredCertificateKey, CACertificate: testIntCACertificateChain, }, }, }, expectedErrors: 0, }, { name: "future valid cert with intermediate CA", route: &api.Route{ Spec: api.RouteSpec{ Host: "valid.in.the.future.ca.test", TLS: &api.TLSConfig{ Termination: api.TLSTerminationEdge, Certificate: testFutureValidCertificateWithIntCA, Key: testFutureValidCertificateKey, CACertificate: testIntCACertificateChain, }, }, }, expectedErrors: 0, }, { name: "future valid cert with intermediate CA and diff host", route: &api.Route{ Spec: api.RouteSpec{ Host: "future.valid.test", TLS: &api.TLSConfig{ Termination: api.TLSTerminationEdge, Certificate: testFutureValidCertificateWithIntCA, Key: testFutureValidCertificateKey, CACertificate: testIntCACertificateChain, }, }, }, expectedErrors: 0, }, { name: "invalid CA with csr", route: &api.Route{ Spec: api.RouteSpec{ Host: "invalid.ca.test", TLS: &api.TLSConfig{ Termination: api.TLSTerminationEdge, Certificate: testCertificate, Key: testPrivateKey, CACertificate: testInvalidCANoCert1, }, }, }, expectedErrors: 2, }, { name: "another invalid CA with private key", route: &api.Route{ Spec: api.RouteSpec{ Host: "another.invalid.ca.test", TLS: &api.TLSConfig{ Termination: api.TLSTerminationEdge, Certificate: testCertificate, Key: testPrivateKey, CACertificate: testInvalidCANoCert2, }, }, }, expectedErrors: 2, }, { name: "invalid CA malformed certificate", route: &api.Route{ Spec: api.RouteSpec{ Host: "malformed.ca.test", TLS: &api.TLSConfig{ Termination: api.TLSTerminationEdge, Certificate: testCertificate, Key: testPrivateKey, CACertificate: testInvalidCAMalformedCert, }, }, }, expectedErrors: 2, }, { name: "invalid destination CA with csr", route: &api.Route{ Spec: api.RouteSpec{ Host: "csr.destination.ca", TLS: &api.TLSConfig{ Termination: api.TLSTerminationReencrypt, Certificate: testSelfSignedCert, Key: testSelfSignedKey, DestinationCACertificate: testInvalidCANoCert1, }, }, }, expectedErrors: 1, }, { name: "invalid destination CA with private key", route: &api.Route{ Spec: api.RouteSpec{ Host: "key.destination.ca", TLS: &api.TLSConfig{ Termination: api.TLSTerminationReencrypt, Certificate: testSelfSignedCert, Key: testSelfSignedKey, DestinationCACertificate: testInvalidCANoCert1, }, }, }, expectedErrors: 1, }, { name: "malformed destination CA", route: &api.Route{ Spec: api.RouteSpec{ Host: "malformed.destination.ca", TLS: &api.TLSConfig{ Termination: api.TLSTerminationReencrypt, Certificate: testSelfSignedCert, Key: testSelfSignedKey, DestinationCACertificate: testInvalidCAMalformedCert, }, }, }, expectedErrors: 1, }, } for _, tc := range tests { errs := ExtendedValidateRoute(tc.route) if len(errs) != tc.expectedErrors { t.Errorf("Test case %s expected %d error(s), got %d. %v", tc.name, tc.expectedErrors, len(errs), errs) } } } // TestValidateHostName checks that a route's host name matches DNS requirements. func TestValidateHostName(t *testing.T) { tests := []struct { name string route *api.Route expectedErrors bool }{ { name: "valid-host-name", route: &api.Route{ Spec: api.RouteSpec{ Host: "www.example.test", }, }, expectedErrors: false, }, { name: "invalid-host-name", route: &api.Route{ Spec: api.RouteSpec{ Host: "name-namespace-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890.example.test", }, }, expectedErrors: true, }, { name: "valid-host-63-chars-label", route: &api.Route{ Spec: api.RouteSpec{ Host: "name-namespace-1234567890-1234567890-1234567890-1234567890-1234.example.test", }, }, expectedErrors: false, }, { name: "invalid-host-64-chars-label", route: &api.Route{ Spec: api.RouteSpec{ Host: "name-namespace-1234567890-1234567890-1234567890-1234567890-12345.example.test", }, }, expectedErrors: true, }, { name: "valid-name-253-chars", route: &api.Route{ Spec: api.RouteSpec{ Host: "name-namespace.a1234567890.b1234567890.c1234567890.d1234567890.e1234567890.f1234567890.g1234567890.h1234567890.i1234567890.j1234567890.k1234567890.l1234567890.m1234567890.n1234567890.o1234567890.p1234567890.q1234567890.r1234567890.s12345678.example.test", }, }, expectedErrors: false, }, { name: "invalid-name-279-chars", route: &api.Route{ Spec: api.RouteSpec{ Host: "name-namespace.a1234567890.b1234567890.c1234567890.d1234567890.e1234567890.f1234567890.g1234567890.h1234567890.i1234567890.j1234567890.k1234567890.l1234567890.m1234567890.n1234567890.o1234567890.p1234567890.q1234567890.r1234567890.s1234567890.t1234567890.u1234567890.example.test", }, }, expectedErrors: true, }, } for _, tc := range tests { errs := ValidateHostName(tc.route) if tc.expectedErrors { if len(errs) < 1 { t.Errorf("Test case %s expected errors, got none.", tc.name) } } else { if len(errs) > 0 { t.Errorf("Test case %s expected no errors, got %d. %v", tc.name, len(errs), errs) } } } }