Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
567ce2c
feat: add gatekeeper
staaldraad Aug 25, 2025
c2e8bce
test: custom flake
staaldraad Aug 25, 2025
5bd75d9
feat: use gatekeeper package from upstream private repo
samrose Aug 25, 2025
6cb4ef1
chore: add overlay
staaldraad Aug 26, 2025
9c9a43e
chore: add deploy_key for gk repo
staaldraad Aug 26, 2025
60a1bae
fix: fmt and go version, hopefully
staaldraad Aug 26, 2025
e873fd1
fix: fmt and go version, hopefully
staaldraad Aug 26, 2025
2f76ec4
fix: pass go override in overlays
staaldraad Aug 26, 2025
659f071
fix: pass go override in overlays
staaldraad Aug 27, 2025
e100010
feat: package gatekeeper in this package set
samrose Aug 28, 2025
a1fc278
fix: update source of go 1.24 nixpkgs
samrose Aug 28, 2025
b6673b9
Revert "fix: update source of go 1.24 nixpkgs"
samrose Aug 28, 2025
aa52b78
Revert "feat: package gatekeeper in this package set"
samrose Aug 28, 2025
29a0026
fix: clean up nix flake and lock, drop overlay
samrose Aug 28, 2025
dad6e5b
chore: install gatekeeper with ansible
staaldraad Aug 29, 2025
9ea8c88
fix: smallest typo
staaldraad Aug 29, 2025
f12bd69
Apply suggestion from @hunleyd
staaldraad Aug 29, 2025
971e30e
fix: syntax error
staaldraad Aug 29, 2025
73040d5
test: some sanity tests for jit pam module
samrose Sep 12, 2025
e953383
fix: get treefmt to pass
samrose Sep 12, 2025
7673932
test: more fixes to test`
samrose Sep 12, 2025
3d63bf9
chore: rebase and small changes from review
staaldraad Oct 10, 2025
76ac77d
chore: ruff
staaldraad Oct 10, 2025
95ff6b3
chore: rebase and bump
staaldraad Oct 23, 2025
fef2cba
fix: catchup to develop
staaldraad Oct 27, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/nix-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
fail-fast: false
matrix:
include:
- runner: blacksmith-32vcpu-ubuntu-2404
- runner: blacksmith-32vcpu-ubuntu-2404
arch: amd64
- runner: blacksmith-32vcpu-ubuntu-2404-arm
arch: arm64
Expand Down Expand Up @@ -110,7 +110,7 @@ jobs:
df -h
- name: Build psql bundle
run: >
nix run "github:Mic92/nix-fast-build?rev=b1dae483ab7d4139a6297e02b6de9e5d30e43d48"
nix run "github:Mic92/nix-fast-build?rev=b1dae483ab7d4139a6297e02b6de9e5d30e43d48"
-- --skip-cached --no-nom ${{ matrix.runner == 'macos-latest-xlarge' && '--max-jobs 1' || '' }}
--flake ".#checks.$(nix eval --raw --impure --expr 'builtins.currentSystem')"
env:
Expand Down
13 changes: 13 additions & 0 deletions ansible/tasks/setup-postgres.yml
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,19 @@
group: 'postgres'
src: 'files/postgresql_config/custom_read_replica.conf.j2'

- name: Check if psql_version is psql_15
set_fact:
is_psql_15: "{{ psql_version in ['psql_15'] }}"

- name: create placeholder pam config
file:
path: '/etc/pam.d/postgresql'
state: touch
owner: postgres
group: postgres
mode: 0664
when: not is_psql_15

# Install extensions before init
- name: Install Postgres extensions
ansible.builtin.import_tasks:
Expand Down
21 changes: 20 additions & 1 deletion ansible/tasks/stage2-setup-postgres.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,26 @@
shell: |
sudo -u postgres bash -c ". /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh && nix profile install github:supabase/postgres/{{ git_commit_sha }}#{{postgresql_version}}_src"
when: stage2_nix


- name: Check if psql_version is psql_15
set_fact:
is_psql_15: "{{ psql_version == 'psql_15' }}"

- name: Install gatekeeper if not pg15
when:
- stage2_nix
- not is_psql_15
block:
- name: Install gatekeeper from nix binary cache
become: yes
shell: |
sudo -u postgres bash -c ". /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh && nix profile install github:supabase/postgres/{{ git_commit_sha }}#gatekeeper"

- name: Create symbolic link for linux-pam to find pam_jit_pg.so
become: yes
shell: |
sudo ln -s /var/lib/postgresql/.nix-profile/lib/security/pam_jit_pg.so $(find /nix/store -type d -path "/nix/store/*-linux-pam-*/lib/security" -print -quit)/pam_jit_pg.so
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we trying to write in the store here ? Did you mean /usr/lib/x86_64-linux-gnu/security/pam_jit_pg.so where all the other pam modules are deployed in distribution like Ubuntu ?

Do we really need to copy that module if we can specify the full module path in the pam configuration (/etc/pam.d/postgresql) ?

auth required /var/lib/postgresql/.nix-profile/lib/security/pam_jwt_pg.so jwks=https://auth.supabase.green/auth/v1/.well-known/jwks.json mappings=/tmp/users.yaml
account required /var/lib/postgresql/.nix-profile/lib/security/pam_jwt_pg.so jwks=https://auth.supabase.green/auth/v1/.well-known/jwks.json mappings=/tmp/users.yaml

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did not try with the full path, nice!

Did you mean /usr/lib/x86_64-linux-gnu/security/pam_jit_pg.so

Yes original intention was to use that location, but during testing pam was failing to lookup the module and was looking in the store instead. Full paths would solve this


- name: Set ownership and permissions for /etc/ssl/private
become: yes
file:
Expand Down
6 changes: 3 additions & 3 deletions ansible/vars.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ postgres_major:

# Full version strings for each major version
postgres_release:
postgresorioledb-17: "17.5.1.047-orioledb"
postgres17: "17.6.1.026"
postgres15: "15.14.1.026"
postgresorioledb-17: "17.5.1.051-orioledb"
postgres17: "17.6.1.030"
postgres15: "15.14.1.030"

# Non Postgres Extensions
pgbouncer_release: 1.19.0
Expand Down
6 changes: 5 additions & 1 deletion nix/packages/default.nix
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
{ self, inputs, ... }:
{
imports = [ ./postgres.nix ];
imports = [
./postgres.nix
# ./gatekeeper.nix
];
perSystem =
{
inputs',
Expand Down Expand Up @@ -34,6 +37,7 @@
cleanup-ami = pkgs.callPackage ./cleanup-ami.nix { };
dbmate-tool = pkgs.callPackage ./dbmate-tool.nix { inherit (self.supabase) defaults; };
docs = pkgs.callPackage ./docs.nix { };
gatekeeper = pkgs.callPackage ./gatekeeper.nix { inherit inputs pkgs; };
supabase-groonga = pkgs.callPackage ./groonga { };
http-mock-server = pkgs.callPackage ./http-mock-server.nix { };
local-infra-bootstrap = pkgs.callPackage ./local-infra-bootstrap.nix { };
Expand Down
50 changes: 50 additions & 0 deletions nix/packages/gatekeeper.nix
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to declare the package here if the same package is publicly available in https://github.com/supabase/jit-db-gatekeeper/blob/ac9c0ddef7a31f4143674a095e5bd96aee984685/default.nix ?
We could use it as an input to this flake and specify the version we rely on in the flake input parameters.

Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
inputs,
system,
pkgs,
...
}:
let
go124 = inputs.nixpkgs-go124.legacyPackages.${system}.go_1_24;
# Use completely clean nixpkgs without any overlays for gatekeeper
#cleanPkgs = inputs.nixpkgs.legacyPackages.${system};
buildGoModule = pkgs.buildGoModule.override { go = go124; };
in

buildGoModule {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As jit-db-gatekeeper contains unittest, it might be worth adding a check to run them:

  checkPhase = ''
    runHook preCheck
    go test -v ./...
    runHook postCheck
  '';

pname = "gatekeeper";
version = "0.1.0";

src = pkgs.fetchFromGitHub {
owner = "supabase";
repo = "jit-db-gatekeeper";
rev = "v1.0.0";
hash = "sha256-hrYh1dBxk+aN3b/J9mZqk/ZXHmWA/MIqZLVgICT7e90=";
};

vendorHash = "sha256-G9x2TARSJMn30R6ZOlsggxEtn5t2ezWz1YtkLXdYiAE=";

buildInputs = [
pkgs.pam
] ++ pkgs.lib.optionals pkgs.stdenv.isDarwin [ pkgs.darwin.apple_sdk.frameworks.Security ];

buildPhase = ''
runHook preBuild
go build -buildmode=c-shared -o pam_jit_pg.so
runHook postBuild
'';

installPhase = ''
runHook preInstall
mkdir -p $out/lib/security
cp pam_jit_pg.so $out/lib/security/
runHook postInstall
'';

meta = with pkgs.lib; {
description = "PAM module for JWT authentication with PostgreSQL backend";
homepage = "https://github.com/supabase/jit-db-gatekeeper";
license = licenses.mit;
platforms = platforms.unix;
};
}
221 changes: 221 additions & 0 deletions testinfra/test_ami_nix.py
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,227 @@ def test_libpq5_version(host):
print("✓ libpq5 version is >= 14")


def test_jit_pam_module_installed(host):
"""Test that the JIT PAM module (pam_jit_pg.so) is properly installed."""
# Check PostgreSQL version first
result = run_ssh_command(
host["ssh"], "sudo -u postgres psql --version | grep -oE '[0-9]+' | head -1"
)
pg_major_version = 15 # Default
if result["succeeded"] and result["stdout"].strip():
try:
pg_major_version = int(result["stdout"].strip())
except ValueError:
pass
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We want to know if we cannot parse the postgresql version. We should fail instead of using a default value.


# Skip test for PostgreSQL 15 as gatekeeper is not installed for PG15
if pg_major_version == 15:
print("\nSkipping JIT PAM module test for PostgreSQL 15 (not installed)")
return

# Check if gatekeeper is installed via Nix
result = run_ssh_command(
host["ssh"],
"sudo -u postgres ls -la /var/lib/postgresql/.nix-profile/lib/security/pam_jit_pg.so 2>/dev/null",
)
if result["succeeded"]:
print(f"\nJIT PAM module found in Nix profile:\n{result['stdout']}")
else:
print("\nJIT PAM module not found in postgres user's Nix profile")
assert False, "JIT PAM module (pam_jit_pg.so) not found in expected location"

# Check if the symlink exists in the Linux PAM security directory
result = run_ssh_command(
host["ssh"],
"find /nix/store -type f -path '*/lib/security/pam_jit_pg.so' 2>/dev/null | head -5",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be related to a previous comment but this will return the lib in the gatekeeper package like this: /nix/store/miwaglm79i2vpilmp8rxd2mymjs7nibz-gatekeeper-0.1.0/lib/security/pam_jit_pg.so. I guess we want to check that /usr/lib/x86_64-linux-gnu/security/pam_jit_pg.so exists instead ?

)
if result["succeeded"] and result["stdout"].strip():
print(f"\nJIT PAM module symlinks found:\n{result['stdout']}")
else:
print("\nNo JIT PAM module symlinks found in /nix/store")

# Verify the module is a valid shared library
result = run_ssh_command(
host["ssh"], "file /var/lib/postgresql/.nix-profile/lib/security/pam_jit_pg.so"
)
if result["succeeded"]:
print(f"\nJIT PAM module file type:\n{result['stdout']}")
assert (
"shared object" in result["stdout"].lower()
or "dynamically linked" in result["stdout"].lower()
), "JIT PAM module is not a valid shared library"

print("✓ JIT PAM module is properly installed")


def test_pam_postgresql_config(host):
"""Test that the PAM configuration for PostgreSQL exists and is properly configured."""
# Check PostgreSQL version to determine if PAM config should exist
result = run_ssh_command(
host["ssh"], "sudo -u postgres psql --version | grep -oE '[0-9]+' | head -1"
)
pg_major_version = 15 # Default
if result["succeeded"] and result["stdout"].strip():
try:
pg_major_version = int(result["stdout"].strip())
except ValueError:
pass

print(f"\nPostgreSQL major version: {pg_major_version}")

# PAM config should exist for non-PostgreSQL 15 versions
if pg_major_version != 15:
# Check if PAM config file exists
result = run_ssh_command(host["ssh"], "ls -la /etc/pam.d/postgresql")
if result["succeeded"]:
print(f"\nPAM config file found:\n{result['stdout']}")

# Check file permissions
result = run_ssh_command(
host["ssh"], "stat -c '%a %U %G' /etc/pam.d/postgresql"
)
if result["succeeded"]:
perms = result["stdout"].strip()
print(f"PAM config permissions: {perms}")
# Should be owned by postgres:postgres with 664 permissions
assert (
"postgres postgres" in perms
), "PAM config not owned by postgres:postgres"
else:
print("\nPAM config file not found")
assert False, "PAM configuration file /etc/pam.d/postgresql not found"
else:
print("\nSkipping PAM config check for PostgreSQL 15")
# For PostgreSQL 15, the PAM config should NOT exist
result = run_ssh_command(host["ssh"], "test -f /etc/pam.d/postgresql")
if result["succeeded"]:
print("\nWARNING: PAM config exists for PostgreSQL 15 (not expected)")

print("✓ PAM configuration is properly set up")


def test_jit_pam_gatekeeper_profile(host):
"""Test that the gatekeeper package is properly installed in the postgres user's Nix profile."""
# Check PostgreSQL version first
result = run_ssh_command(
host["ssh"], "sudo -u postgres psql --version | grep -oE '[0-9]+' | head -1"
)
pg_major_version = 15 # Default
if result["succeeded"] and result["stdout"].strip():
try:
pg_major_version = int(result["stdout"].strip())
except ValueError:
pass

# Skip test for PostgreSQL 15 as gatekeeper is not installed for PG15
if pg_major_version == 15:
print("\nSkipping gatekeeper profile test for PostgreSQL 15 (not installed)")
return

# Check if gatekeeper is in the postgres user's Nix profile
result = run_ssh_command(
host["ssh"],
"sudo -u postgres nix profile list --json | jq -r '.elements.gatekeeper.storePaths[0]'",
)
if result["succeeded"] and result["stdout"].strip():
print(f"\nGatekeeper found in Nix profile:\n{result['stdout']}")
else:
# Try alternative check
result = run_ssh_command(
host["ssh"],
"sudo -u postgres ls -la /var/lib/postgresql/.nix-profile/ | grep -i gate",
)
if result["succeeded"] and result["stdout"].strip():
print(f"\nGatekeeper-related files in profile:\n{result['stdout']}")
else:
print("\nGatekeeper not found in postgres user's Nix profile")
# This might be expected if it's installed system-wide instead

# Check if we can find the gatekeeper derivation
result = run_ssh_command(
host["ssh"],
"find /nix/store -maxdepth 1 -type d -name '*gatekeeper*' 2>/dev/null | head -5",
)
if result["succeeded"] and result["stdout"].strip():
print(f"\nGatekeeper derivations found:\n{result['stdout']}")
else:
print("\nNo gatekeeper derivations found in /nix/store")

print("✓ Gatekeeper package installation check completed")


def test_jit_pam_module_dependencies(host):
"""Test that the JIT PAM module has all required dependencies."""
# Check PostgreSQL version first
result = run_ssh_command(
host["ssh"], "sudo -u postgres psql --version | grep -oE '[0-9]+' | head -1"
)
pg_major_version = 15 # Default
if result["succeeded"] and result["stdout"].strip():
try:
pg_major_version = int(result["stdout"].strip())
except ValueError:
pass

# Skip test for PostgreSQL 15 as gatekeeper is not installed for PG15
if pg_major_version == 15:
print(
"\nSkipping JIT PAM module dependencies test for PostgreSQL 15 (not installed)"
)
return

# Check dependencies of the PAM module
result = run_ssh_command(
host["ssh"],
"ldd /var/lib/postgresql/.nix-profile/lib/security/pam_jit_pg.so 2>/dev/null",
)
if result["succeeded"]:
print(f"\nJIT PAM module dependencies:\n{result['stdout']}")

# Check for required libraries
required_libs = ["libpam", "libc"]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that these dynamic dependencies/libraries are not coming from Ubuntu but from Nix which could cause problem as Nix and Ubuntu might not use the same PAM version. In the following test, we see that the module is loading PAM 1.6.0 but that version of Ubuntu is using PAM 1.5.3:

$ ldd /var/lib/postgresql/.nix-profile/lib/security/pam_jit_pg.so
        linux-vdso.so.1 (0x00007fffa3338000)
        libpam.so.0 => /nix/store/k491acz8rcfhrpivv0rg6q83a14zss2j-linux-pam-1.6.0/lib/libpam.so.0 (0x00007fe0c901c000)
        libpthread.so.0 => /nix/store/ddwyrxif62r8n6xclvskjyy6szdhvj60-glibc-2.39-5/lib/libpthread.so.0 (0x00007fe0c9017000)
        libresolv.so.2 => /nix/store/ddwyrxif62r8n6xclvskjyy6szdhvj60-glibc-2.39-5/lib/libresolv.so.2 (0x00007fe0c9006000)
        libc.so.6 => /nix/store/ddwyrxif62r8n6xclvskjyy6szdhvj60-glibc-2.39-5/lib/libc.so.6 (0x00007fe0c8613000)
        libaudit.so.1 => /nix/store/0i8hhak73jnlilfgfsh1wh0fd53pb0r9-audit-3.1.2/lib/libaudit.so.1 (0x00007fe0c8fd1000)
$ patchelf --print-rpath /root/.nix-profile/lib/security/pam_jit_pg.so
/nix/store/k491acz8rcfhrpivv0rg6q83a14zss2j-linux-pam-1.6.0/lib:/nix/store/ddwyrxif62r8n6xclvskjyy6szdhvj60-glibc-2.39-5/lib
$ dpkg -l libpam-runtime
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name           Version          Architecture Description
+++-==============-================-============-===================================
ii  libpam-runtime 1.5.3-5ubuntu5.4 all          Runtime support for the PAM library

We can instead remove the rpath and let the dynamic linker do its job (without looking at other nix libraries):

$ cp /var/lib/postgres/.nix-profile/lib/security/pam_jit_pg.so /usr/lib/x86_64-linux-gnu/security/
$ patchelf --remove-rpath /usr/lib/x86_64-linux-gnu/security/pam_jit_pg.so
$ ldd /usr/lib/x86_64-linux-gnu/security/pam_jit_pg.so
        linux-vdso.so.1 (0x00007fff3179e000)
        libpam.so.0 => /lib/x86_64-linux-gnu/libpam.so.0 (0x000078aa645ea000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x000078aa645e5000)
        libresolv.so.2 => /lib/x86_64-linux-gnu/libresolv.so.2 (0x000078aa645d2000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x000078aa63a00000)
        libaudit.so.1 => /lib/x86_64-linux-gnu/libaudit.so.1 (0x000078aa645a4000)
        /lib64/ld-linux-x86-64.so.2 (0x000078aa64602000)
        libcap-ng.so.0 => /lib/x86_64-linux-gnu/libcap-ng.so.0 (0x000078aa6459a000)

We could remove that rpath after the build of the package:

  postFixup = ''
    patchelf --remove-rpath $out/lib/security/pam_jit_pg.so
  '';

But still there might be other surprises as the gatekeeper module has been build based on PAM 1.6.0.
Usually PAM has a good backward compatibility and the amount of dyn symbols used by gatekeeper is rather limited:

$ objdump -T /var/lib/postgres/.nix-profile/lib/security/pam_jit_pg.so | grep PAM
0000000000000000      DF *UND*  0000000000000000 (LIBPAM_1.0) pam_strerror
0000000000000000      DF *UND*  0000000000000000 (LIBPAM_EXTENSION_1.0) pam_syslog
0000000000000000      DF *UND*  0000000000000000 (LIBPAM_1.0) pam_get_item
0000000000000000      DF *UND*  0000000000000000 (LIBPAM_1.0) pam_get_user
0000000000000000      DF *UND*  0000000000000000 (LIBPAM_EXTENSION_1.1) pam_get_authtok

If (and only if) we face issue (I would test if further first), I would build it against the same version using https://lazamar.co.uk/nix-versions/?package=linux-pam&version=1.5.3&fullName=linux-pam-1.5.3&keyName=linux-pam&revision=7a339d87931bba829f68e94621536cad9132971a&channel=nixpkgs-unstable#instructions

We might want to create an automated test that exercice the module using pamtester just to verify that we don't get any dlopen errors in the logs.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we were/are building against 1.6.0 because of postgresql having been built against it (and hence also the hackery of copying the .so to /nix/store/*-linux-pam-*/lib/security because the linker looks for the modules there instead of the default Ubuntu path)

$ patchelf --print-rpath /nix/store/2x79j9fi9j13hhf5n0yc9825qa4nynv3-postgresql-and-plugins-17.6/bin/.postgres-wrapped
/nix/store/bvjhqzpwbzmfi350nir8gf7h45igvp5z-libxml2-2.12.6/lib:/nix/store/wcwqdhl9jpwgj1fdr0pw9dbaf5m43f17-lz4-1.9.4/lib:/nix/store/mxvqrp4jj6zklxc1i32ra8iapnzynyzc-zstd-1.5.5/lib:/nix/store/ram2bh4rs56rp8sr0gcdb108wcc609si-icu4c-73.2/lib:/nix/store/ymav8nb29vsdryddi435xcig3pk7i00q-zlib-1.3.1/lib:/nix/store/0kfbzhd8qdsxsd4qf9dkpcd3f916krvr-openssl-3.0.13/lib:/nix/store/ss6bfrdx69ng9f448d5hq1683hkpxcng-systemd-255.4/lib:/nix/store/vaz0prypndg3y6zxmdcpabinwg9dmmq9-libkrb5-1.21.2/lib:/nix/store/4rdpzzfssknp4k4cn59wc7xcdiyv9j53-linux-pam-1.6.0/lib:/nix/store/10pd749c2v3m35d4hk5xdfylyfr1hzqz-glibc-2.39-5/lib

-->

/nix/store/4rdpzzfssknp4k4cn59wc7xcdiyv9j53-linux-pam-1.6.0/lib

Tried modifying the rpath on postgres-wrapped but that leads to problems looking up libaudit.so.1 (even though it is in the new rpath and when specifying the path manually to the location in the store)

for lib in required_libs:
if lib not in result["stdout"].lower():
print(f"WARNING: Required library {lib} not found in dependencies")

# Check for any missing dependencies
if "not found" in result["stdout"].lower():
assert False, "JIT PAM module has missing dependencies"
else:
print("\nCould not check JIT PAM module dependencies")

print("✓ JIT PAM module dependencies are satisfied")


def test_jit_pam_postgresql_integration(host):
"""Test that PostgreSQL can be configured to use PAM authentication."""
# Check if PAM is available as an authentication method in PostgreSQL
result = run_ssh_command(
host["ssh"],
"sudo -u postgres psql -c \"SELECT name, setting FROM pg_settings WHERE name LIKE '%pam%';\" 2>/dev/null",
)
if result["succeeded"]:
print(f"\nPostgreSQL PAM-related settings:\n{result['stdout']}")

# Check pg_hba.conf for potential PAM entries (even if not currently active)
result = run_ssh_command(
host["ssh"],
"grep -i pam /etc/postgresql/pg_hba.conf 2>/dev/null || echo 'No PAM entries in pg_hba.conf'",
)
if result["succeeded"]:
print(f"\nPAM entries in pg_hba.conf:\n{result['stdout']}")

# Verify PostgreSQL was compiled with PAM support
result = run_ssh_command(
host["ssh"],
"sudo -u postgres pg_config --configure 2>/dev/null | grep -i pam || echo 'PAM compile flag not found'",
)
if result["succeeded"]:
print(f"\nPostgreSQL PAM compile flags:\n{result['stdout']}")

print("✓ PostgreSQL PAM integration check completed")


def test_postgrest_read_only_session_attrs(host):
"""Test PostgREST with target_session_attrs=read-only and check for session errors."""
# First, check if PostgreSQL is configured for read-only mode
Expand Down