From f230c2052178dd30316b422337d05ad8a6862d6d Mon Sep 17 00:00:00 2001 From: Ilya Averyanov Date: Tue, 28 Dec 2021 10:34:41 +0300 Subject: [PATCH] chore(authn): test HTTPS authn --- .../test/data/certs/authn-https-ca.crt | 29 +++ .../test/data/certs/authn-https-ca.key | 51 ++++++ .../test/data/certs/authn-https-client.crt | 24 +++ .../test/data/certs/authn-https-client.key | 27 +++ .../test/data/certs/authn-https-server.crt | 24 +++ .../test/data/certs/authn-https-server.key | 27 +++ .../emqx_authn/test/emqx_authn_http_SUITE.erl | 24 +-- .../test/emqx_authn_http_test_server.erl | 92 ++++++---- .../test/emqx_authn_https_SUITE.erl | 166 ++++++++++++++++++ apps/emqx_authn/test/emqx_authn_jwt_SUITE.erl | 2 +- .../src/emqx_connector_http.erl | 10 +- 11 files changed, 421 insertions(+), 55 deletions(-) create mode 100644 apps/emqx_authn/test/data/certs/authn-https-ca.crt create mode 100644 apps/emqx_authn/test/data/certs/authn-https-ca.key create mode 100644 apps/emqx_authn/test/data/certs/authn-https-client.crt create mode 100644 apps/emqx_authn/test/data/certs/authn-https-client.key create mode 100644 apps/emqx_authn/test/data/certs/authn-https-server.crt create mode 100644 apps/emqx_authn/test/data/certs/authn-https-server.key create mode 100644 apps/emqx_authn/test/emqx_authn_https_SUITE.erl diff --git a/apps/emqx_authn/test/data/certs/authn-https-ca.crt b/apps/emqx_authn/test/data/certs/authn-https-ca.crt new file mode 100644 index 000000000..77275c6ac --- /dev/null +++ b/apps/emqx_authn/test/data/certs/authn-https-ca.crt @@ -0,0 +1,29 @@ +-----BEGIN CERTIFICATE----- +MIIE5DCCAswCCQDNMAIDrjBuwjANBgkqhkiG9w0BAQsFADA0MRIwEAYDVQQKDAlF +TVFYIFRlc3QxHjAcBgNVBAMMFUNlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0yMTEy +MjgwODM5MTBaFw00OTA1MTUwODM5MTBaMDQxEjAQBgNVBAoMCUVNUVggVGVzdDEe +MBwGA1UEAwwVQ2VydGlmaWNhdGUgQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEF +AAOCAg8AMIICCgKCAgEAnHeqS5uHMKn8qbvcBDAnZJa8iGyp7w2eRax2SjjczoQg +SYhV2qEYnDKxh0GkxeinUImYMvhWDQiEfonJSem7gW0xLBt1z8QdJgI9XyYkHKOC +NaEzhd3mER/TR0FiFj4rp7WqK0ZvqHGpDrXFCiUG7cAR6VkqJcjlQm+DSlJzHgvM +mNNlBdwUpO6dkVpVTP/v86AhC5rLgx1WV9lart8iKH2EDpGNpRB6lSqkI6OpGiYK +ddS3jOYctp1RqZey3IoPqF5xcEdD/nuxX31tvdUnkh1X2Fyiw7aXm9ec0X5vuUk8 +EHeIEI4AYAdIBfo72wpdWcf1KKxS1HpOYRZOXQAXICZ8Nts2P6w4nExcxfdhyqjX +ht+D2aE78gltEt8MiPmtPRi2y6qeeiQ3A37WDxAgy9BRtQbINTMW1vTMToH9x7wT +1LGbLVzXZ+e5vcKJvm8FRWAYIrRW0AYNhVvzPcOqa1Rr0oas3UVieLxksW9aScya +K14UE06s3PAgcasWMdUK4yyrrBpzXKNTxwZfNk2NQOvVlV4fVmzYDb/16EKMhT+W +BU9eDD4JHyFYXUK7J/NLjYuPKR21XqgvV2yjAWR9zf4GnAsUTQHba6E87GdclREF +U0fnqtX1FrXe7sLVU6xJvZg/f1Us2RhfdpP2XIPS3E8JYOGUGTkI+RHPFQKrWOsC +AwEAATANBgkqhkiG9w0BAQsFAAOCAgEAAuY/4cYUrzhbZYOXu12bubOFEuweqCyK +oX2ehpH7MEwTAOsiwzWo/qaeNahSAYtlntAp2Fut5s9fwLRATrF57CjAGDfIG1J6 +gINKHUQTfTshSLqUIcN96JMQGJaE8e/6198shOq4DR7bOBVqOwq7yGbBTrkHNDu0 +FHUeygnV2Ik54rcCsSA4bLeEg3X7ZMmakRGY8lD2R+vnfyxlY2WFSlbOL+MJStca +rE1v444dgMVAFyfLDgf1gr+pbCQthOcPtRUD2KAK8A9Ls7IyKn8ShonMQKrYLixu +FNPv8az5OefRTHdWG2KKFamFQhNYwVJwxM++0XkUUVlc7brtJ9AOr/H5bJhAR9LA +qc9sueIOg2kEadEvMnE3GMy9dIA5WYTZmXv7PH3j5D2+C6mZnTMo/75l9OPLSj/r +ddzCzkgu76hsKPKVjTqNyYJDeaTJhZ0OR+PWzB5/VUD4rIZ3cavgFVJTGk5I7SPy +PQvqjBCj1A0frCTnlavSmbItyJzaQrnzLKihvehW3vOJ8KcBWs4cILLK7f8wR1zj +qsatv//6z17kGrTzivi8o1epA7F43eHlXCG7wXJq82ls6Lix79Ek95zXwYz2RKJ1 +ZGdwttGD+mh0Jh1U3OR97DD4N821xYlY29oVEI27OmKm4zv3z4S2dZqEYrk6yQ7+ +OMemQ8o1DIk= +-----END CERTIFICATE----- diff --git a/apps/emqx_authn/test/data/certs/authn-https-ca.key b/apps/emqx_authn/test/data/certs/authn-https-ca.key new file mode 100644 index 000000000..eb340db45 --- /dev/null +++ b/apps/emqx_authn/test/data/certs/authn-https-ca.key @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +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 +-----END RSA PRIVATE KEY----- diff --git a/apps/emqx_authn/test/data/certs/authn-https-client.crt b/apps/emqx_authn/test/data/certs/authn-https-client.crt new file mode 100644 index 000000000..1564fc61b --- /dev/null +++ b/apps/emqx_authn/test/data/certs/authn-https-client.crt @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIID/jCCAeagAwIBAgIJANRNg7GwqxjwMA0GCSqGSIb3DQEBCwUAMDQxEjAQBgNV +BAoMCUVNUVggVGVzdDEeMBwGA1UEAwwVQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4X +DTIxMTIyODA4MzkxMFoXDTQ5MDUxNTA4MzkxMFowJTESMBAGA1UECgwJRU1RWCBU +ZXN0MQ8wDQYDVQQDDAZjbGllbnQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQDieKJGbZGACvdwI5TbpesvudLx+lxW6cp0hsCR+SERzOE8vx0Jrca6oP+y +WIclYhPv1LLq2/FAvaF+WBYhvSAg7fqx3U8XJpH8pEV4NxV0cbSj4i16XJ09bc1Q +kNPO3Lsh1S06TGY9d7vTO64BLPi5ImGA972pcjoESxybG8zYfQnfXsdQ6bFPjWUa +AnbwxnGWJQQzGTgZgUIJox0Oo3APh4wV1JLTMKlfMekmdImiXHp6r4kh+7C15Bmg +NnF9qEZRKeU09hqIa0SDtUg9rmrLeUCLbaVKUoa6kBkLFUTUGh8VHHhwMHTgrsn7 +UJm0OwvDLH9vcYF/78IS38P/SpyVAgMBAAGjIjAgMAsGA1UdDwQEAwIFoDARBglg +hkgBhvhCAQEEBAMCB4AwDQYJKoZIhvcNAQELBQADggIBAJWJ/KLWZAxCm4pLDnaz +z6HdrBGbRwZMt9CtJCvTy8m+kiW7gu0LzUuIOwyjqPVwTAAWWyYhLZ5PxJiahUh6 +dEt4AN5z03O8HIQ1uScSHCNkAeg2xeGw4GsM7bUmLWD1Kv2+N6DzTDzBebyoh9qV +Ke14AOu1jcIF6nUPJjW5bt4sm1LbkdpgTaChIMl3/aX9DE081g7p7XTQkCtajTgn +LINgPwGl9oQnuYypc7vks4YHiqKD0BXl05jyImfhO7N3LiT43tBLlJ0iRnxa7B6V +VFhj3Zj36qPqj74gxpS1P8q/4MealGGejfBUe3Q6j29gh8YfV/ACip3lB5IrWiHG +IbRbGpv0KnYzv9WggXiXEiMQosl2hSebSxP5zN7wcBATSaiLwSZvs7TOA2vqiwYZ +uAx+eC8XdQjp294RXiHnV6TCb/PYPc4PQJpt8AZElhXi+GuaDhAjf9MOlJiw7UJF +6BMiMp4vYiPoqYezIqjBe2qal23SIubncP7/P/a0b/7CW8frZ8wha56f0o6vPTeV +09VvEMXG+b/mAs4qV1xBjwr16xuR/8kZk9mZjJy5046bsnh9oF0hctyQhPQeKptm +UHgJroJgSm92jL2D4r4Y+2N/2aw3J0EzZ0AN/XytTRYmqhsnC98lvbw4sE2VtT4M +sTHEF6TomqSoTBZ5B/Wwyi2G +-----END CERTIFICATE----- diff --git a/apps/emqx_authn/test/data/certs/authn-https-client.key b/apps/emqx_authn/test/data/certs/authn-https-client.key new file mode 100644 index 000000000..a95274d5a --- /dev/null +++ b/apps/emqx_authn/test/data/certs/authn-https-client.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEA4niiRm2RgAr3cCOU26XrL7nS8fpcVunKdIbAkfkhEczhPL8d +Ca3GuqD/sliHJWIT79Sy6tvxQL2hflgWIb0gIO36sd1PFyaR/KRFeDcVdHG0o+It +elydPW3NUJDTzty7IdUtOkxmPXe70zuuASz4uSJhgPe9qXI6BEscmxvM2H0J317H +UOmxT41lGgJ28MZxliUEMxk4GYFCCaMdDqNwD4eMFdSS0zCpXzHpJnSJolx6eq+J +IfuwteQZoDZxfahGUSnlNPYaiGtEg7VIPa5qy3lAi22lSlKGupAZCxVE1BofFRx4 +cDB04K7J+1CZtDsLwyx/b3GBf+/CEt/D/0qclQIDAQABAoIBABMocVHT4wMZ6mSq +HeWW25Zl+dpOe5E+pcnFvHScxpdi5Yrl/+bZtH4FMJw9sPEQou8e5yPHB1masRan +DPg9r4IZn6N8PTyQHrlojBfnUQFQvR8/+ujm/MY9i6jNF53gPlRWXEUaQWvhvRnZ +apbe3wuKRQVL79dtukqyr/DPIT0O7hEvqS3HpxoFYq3MkgWNMErOGznWGnLczZWO ++7swsuMmKoPDV6FEz17DiBx3vCKZRVQB9Dx2cTm4A2DkfEms2aIXzObV5AyAZxcG +6krPcRV6KTE9oFmEQwZNLnwWXsBWYVGOmgN+IeDq/jHfkAaBU21GrnlFgcPWNuNS +EN2UtQECgYEA87NJv5ZqpIdw/kuyV3KpkL1btP/UF8lmRJfLDreKkJq8TiY2/DmF +vOjq9gg/19Obve09utT3w0GPzDmATn2C+STGO5aQHJb2UPRerLfJzizAKph6yMKh +rypk0prdNJTqhOFC8M3aS54x5k7OmT6wrVKA1rJQ3RRNz94xrrGD0PkCgYEA7ea9 +AHVg5wZVcV8n3aPUNFVZ1saaQv4hnmXP3pYPuffin17oDVY69qPzJVuI5E8Or2Em +EN4Rs9G7gFZ2uor9nzsZdTnKVn2gYDE7NdslcqZUqwhtzQ3xR2Ai7VozIUyd+p77 +WbsUhyIf1uOnOW/v3fNX/+vbysbgnqYLWakh630CgYBBe6mTa42YTDSWgCyZxtu9 +YsRjrGKHSbzLLaaIe9Ul6g4zSZ14xNQk4MlR9wGAswGkVT1DGLrCorlK/SB29s7c +t370wA5VQFNLiX5vFquJVQkF6RcFHxdnBBM3bBmIaYNi1Uyxe/7uVsG9yutEzk2X +JRYtmpiT70LBWkkrUdPDsQKBgFtZh2d+qufrAbIX1MoBl4FE6MtU1XU1+hjFhW01 +9/Hz4lxJ6Bb+7oM4bywAGu93/+6OAjzl2KxQs4vTJ6H3ru2OlvbxauWNNaDaJp9G +d/mvLsHB6c+cM/KxUpgLU6jMr7jFhURuVrKRAuLT5aljdxqlzzuhCHOzrBqfLaqP +DExNAoGAXzFQJyfqX46cgpbzW+J2Y5EN422w0zes87AtO9HjysexMbGRy+ZVOQ+b +Q7MAieMh8r2g1fMhzYIGwiQqb9xLS00aAXxSp65ngqnPQe7TSBc3IkT42bwuF5Qd +D4ygVfuDH6EcPs4ZWXPpuzWw93K6BxKJvLQFuBmm72DirCf2NyQ= +-----END RSA PRIVATE KEY----- diff --git a/apps/emqx_authn/test/data/certs/authn-https-server.crt b/apps/emqx_authn/test/data/certs/authn-https-server.crt new file mode 100644 index 000000000..a3507cfbb --- /dev/null +++ b/apps/emqx_authn/test/data/certs/authn-https-server.crt @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIIEAzCCAeugAwIBAgIJANRNg7GwqxjvMA0GCSqGSIb3DQEBCwUAMDQxEjAQBgNV +BAoMCUVNUVggVGVzdDEeMBwGA1UEAwwVQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4X +DTIxMTIyODA4MzkxMFoXDTQ5MDUxNTA4MzkxMFowKjESMBAGA1UECgwJRU1RWCBU +ZXN0MRQwEgYDVQQDDAthdXRobi1odHRwczCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAL5kOgBV1lOMZYPwhrDiOwwLoo+WdepKhubQ8isCiOsSZ7ubwzIh +gNjFZ+Q/dR78wHkuJpQTKukv1srl1PNlcHBs+4AUi6YwwsFq9pLiSv7+bsXTPCnF +rDfQpILKXilLFIrZB9aBFywlDOHdoiNSKveO9ihZSgRz71HLh2OVYt+ToNF35pZp +pPKM0WKQnOZDu+P505hzQ1aar6oUJKChEdV5OOQVmGz9pMjdHvjy5C9VS2xnIS2H +TOAot1FM66jwr4UgtD3QHnIBH/vAzeICS6Xf2FSuZjmeDOvtxCXbA5H7iWEsxGj3 +1yBJB3U72qLz/QSm101N+EKRg+jPi40O4Z8CAwEAAaMiMCAwCwYDVR0PBAQDAgWg +MBEGCWCGSAGG+EIBAQQEAwIGQDANBgkqhkiG9w0BAQsFAAOCAgEAlUSYcgkJ0zTq +knAvCRwaHcNjPU1ZQryrp2oqiDLOzMJFMPJ144jcXhrY0UiG9kdxeMP6PjZw+JK9 +6KxMtgy8dE7mJQnnx8Ino5WYHncyzL6FPv1CJA153xHIepVrX58Amys2kauw4jga +vVzH6o4cyOvnWPx9iFNHrXIvWydxNF9iqejlN7HSSNDqz/kK3Ltzw0Hp5BN8vcwd +hFyDOxgJKKEY159TPjs9HTvUrOKx7Fmlc6D1kGyzOH2rEajGm6oLJZtB/2avPAT1 +8x3PAO+2PqmbwT5rW4koDKVNvDGrZ6YTK43GIx6o6B5Mlb8lxXFSpgkgPy85wx6C +D7E4bYoZbhY7WCqTSUIe4LpJq0iW4lx3oXV3WEPSBaaWwH34VtvSbASAhu1HYbZP +rTae8xXY/HaKH5YE71+AqkQ+IQ4760yWgxdiifT/4dIiWG0RFRdP6InPWpBGXIPg +rzETeEV1mIbO97xX93z4PNpi6UgAhwVTSrLYI+yKj8hfqx8GhBI2QBnW7t7W4gfa +NxwB64JfCZOWOob/dWwq+70zOIiLUquUVEYkjyGP/FVbh7W0h5tcEsSnc0igc6wF +FhQaI8NGOt53ScN2Lqxl8KboIQIHG3YOqrTaviSNNCQ5TOIMgZ5B43IuxLxT65yC +mfg8VCXY3BXCvqrKp+UyYQAD8ZzH5wU= +-----END CERTIFICATE----- diff --git a/apps/emqx_authn/test/data/certs/authn-https-server.key b/apps/emqx_authn/test/data/certs/authn-https-server.key new file mode 100644 index 000000000..fcd49b958 --- /dev/null +++ b/apps/emqx_authn/test/data/certs/authn-https-server.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAvmQ6AFXWU4xlg/CGsOI7DAuij5Z16kqG5tDyKwKI6xJnu5vD +MiGA2MVn5D91HvzAeS4mlBMq6S/WyuXU82VwcGz7gBSLpjDCwWr2kuJK/v5uxdM8 +KcWsN9CkgspeKUsUitkH1oEXLCUM4d2iI1Iq9472KFlKBHPvUcuHY5Vi35Og0Xfm +lmmk8ozRYpCc5kO74/nTmHNDVpqvqhQkoKER1Xk45BWYbP2kyN0e+PLkL1VLbGch +LYdM4Ci3UUzrqPCvhSC0PdAecgEf+8DN4gJLpd/YVK5mOZ4M6+3EJdsDkfuJYSzE +aPfXIEkHdTvaovP9BKbXTU34QpGD6M+LjQ7hnwIDAQABAoIBADOTAOdAWVuuh31T +NZlK30XnDPUqg+ygnaR+62rdN+u9w53dluXIj5eo+fipe/eV7imlZ8vq2U/rppq1 +4ZbBXtEFpKdQaXfuc4Njj0HAzSIAGE+8ZerG4l0IRtgrK5CyBvGJ0wa3V2ic7L1u +hVJeGseO0X2imltUcHrO0HEYcX0wjvS4mbLO1tW7CHLSdYv+74ndF73uKjuS55lH +uu2oEv+Lyz4lC0g3CjS8JyU0fjwmspwCk9R0Fui7s0OmDJLNTLwmCgRj/6i666za +EKRIRrMT6jg93sFfKcgcl89qK7JVJofn1zD4T78cAlYODW0sdHp2C4DXScRVz/bp +Xeq6hBECgYEA+c8cYS73rmyx6CphkR7W0HAeb2M1iq+EIge59zjhQK8vuSYl+A3Z +V3AsnwEflj9y9yH+tdxHHLA7nBM2s3VTqQcHzf7Kl5bJnmiy67N4G2439ICdinF4 +LpZi8MC03DsO8Ll0xIex2zZ7MWQSpRN5S3geOWL7aWdOzij+3LOHkLcCgYEAwxwl +pD4nFaXMK8yVE8o+rmLnft7SoqMQGuBam2G8bukxMJOUf+w1f848poljGGZ9iUY5 +LmgM0ZCpbtSvj0W2YfA4nwiV4rsNOHfCv2jxP8HVssTZ8mOZBnJn6nPmrL89zD/c +Hte4UziORBdp578ROt9tYLfTiXu0ZMjO++Fo/lkCgYAQl6oZ5mW7JysV8aKzYeoA +xEGxQlSvFoNfQ0Yd3qBPjJNN5/PDqx/Rh/jewtNXRnWbZp2ldLEgfbAn6LrMZrGc +24OwMglA0lon9GpV74C9ya9bxSMxq+HArmp59ULOEfonERppZ13v4omCOVRntIhs +89iGFUX/tUXtuZlcDWymtwKBgBqoK9Rm0Xw5rM2HJA8SIMI+rRY+Z1TlJnwljvuP +vOkCX0Adybo4kY6mpM60Ep/w0NICkClw+d9f/mYwFNRkV+jFo1bHG4NgvwuqASeZ +tOxbFVFZZ9WgGfYxh1UXBLsxXcYcK3zjSEHGhllzQXryNe5vPEhslTBBgIIMlYsA +XxHxAoGAX8UAWut6owblPbB3E4k6JFxRDOvbYIvKFEuAfpRbmna8af5jGUUxuOAp +q09fQHnrkJpjaSMIym0oiHyLe13+NPRQs+jeHH3hzAM44DFlh/fpE77Yd9ZFRqXq +IiCv5uA7sl+0WlQCmZFLvPFwZ3XAm9lDO+3IbMYBNpgLTt2+QQc= +-----END RSA PRIVATE KEY----- diff --git a/apps/emqx_authn/test/emqx_authn_http_SUITE.erl b/apps/emqx_authn/test/emqx_authn_http_SUITE.erl index 2c0716e8b..b52588124 100644 --- a/apps/emqx_authn/test/emqx_authn_http_SUITE.erl +++ b/apps/emqx_authn/test/emqx_authn_http_SUITE.erl @@ -57,11 +57,11 @@ init_per_testcase(_Case, Config) -> emqx_authn_test_lib:delete_authenticators( [authentication], ?GLOBAL), - emqx_authn_http_test_server:start(?HTTP_PORT, ?HTTP_PATH), + {ok, _} = emqx_authn_http_test_server:start_link(?HTTP_PORT, ?HTTP_PATH), Config. end_per_testcase(_Case, _Config) -> - ok = emqx_authn_http_test_server:stop() . + ok = emqx_authn_http_test_server:stop(). %%------------------------------------------------------------------------------ %% Tests @@ -118,7 +118,7 @@ test_user_auth(#{handler := Handler, ?PATH, {create_authenticator, ?GLOBAL, AuthConfig}), - emqx_authn_http_test_server:set_handler(Handler), + ok = emqx_authn_http_test_server:set_handler(Handler), ?assertEqual(Result, emqx_access_control:authenticate(?CREDENTIALS)), @@ -221,15 +221,15 @@ test_is_superuser({Kind, Value, ExpectedValue}) -> iolist_to_binary([<<"is_superuser=">>, Value])} end, - emqx_authn_http_test_server:set_handler( - fun(Req0, State) -> - Req = cowboy_req:reply( - 200, - #{<<"content-type">> => ContentType}, - Res, - Req0), - {ok, Req, State} - end), + ok = emqx_authn_http_test_server:set_handler( + fun(Req0, State) -> + Req = cowboy_req:reply( + 200, + #{<<"content-type">> => ContentType}, + Res, + Req0), + {ok, Req, State} + end), ?assertMatch( {ok, #{is_superuser := ExpectedValue}}, diff --git a/apps/emqx_authn/test/emqx_authn_http_test_server.erl b/apps/emqx_authn/test/emqx_authn_http_test_server.erl index 4896a8b13..caeb798ab 100644 --- a/apps/emqx_authn/test/emqx_authn_http_test_server.erl +++ b/apps/emqx_authn/test/emqx_authn_http_test_server.erl @@ -16,20 +16,18 @@ -module(emqx_authn_http_test_server). --behaviour(gen_server). +-behaviour(supervisor). -behaviour(cowboy_handler). % cowboy_server callbacks -export([init/2]). -% gen_server callbacks --export([init/1, - handle_call/3, - handle_cast/2 - ]). +% supervisor callbacks +-export([init/1]). % API --export([start/2, +-export([start_link/2, + start_link/3, stop/0, set_handler/1 ]). @@ -38,52 +36,70 @@ %% API %%------------------------------------------------------------------------------ -start(Port, Path) -> - Dispatch = cowboy_router:compile([ - {'_', [{Path, ?MODULE, []}]} - ]), - {ok, _} = cowboy:start_clear(?MODULE, - [{port, Port}], - #{env => #{dispatch => Dispatch}} - ), - {ok, _} = gen_server:start_link({local, ?MODULE}, ?MODULE, [], []), - ok. +start_link(Port, Path) -> + start_link(Port, Path, false). + +start_link(Port, Path, SSLOpts) -> + supervisor:start_link({local, ?MODULE}, ?MODULE, [Port, Path, SSLOpts]). stop() -> - gen_server:stop(?MODULE), - cowboy:stop_listener(?MODULE). + gen_server:stop(?MODULE). set_handler(F) when is_function(F, 2) -> - gen_server:call(?MODULE, {set_handler, F}). + true = ets:insert(?MODULE, {handler, F}), + ok. %%------------------------------------------------------------------------------ -%% gen_server API +%% supervisor API %%------------------------------------------------------------------------------ -init([]) -> - F = fun(Req0, State) -> - Req = cowboy_req:reply( - 400, - #{<<"content-type">> => <<"text/plain">>}, - <<"">>, - Req0), - {ok, Req, State} - end, - {ok, F}. +init([Port, Path, SSLOpts]) -> + Dispatch = cowboy_router:compile( + [ + {'_', [{Path, ?MODULE, []}]} + ]), + + ProtoOpts = #{env => #{dispatch => Dispatch}}, -handle_cast(_, F) -> - {noreply, F}. + Tab = ets:new(?MODULE, [set, named_table, public]), + ets:insert(Tab, {handler, fun default_handler/2}), -handle_call({set_handler, F}, _From, _F) -> - {reply, ok, F}; + {Transport, TransOpts, CowboyModule} = transport_settings(Port, SSLOpts), -handle_call(get_handler, _From, F) -> - {reply, F, F}. + ChildSpec = ranch:child_spec(?MODULE, Transport, TransOpts, CowboyModule, ProtoOpts), + + {ok, {{one_for_one, 10, 10}, [ChildSpec]}}. %%------------------------------------------------------------------------------ %% cowboy_server API %%------------------------------------------------------------------------------ init(Req, State) -> - Handler = gen_server:call(?MODULE, get_handler), + [{handler, Handler}] = ets:lookup(?MODULE, handler), Handler(Req, State). + +%%------------------------------------------------------------------------------ +%% Internal functions +%%------------------------------------------------------------------------------ + +transport_settings(Port, false) -> + TransOpts = #{socket_opts => [{port, Port}], + connection_type => supervisor}, + {ranch_tcp, TransOpts, cowboy_clear}; + +transport_settings(Port, SSLOpts) -> + TransOpts = #{socket_opts => [{port, Port}, + {next_protocols_advertised, [<<"h2">>, <<"http/1.1">>]}, + {alpn_preferred_protocols, [<<"h2">>, <<"http/1.1">>]} + | SSLOpts], + connection_type => supervisor}, + {ranch_ssl, TransOpts, cowboy_tls}. + +default_handler(Req0, State) -> + Req = cowboy_req:reply( + 400, + #{<<"content-type">> => <<"text/plain">>}, + <<"">>, + Req0), + {ok, Req, State}. + diff --git a/apps/emqx_authn/test/emqx_authn_https_SUITE.erl b/apps/emqx_authn/test/emqx_authn_https_SUITE.erl new file mode 100644 index 000000000..d70946bcd --- /dev/null +++ b/apps/emqx_authn/test/emqx_authn_https_SUITE.erl @@ -0,0 +1,166 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020-2021 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_authn_https_SUITE). + +-compile(nowarn_export_all). +-compile(export_all). + +-include("emqx_authn.hrl"). +-include_lib("eunit/include/eunit.hrl"). +-include_lib("common_test/include/ct.hrl"). +-include_lib("emqx/include/emqx_placeholder.hrl"). + +-define(PATH, [?CONF_NS_ATOM]). + +-define(HTTPS_PORT, 33333). +-define(HTTPS_PATH, "/auth"). +-define(CREDENTIALS, #{username => <<"plain">>, + password => <<"plain">>, + listener => 'tcp:default', + protocol => mqtt + }). + + +all() -> + emqx_common_test_helpers:all(?MODULE). + +init_per_suite(Config) -> + _ = application:load(emqx_conf), + emqx_common_test_helpers:start_apps([emqx_authn]), + application:ensure_all_started(cowboy), + Config. + +end_per_suite(_) -> + emqx_authn_test_lib:delete_authenticators( + [authentication], + ?GLOBAL), + emqx_common_test_helpers:stop_apps([emqx_authn]), + application:stop(cowboy), + ok. + +init_per_testcase(_Case, Config) -> + {ok, _} = emqx_cluster_rpc:start_link(node(), emqx_cluster_rpc, 1000), + emqx_authn_test_lib:delete_authenticators( + [authentication], + ?GLOBAL), + {ok, _} = emqx_authn_http_test_server:start_link(?HTTPS_PORT, ?HTTPS_PATH, server_ssl_opts()), + ok = emqx_authn_http_test_server:set_handler(fun cowboy_handler/2), + Config. + +end_per_testcase(_Case, _Config) -> + ok = emqx_authn_http_test_server:stop(). + +%%------------------------------------------------------------------------------ +%% Tests +%%------------------------------------------------------------------------------ + +t_create(_Config) -> + {ok, _} = create_https_auth_with_ssl_opts( + #{<<"server_name_indication">> => <<"authn-https">>, + <<"verify">> => <<"verify_peer">>, + <<"versions">> => [<<"tlsv1.2">>], + <<"ciphers">> => [<<"ECDHE-RSA-AES256-GCM-SHA384">>]}), + + ?assertMatch( + {ok, _}, + emqx_access_control:authenticate(?CREDENTIALS)). + +t_create_invalid_domain(_Config) -> + {ok, _} = create_https_auth_with_ssl_opts( + #{<<"server_name_indication">> => <<"authn-https-unknown-host">>, + <<"verify">> => <<"verify_peer">>, + <<"versions">> => [<<"tlsv1.2">>], + <<"ciphers">> => [<<"ECDHE-RSA-AES256-GCM-SHA384">>]}), + + ?assertEqual( + {error, not_authorized}, + emqx_access_control:authenticate(?CREDENTIALS)). + +t_create_invalid_version(_Config) -> + {ok, _} = create_https_auth_with_ssl_opts( + #{<<"server_name_indication">> => <<"authn-https">>, + <<"verify">> => <<"verify_peer">>, + <<"versions">> => [<<"tlsv1.1">>]}), + + ?assertEqual( + {error, not_authorized}, + emqx_access_control:authenticate(?CREDENTIALS)). + +t_create_invalid_ciphers(_Config) -> + {ok, _} = create_https_auth_with_ssl_opts( + #{<<"server_name_indication">> => <<"authn-https">>, + <<"verify">> => <<"verify_peer">>, + <<"versions">> => [<<"tlsv1.2">>], + <<"ciphers">> => [<<"ECDHE-ECDSA-AES256-SHA384">>]}), + + ?assertEqual( + {error, not_authorized}, + emqx_access_control:authenticate(?CREDENTIALS)). + +%%------------------------------------------------------------------------------ +%% Helpers +%%------------------------------------------------------------------------------ + +create_https_auth_with_ssl_opts(SpecificSSLOpts) -> + AuthConfig = raw_https_auth_config(SpecificSSLOpts), + emqx:update_config(?PATH, {create_authenticator, ?GLOBAL, AuthConfig}). + +raw_https_auth_config(SpecificSSLOpts) -> + SSLOpts = maps:merge( + client_ssl_opts(), + #{enable => <<"true">>}), + #{ + mechanism => <<"password-based">>, + enable => <<"true">>, + + backend => <<"http">>, + method => <<"get">>, + url => <<"https://127.0.0.1:33333/auth">>, + body => #{<<"username">> => ?PH_USERNAME, <<"password">> => ?PH_PASSWORD}, + headers => #{<<"X-Test-Header">> => <<"Test Value">>}, + ssl => maps:merge(SSLOpts, SpecificSSLOpts) + }. + +start_apps(Apps) -> + lists:foreach(fun application:ensure_all_started/1, Apps). + +stop_apps(Apps) -> + lists:foreach(fun application:stop/1, Apps). + +cert_path(FileName) -> + Dir = code:lib_dir(emqx_authn, test), + filename:join([Dir, <<"data/certs">>, FileName]). + +cowboy_handler(Req0, State) -> + Req = cowboy_req:reply( + 200, + Req0), + {ok, Req, State}. + +client_ssl_opts() -> + #{keyfile => cert_path("authn-https-client.key"), + certfile => cert_path("authn-https-client.crt"), + cacertfile => cert_path("authn-https-ca.crt")}. + +server_ssl_opts() -> + [{keyfile, cert_path("authn-https-server.key")}, + {certfile, cert_path("authn-https-server.crt")}, + {cacertfile, cert_path("authn-https-ca.crt")}, + {verify, verify_none}, + {versions, ['tlsv1.2', 'tlsv1.3']}, + {ciphers, ["ECDHE-RSA-AES256-GCM-SHA384", "TLS_CHACHA20_POLY1305_SHA256"]} + ]. diff --git a/apps/emqx_authn/test/emqx_authn_jwt_SUITE.erl b/apps/emqx_authn/test/emqx_authn_jwt_SUITE.erl index 0a166616a..7cf628392 100644 --- a/apps/emqx_authn/test/emqx_authn_jwt_SUITE.erl +++ b/apps/emqx_authn/test/emqx_authn_jwt_SUITE.erl @@ -156,7 +156,7 @@ t_jwt_authenticator_public_key(_) -> ok. t_jwks_renewal(_Config) -> - ok = emqx_authn_http_test_server:start(?JWKS_PORT, ?JWKS_PATH), + {ok, _} = emqx_authn_http_test_server:start_link(?JWKS_PORT, ?JWKS_PATH), ok = emqx_authn_http_test_server:set_handler(fun jwks_handler/2), PrivateKey = test_rsa_key(private), diff --git a/apps/emqx_connector/src/emqx_connector_http.erl b/apps/emqx_connector/src/emqx_connector_http.erl index 2b9bd48aa..55de39ef5 100644 --- a/apps/emqx_connector/src/emqx_connector_http.erl +++ b/apps/emqx_connector/src/emqx_connector_http.erl @@ -203,10 +203,12 @@ on_query(InstId, {KeyOrNum, Method, Request, Timeout}, AfterQuery, request => Request, connector => InstId, state => State}), NRequest = update_path(BasePath, Request), - case Result = ehttpc:request(case KeyOrNum of - undefined -> PoolName; - _ -> {PoolName, KeyOrNum} - end, Method, NRequest, Timeout) of + Name = case KeyOrNum of + undefined -> PoolName; + _ -> {PoolName, KeyOrNum} + end, + Result = ehttpc:request(Name, Method, NRequest, Timeout), + case Result of {error, Reason} -> ?SLOG(error, #{msg => "http connector do reqeust failed", request => NRequest, reason => Reason,