From e3bfaf6a2459b6d2def1556f35caf306b65f9c4a Mon Sep 17 00:00:00 2001 From: CommanderKeynes Date: Tue, 3 Sep 2024 14:42:54 -0500 Subject: [PATCH] Add tests for LDAP --- .circleci/glauth.cfg | 111 +++++++++++++++++++++++++++++++++++++ .circleci/pgcat_ldap.toml | 25 +++++++++ .circleci/pgcat_trust.toml | 1 - tests/docker/Dockerfile | 2 + tests/python/tests.py | 86 ++++++++++++++++++++++++++-- 5 files changed, 218 insertions(+), 7 deletions(-) create mode 100644 .circleci/glauth.cfg create mode 100644 .circleci/pgcat_ldap.toml diff --git a/.circleci/glauth.cfg b/.circleci/glauth.cfg new file mode 100644 index 00000000..e76b33e1 --- /dev/null +++ b/.circleci/glauth.cfg @@ -0,0 +1,111 @@ +################# +# glauth.conf + +################# +# General configuration. +debug = true + +[ldap] + enabled = true + # run on a non privileged port + listen = "0.0.0.0:3893" + tls = false + +[ldaps] + enabled = false +################# +# Tracing section controls the tracer configuration +[tracing] + # if enabled is set to false, a no-op tracer will be used + enabled = true + # if both grpcEndpoint and httpEndpoint are unset, the default stdout provider will be used + # TODO add allowGRPCInsecure: right now grpc otlp is using the WithInsecure flag so traffic + # will always go without verifying server certificates + # grpcEndpoint = "otlp.monitoring.io:4317" + # httpEndpoint = "http://otlp.monitoring.io:4318" +################# +# The backend section controls the data store. +[backend] + datastore = "config" + baseDN = "dc=example,dc=com" + nameformat = "cn" + groupformat = "ou" + + # If you are using a client that requires reading the root DSE first + # such as SSSD + # anonymousdse = true + + ## Configure dn format to use structures like + ## "uid=serviceuser,cn=svcaccts,$BASEDN" instead of "cn=serviceuser,ou=svcaccts,$BASEDN" + ## to help ease migrations from other LDAP systems + # nameformat = "uid" + # groupformat = "cn" + + ## Configure ssh-key attribute name, default is 'sshPublicKey' + # sshkeyattr = "ipaSshPubKey" + +[behaviors] + # Ignore all capabilities restrictions, for instance allowing every user to perform a search + IgnoreCapabilities = false + # Enable a "fail2ban" type backoff mechanism temporarily banning repeated failed login attempts + LimitFailedBinds = true + # How many failed login attempts are allowed before a ban is imposed + NumberOfFailedBinds = 3 + # How long (in seconds) is the window for failed login attempts + PeriodOfFailedBinds = 10 + # How long (in seconds) is the ban duration + BlockFailedBindsFor = 60 + # Clean learnt IP addresses every N seconds + PruneSourceTableEvery = 600 + # Clean learnt IP addresses not seen in N seconds + PruneSourcesOlderThan = 600 + +################# +# The users section contains a hardcoded list of valid users. +# to create a passSHA256: echo -n "mysecret" | openssl dgst -sha256 +[[users]] + name = "admin_user" + uidnumber = 5001 + primarygroup = 5501 + mail = "admin_user@example.com" + passsha256 = "6478579e37aff45f013e14eeb30b3cc56c72ccdc310123bcdf53e0333e3f416a" # dogood + [[users.customattributes]] + employeetype = ["Intern", "Temp"] + employeenumber = [12345, 54321] + [[users.capabilities]] + action = "search" + object = "dc=example,dc=com" + +# This user record shows all of the possible fields available +[[users]] + name = "sharding_user" + givenname="John" + sn="Doe" + mail = "sharding_user@example.com" + uidnumber = 5002 + primarygroup = 5501 + loginShell = "/bin/sh" + homeDir = "/root" + passsha256 = "6478579e37aff45f013e14eeb30b3cc56c72ccdc310123bcdf53e0333e3f416a" # dogood + sshkeys = ["ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEA3UKCEllO2IZXgqNygiVb+dDLJJwVw3AJwV34t2jzR+/tUNVeJ9XddKpYQektNHsFmY93lJw5QDSbeH/mAC4KPoUM47EriINKEelRbyG4hC/ko/e2JWqEclPS9LP7GtqGmscXXo4JFkqnKw4TIRD52XI9n1syYM9Y8rJ88fjC/Lpn+01AB0paLVIfppJU35t0Ho9doHAEfEvcQA6tcm7FLJUvklAxc8WUbdziczbRV40KzDroIkXAZRjX7vXXhh/p7XBYnA0GO8oTa2VY4dTQSeDAUJSUxbzevbL0ll9Gi1uYaTDQyE5gbn2NfJSqq0OYA+3eyGtIVjFYZgi+txSuhw== rsa-key-20160209"] + passappsha256 = [ + "c32255dbf6fd6b64883ec8801f793bccfa2a860f2b1ae1315cd95cdac1338efa", # TestAppPw1 + "c9853d5f2599e90497e9f8cc671bd2022b0fb5d1bd7cfff92f079e8f8f02b8d3", # TestAppPw2 + "4939efa7c87095dacb5e7e8b8cfb3a660fa1f5edcc9108f6d7ec20ea4d6b3a88", # TestAppPw3 + ] + +################# +# The groups section contains a hardcoded list of valid users. +[[groups]] + name = "superheros" + gidnumber = 5501 + +[[groups]] + name = "svcaccts" + gidnumber = 5502 + +[[groups]] + name = "vpn" + gidnumber = 5503 + includegroups = [ 5501 ] + diff --git a/.circleci/pgcat_ldap.toml b/.circleci/pgcat_ldap.toml new file mode 100644 index 00000000..452eb110 --- /dev/null +++ b/.circleci/pgcat_ldap.toml @@ -0,0 +1,25 @@ + +[general] +host = "0.0.0.0" +port = 6432 +admin_username = "admin_user" +admin_password = "" +admin_auth_type = "ldap" +admin_auth_ldapurl = "ldap://127.0.0.1:3893" +admin_auth_ldapsuffix = "@example.com" + +[pools.sharded_db.users.0] +username = "sharding_user" +password = "sharding_user" +auth_type = "ldap" +auth_ldapurl = "ldap://127.0.0.1:3893" +auth_ldapsuffix = "@example.com" +pool_size = 10 +min_pool_size = 1 +pool_mode = "transaction" + +[pools.sharded_db.shards.0] +servers = [ + [ "127.0.0.1", 5432, "primary" ], +] +database = "shard0" diff --git a/.circleci/pgcat_trust.toml b/.circleci/pgcat_trust.toml index 98d21c95..7e33ac8a 100644 --- a/.circleci/pgcat_trust.toml +++ b/.circleci/pgcat_trust.toml @@ -1,6 +1,5 @@ [general] - host = "0.0.0.0" port = 6432 admin_username = "admin_user" diff --git a/tests/docker/Dockerfile b/tests/docker/Dockerfile index 6eccddd1..553dd613 100644 --- a/tests/docker/Dockerfile +++ b/tests/docker/Dockerfile @@ -6,6 +6,8 @@ RUN apt-get update && apt-get install llvm-11 psmisc postgresql-contrib postgres RUN cargo install cargo-binutils rustfilt RUN rustup component add llvm-tools-preview RUN sudo gem install bundler +RUN wget -O /usr/bin/glauth https://github.com/glauth/glauth/releases/download/v2.3.2/glauth-linux-amd64 +RUN chmod +x /usr/bin/glauth RUN wget -O toxiproxy-2.4.0.deb https://github.com/Shopify/toxiproxy/releases/download/v2.4.0/toxiproxy_2.4.0_linux_$(dpkg --print-architecture).deb && \ sudo dpkg -i toxiproxy-2.4.0.deb RUN wget -O go1.21.3.linux-$(dpkg --print-architecture).tar.gz https://go.dev/dl/go1.21.3.linux-$(dpkg --print-architecture).tar.gz && \ diff --git a/tests/python/tests.py b/tests/python/tests.py index 3ce4cb9a..13478e4e 100644 --- a/tests/python/tests.py +++ b/tests/python/tests.py @@ -11,16 +11,43 @@ PGCAT_PORT = "6432" -def pgcat_start(): - pg_cat_send_signal(signal.SIGTERM) - os.system("./target/debug/pgcat .circleci/pgcat.toml &") +def ldap_start(): + glauth_send_signal(signal.SIGTERM) + os.system("glauth -c .circleci/glauth.cfg &") time.sleep(2) -def pgcat_trust_start(): + +def pgcat_start_inner(config_path: str): pg_cat_send_signal(signal.SIGTERM) - os.system("./target/debug/pgcat .circleci/pgcat_trust.toml &") + os.system(f"./target/debug/pgcat {config_path} &") time.sleep(2) +def pgcat_start(): + pgcat_start_inner(config_path='.circleci/pgcat.toml') + + +def pgcat_trust_start(): + pgcat_start_inner(config_path='.circleci/pgcat_trust.toml') + + +def pgcat_ldap_start(): + pgcat_start_inner(config_path='.circleci/pgcat_ldap.toml') + +def glauth_send_signal(signal: signal.Signals): + try: + for proc in psutil.process_iter(["pid", "name"]): + if "glauth" == proc.name(): + os.kill(proc.pid, signal) + except Exception as e: + # The process can be gone when we send this signal + print(e) + + if signal == signal.SIGTERM: + # Returns 0 if pgcat process exists + time.sleep(2) + if not os.system('pgrep glauth'): + raise Exception("glauth not closed after SIGTERM") + def pg_cat_send_signal(signal: signal.Signals): try: @@ -51,7 +78,7 @@ def connect_db_trust( db = "sharded_db" conn = psycopg2.connect( - f"postgres://{user}:@{PGCAT_HOST}:{PGCAT_PORT}/{db}?application_name=testing_pgcat", + f"postgres://{user}@{PGCAT_HOST}:{PGCAT_PORT}/{db}?application_name=testing_pgcat", connect_timeout=2, ) conn.autocommit = autocommit @@ -59,6 +86,28 @@ def connect_db_trust( return (conn, cur) +def connect_db_ldap( + autocommit: bool = True, + admin: bool = False, +) -> Tuple[psycopg2.extensions.connection, psycopg2.extensions.cursor]: + + if admin: + user = "admin_user" + password = "dogood" + db = "pgcat" + else: + user = "sharding_user" + password = "dogood" + db = "sharded_db" + + conn = psycopg2.connect( + f"postgres://{user}:{password}@{PGCAT_HOST}:{PGCAT_PORT}/{db}?application_name=testing_pgcat", + connect_timeout=2, + ) + conn.autocommit = autocommit + cur = conn.cursor() + + return (conn, cur) def connect_db( autocommit: bool = True, @@ -104,6 +153,30 @@ def test_normal_trust_auth(): print(res) cleanup_conn(conn, cur) +def test_normal_ldap_auth(): + conn, cur = connect_db_ldap(autocommit=False) + cur.execute("SELECT 1") + res = cur.fetchall() + print(res) + cleanup_conn(conn, cur) + +def test_admin_ldap_auth(): + conn, cur = connect_db_ldap(admin=True) + cur.execute("SHOW POOLS") + res = cur.fetchall() + print(res) + cleanup_conn(conn, cur) + +def test_ldap(): + ldap_start() + pgcat_ldap_start() + + test_admin_ldap_auth() + test_normal_ldap_auth() + + glauth_send_signal(signal.SIGTERM) + pg_cat_send_signal(signal.SIGTERM) + def test_trust(): pgcat_trust_start() @@ -370,3 +443,4 @@ def test_shutdown_logic(): test_shutdown_logic() test_trust() +test_ldap()