From a6de90c3f9642230250e1ad327918d57233aebae Mon Sep 17 00:00:00 2001 From: wwhai <751957846@qq.com> Date: Sat, 16 Jan 2021 22:28:15 +0800 Subject: [PATCH] fix(test): add two way ssl test (#4025) --- .github/workflows/run_cts_tests.yaml | 10 +++- apps/emqx_auth_pgsql/etc/emqx_auth_pgsql.conf | 9 ++- .../priv/emqx_auth_pgsql.schema | 11 +++- .../test/emqx_auth_pgsql_SUITE.erl | 58 +++++++++++++++---- 4 files changed, 71 insertions(+), 17 deletions(-) diff --git a/.github/workflows/run_cts_tests.yaml b/.github/workflows/run_cts_tests.yaml index 807af28e9..123910e06 100644 --- a/.github/workflows/run_cts_tests.yaml +++ b/.github/workflows/run_cts_tests.yaml @@ -169,7 +169,7 @@ jobs: pgsql: runs-on: ubuntu-20.04 - + strategy: fail-fast: false matrix: @@ -194,6 +194,12 @@ jobs: run: | docker-compose -f .ci/compatibility_tests/docker-compose-pgsql-tls.yaml build --no-cache docker-compose -f .ci/compatibility_tests/docker-compose-pgsql-tls.yaml up -d + if [ "$PGSQL_TAG" = "12" ] || [ "$PGSQL_TAG" = "13" ]; then + sed -i 's|^[#[:space:]]*auth.pgsql.ssl.tls_versions[ \t]*=.*|auth.pgsql.ssl.tls_versions = tlsv1.3,tlsv1.2|g' apps/emqx_auth_pgsql/etc/emqx_auth_pgsql.conf + else + sed -i 's|^[#[:space:]]*auth.pgsql.ssl.tls_versions[ \t]*=.*|auth.pgsql.ssl.tls_versions = tlsv1.2,tlsv1.1|g' apps/emqx_auth_pgsql/etc/emqx_auth_pgsql.conf + fi + sed -i 's|^[#[:space:]]*auth.pgsql.username[ \t]*=.*|auth.pgsql.username = postgres|g' apps/emqx_auth_pgsql/etc/emqx_auth_pgsql.conf sed -i 's|^[#[:space:]]*auth.pgsql.password[ \t]*=.*|auth.pgsql.password = postgres|g' apps/emqx_auth_pgsql/etc/emqx_auth_pgsql.conf sed -i 's|^[#[:space:]]*auth.pgsql.database[ \t]*=.*|auth.pgsql.database = postgres|g' apps/emqx_auth_pgsql/etc/emqx_auth_pgsql.conf @@ -291,7 +297,7 @@ jobs: sed -i 's|^[#[:space:]]*auth.redis.type[[:space:]]*=.*|auth.redis.type = cluster|g' apps/emqx_auth_redis/etc/emqx_auth_redis.conf sed -i "s|^[#[:space:]]*auth.redis.server[[:space:]]*=.*|auth.redis.server = ${redis_${{ matrix.network_type }}_address}:7000, ${redis_${{ matrix.network_type }}_address}:7001, ${redis_${{ matrix.network_type }}_address}:7002|g" apps/emqx_auth_redis/etc/emqx_auth_redis.conf - name: setup - if: matrix.node_type == 'cluster' && matrix.connect_type == 'tls' && matrix.redis_tag != '5' + if: matrix.node_type == 'cluster' && matrix.connect_type == 'tls' && matrix.redis_tag != '5' run: | set -exu sed -i 's|^[#[:space:]]*auth.redis.type[[:space:]]*=.*|auth.redis.type = cluster|g' apps/emqx_auth_redis/etc/emqx_auth_redis.conf diff --git a/apps/emqx_auth_pgsql/etc/emqx_auth_pgsql.conf b/apps/emqx_auth_pgsql/etc/emqx_auth_pgsql.conf index 4bfcf9de6..bf3d290a0 100644 --- a/apps/emqx_auth_pgsql/etc/emqx_auth_pgsql.conf +++ b/apps/emqx_auth_pgsql/etc/emqx_auth_pgsql.conf @@ -39,6 +39,14 @@ auth.pgsql.encoding = utf8 ## Value: on | off auth.pgsql.ssl = off +## TLS version +## You can configure multi-version use "," split, +## default value is :tlsv1.2 +## Example: +## tlsv1.1,tlsv1.2,tlsv1.3 +## +## auth.pgsql.ssl_opts.tls_versions = tlsv1.2 + ## SSL keyfile. ## ## Value: File @@ -107,4 +115,3 @@ auth.pgsql.super_query = select is_superuser from mqtt_user where username = '%u ## ## Note: You can add the 'ORDER BY' statement to control the rules match order auth.pgsql.acl_query = select allow, ipaddr, username, clientid, access, topic from mqtt_acl where ipaddr = '%a' or username = '%u' or username = '$all' or clientid = '%c' - diff --git a/apps/emqx_auth_pgsql/priv/emqx_auth_pgsql.schema b/apps/emqx_auth_pgsql/priv/emqx_auth_pgsql.schema index f57c15c08..29c186fe8 100644 --- a/apps/emqx_auth_pgsql/priv/emqx_auth_pgsql.schema +++ b/apps/emqx_auth_pgsql/priv/emqx_auth_pgsql.schema @@ -35,6 +35,11 @@ {datatype, {enum, [on, off, true, false]}} %% FIXME: true/fasle is compatible with 4.0-4.2 version format, plan to delete in 5.0 ]}. +{mapping, "auth.pgsql.ssl.tls_versions", "emqx_auth_pgsql.server", [ + {default, "tlsv1.2"}, + {datatype, string} +]}. + {mapping, "auth.pgsql.ssl.keyfile", "emqx_auth_pgsql.server", [ {datatype, string} ]}. @@ -81,7 +86,9 @@ SslOpts = fun(Prefix) -> Filter([{keyfile, cuttlefish:conf_get(Prefix ++ ".keyfile", Conf, undefined)}, {certfile, cuttlefish:conf_get(Prefix ++ ".certfile", Conf, undefined)}, - {cacertfile, cuttlefish:conf_get(Prefix ++ ".cacertfile", Conf, undefined)}]) + {cacertfile, cuttlefish:conf_get(Prefix ++ ".cacertfile", Conf, undefined), + {versions, [list_to_existing_atom(Value) + ||Value <- string:tokens(cuttlefish:conf_get("auth.pgsql.ssl.tls_versions", Conf), " ,")]}}]) end, %% FIXME: compatible with 4.0-4.2 version format, plan to delete in 5.0 @@ -97,7 +104,7 @@ true -> GenSsl; false -> [] end, - + TempHost = case inet:parse_address(PgHost) of {ok, IpAddr} -> IpAddr; diff --git a/apps/emqx_auth_pgsql/test/emqx_auth_pgsql_SUITE.erl b/apps/emqx_auth_pgsql/test/emqx_auth_pgsql_SUITE.erl index 230166a62..1306518cf 100644 --- a/apps/emqx_auth_pgsql/test/emqx_auth_pgsql_SUITE.erl +++ b/apps/emqx_auth_pgsql/test/emqx_auth_pgsql_SUITE.erl @@ -72,7 +72,7 @@ all() -> init_per_suite(Config) -> emqx_ct_helpers:start_apps([emqx_auth_pgsql]), drop_acl(), - init_auth(), + drop_auth(), init_auth(), init_acl(), set_special_configs(), @@ -97,6 +97,30 @@ t_comment_config(_) -> ?assertEqual(AuthCount - 1, length(emqx_hooks:lookup('client.authenticate'))), ?assertEqual(AclCount - 1, length(emqx_hooks:lookup('client.check_acl'))). +t_placeholders(_) -> + ClientA = #{username => <<"plain">>, clientid => <<"plain">>, zone => external}, + reload([{password_hash, plain}, + {auth_query, "select password from mqtt_user where username = '%u' and 'a_cn_val' = '%C' limit 1"}]), + {error, not_authorized} = + emqx_access_control:authenticate(ClientA#{password => <<"plain">>}), + {error, not_authorized} = + emqx_access_control:authenticate(ClientA#{password => <<"plain">>, cn => undefined}), + {ok, _} = + emqx_access_control:authenticate(ClientA#{password => <<"plain">>, cn => <<"a_cn_val">>}), + + reload([{auth_query, "select password from mqtt_user where username = '%c' and 'a_dn_val' = '%d' limit 1"}]), + {error, not_authorized} = + emqx_access_control:authenticate(ClientA#{password => <<"plain">>}), + {error, not_authorized} = + emqx_access_control:authenticate(ClientA#{password => <<"plain">>, dn => undefined}), + {ok, _} = + emqx_access_control:authenticate(ClientA#{password => <<"plain">>, dn => <<"a_dn_val">>}), + + reload([{auth_query, "select password from mqtt_user where username = '%u' and '192.168.1.5' = '%a' limit 1"}]), + {error, not_authorized} = + emqx_access_control:authenticate(ClientA#{password => <<"plain">>}), + {ok, _} = + emqx_access_control:authenticate(ClientA#{password => <<"plain">>, peerhost => {192,168,1,5}}). t_check_auth(_) -> Plain = #{clientid => <<"client1">>, username => <<"plain">>, zone => external}, Md5 = #{clientid => <<"md5">>, username => <<"md5">>, zone => external}, @@ -106,22 +130,32 @@ t_check_auth(_) -> BcryptFoo = #{clientid => <<"bcrypt_foo">>, username => <<"bcrypt_foo">>, zone => external}, User1 = #{clientid => <<"bcrypt_foo">>, username => <<"user">>, zone => external}, Bcrypt = #{clientid => <<"bcrypt">>, username => <<"bcrypt">>, zone => external}, - % + BcryptWrong = #{clientid => <<"bcrypt_wrong">>, username => <<"bcrypt_wrong">>, zone => external}, reload([{password_hash, plain}]), - {ok, #{is_superuser := true}} = emqx_access_control:authenticate(Plain#{password => <<"plain">>}), + {ok,#{is_superuser := true}} = + emqx_access_control:authenticate(Plain#{password => <<"plain">>}), reload([{password_hash, md5}]), - {ok, #{is_superuser := false}} = emqx_access_control:authenticate(Md5#{password => <<"md5">>}), + {ok,#{is_superuser := false}} = + emqx_access_control:authenticate(Md5#{password => <<"md5">>}), reload([{password_hash, sha}]), - {ok, #{is_superuser := false}} = emqx_access_control:authenticate(Sha#{password => <<"sha">>}), + {ok,#{is_superuser := false}} = + emqx_access_control:authenticate(Sha#{password => <<"sha">>}), reload([{password_hash, sha256}]), - {ok, #{is_superuser := false}} = emqx_access_control:authenticate(Sha256#{password => <<"sha256">>}), + {ok,#{is_superuser := false}} = + emqx_access_control:authenticate(Sha256#{password => <<"sha256">>}), reload([{password_hash, bcrypt}]), - {ok, #{is_superuser := false}} = emqx_access_control:authenticate(Bcrypt#{password => <<"password">>}), - - reload([{password_hash, {pbkdf2, sha, 1, 16}}, {auth_query, "select password, salt from mqtt_user where username = '%u' limit 1"}]), - {ok, #{is_superuser := false}} = emqx_access_control:authenticate(Pbkdf2#{password => <<"password">>}), + {ok,#{is_superuser := false}} = + emqx_access_control:authenticate(Bcrypt#{password => <<"password">>}), + {error, not_authorized} = + emqx_access_control:authenticate(BcryptWrong#{password => <<"password">>}), + %%pbkdf2 sha + reload([{password_hash, {pbkdf2, sha, 1, 16}}, + {auth_query, "select password, salt from mqtt_user where username = '%u' limit 1"}]), + {ok,#{is_superuser := false}} = + emqx_access_control:authenticate(Pbkdf2#{password => <<"password">>}), reload([{password_hash, {salt, bcrypt}}]), - {ok, #{is_superuser := false}} = emqx_access_control:authenticate(BcryptFoo#{password => <<"foo">>}), + {ok,#{is_superuser := false}} = + emqx_access_control:authenticate(BcryptFoo#{password => <<"foo">>}), {error, _} = emqx_access_control:authenticate(User1#{password => <<"foo">>}), {error, not_authorized} = emqx_access_control:authenticate(Bcrypt#{password => <<"password">>}). @@ -183,4 +217,4 @@ init_auth() -> drop_auth() -> {ok, Pid} = ecpool_worker:client(gproc_pool:pick_worker({ecpool, ?POOL})), - {ok, [], []} = epgsql:squery(Pid, ?DROP_AUTH_TABLE). \ No newline at end of file + {ok, [], []} = epgsql:squery(Pid, ?DROP_AUTH_TABLE).