Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
77 changes: 39 additions & 38 deletions .github/workflows/integration_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,52 +9,53 @@ on:

jobs:
integration-test:
if: ${{ github.event_name != 'pull_request' || startsWith(github.event.pull_request.title, 'build(deps)') }}
# if: ${{ github.event_name != 'pull_request' || startsWith(github.event.pull_request.title, 'build(deps)') }}
if: ${{ github.event_name == 'pull_request' || startsWith(github.event.pull_request.title, 'build(deps)') }}
runs-on: ubuntu-latest-32
env:
CGO_ENABLED: 0
strategy:
fail-fast: false
matrix:
package:
- ./internal/impl/amqp09
- ./internal/impl/amqp1
- ./internal/impl/aws
# - ./internal/impl/azure
# - ./internal/impl/beanstalkd
- ./internal/impl/cassandra
- ./internal/impl/cockroachdb
# - ./internal/impl/couchbase
- ./internal/impl/elasticsearch/v8
- ./internal/impl/elasticsearch/v9
# - ./internal/impl/gcp
- ./internal/impl/gcp/enterprise
# - ./internal/impl/gcp/enterprise/changestreams
# - ./internal/impl/gcp/enterprise/changestreams/metadata
- ./internal/impl/hdfs
- ./internal/impl/influxdb
# - ./internal/impl/kafka
- ./internal/impl/kafka/enterprise
- ./internal/impl/memcached
- ./internal/impl/mssqlserver
- ./internal/impl/mongodb
- ./internal/impl/mongodb/cdc
# - ./internal/impl/mqtt
- ./internal/impl/mysql
# - ./internal/impl/nanomsg
# - ./internal/impl/nats
- ./internal/impl/nsq
- ./internal/impl/opensearch
# - ./internal/impl/amqp09
# - ./internal/impl/amqp1
# - ./internal/impl/aws
# # - ./internal/impl/azure
# # - ./internal/impl/beanstalkd
# - ./internal/impl/cassandra
# - ./internal/impl/cockroachdb
# # - ./internal/impl/couchbase
# - ./internal/impl/elasticsearch/v8
# - ./internal/impl/elasticsearch/v9
# # - ./internal/impl/gcp
# - ./internal/impl/gcp/enterprise
# # - ./internal/impl/gcp/enterprise/changestreams
# # - ./internal/impl/gcp/enterprise/changestreams/metadata
# - ./internal/impl/hdfs
# - ./internal/impl/influxdb
# # - ./internal/impl/kafka
# - ./internal/impl/kafka/enterprise
# - ./internal/impl/memcached
# - ./internal/impl/mssqlserver
# - ./internal/impl/mongodb
# - ./internal/impl/mongodb/cdc
# # - ./internal/impl/mqtt
# - ./internal/impl/mysql
# # - ./internal/impl/nanomsg
# # - ./internal/impl/nats
# - ./internal/impl/nsq
# - ./internal/impl/opensearch
- ./internal/impl/postgresql
- ./internal/impl/pulsar
- ./internal/impl/qdrant
# - ./internal/impl/questdb
- ./internal/impl/redis
- ./internal/impl/redpanda/migrator
- ./internal/impl/sftp
# - ./internal/impl/snowflake
- ./internal/impl/snowflake/streaming
# - ./internal/impl/splunk
# - ./internal/impl/pulsar
# - ./internal/impl/qdrant
# # - ./internal/impl/questdb
# - ./internal/impl/redis
# - ./internal/impl/redpanda/migrator
# - ./internal/impl/sftp
# # - ./internal/impl/snowflake
# - ./internal/impl/snowflake/streaming
# # - ./internal/impl/splunk
# - ./internal/impl/sql

# Requires CGO_ENABLED=1
Expand Down
126 changes: 102 additions & 24 deletions internal/impl/postgresql/ssl_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,15 +111,6 @@ hostssl all all all cert clientcert=%s
Cmd: []string{
"postgres",
"-c", "wal_level=logical",
"-c", "ssl=on",
"-c", "ssl_cert_file=/var/lib/postgresql/server.crt",
"-c", "ssl_key_file=/var/lib/postgresql/server.key",
"-c", "ssl_ca_file=/var/lib/postgresql/ca.crt",
},
Mounts: []string{
fmt.Sprintf("%s:/var/lib/postgresql/server.crt", certs.serverCert),
fmt.Sprintf("%s:/var/lib/postgresql/server.key", certs.serverKey),
fmt.Sprintf("%s:/var/lib/postgresql/ca.crt", certs.caCert),
},
}, func(config *docker.HostConfig) {
config.AutoRemove = true
Expand All @@ -131,24 +122,61 @@ hostssl all all all cert clientcert=%s
assert.NoError(t, pool.Purge(resource))
})

// Overwrite pg_hba.conf to enforce SSL
for range 10 {
time.Sleep(1 * time.Second)
_, err = resource.Exec([]string{"bash", "-c", fmt.Sprintf("echo '%s' > /var/lib/postgresql/data/pg_hba.conf", pgHbaContent)}, dockertest.ExecOptions{})
if err != nil {
continue
}
_, err = resource.Exec([]string{"pg_ctl", "reload"}, dockertest.ExecOptions{})
if err != nil {
continue
}
}
require.NoError(t, err, "Exhausted all retires updating container configuration")

// Wait for PostgreSQL to be ready
hostAndPort := resource.GetHostPort("5432/tcp")
dsn := fmt.Sprintf("user=testuser password='l]YLSc|4[i56_@{gY' dbname=dbname sslmode=disable host=%s port=%s", strings.Split(hostAndPort, ":")[0], strings.Split(hostAndPort, ":")[1])

var db *sql.DB
pool.MaxWait = 120 * time.Second
require.NoError(t, pool.Retry(func() error {
var err error
db, err = sql.Open("postgres", dsn)
if err != nil {
return err
}
return db.Ping()
}))

// Copy certificate files into container with proper ownership
caCertContent, err := os.ReadFile(certs.caCert)
require.NoError(t, err)
serverCertContent, err := os.ReadFile(certs.serverCert)
require.NoError(t, err)
serverKeyContent, err := os.ReadFile(certs.serverKey)
require.NoError(t, err)

_, err = resource.Exec([]string{"bash", "-c", fmt.Sprintf("cat > /var/lib/postgresql/ca.crt << 'EOF'\n%s\nEOF", string(caCertContent))}, dockertest.ExecOptions{})
require.NoError(t, err)
_, err = resource.Exec([]string{"bash", "-c", fmt.Sprintf("cat > /var/lib/postgresql/server.crt << 'EOF'\n%s\nEOF", string(serverCertContent))}, dockertest.ExecOptions{})
require.NoError(t, err)
_, err = resource.Exec([]string{"bash", "-c", fmt.Sprintf("cat > /var/lib/postgresql/server.key << 'EOF'\n%s\nEOF", string(serverKeyContent))}, dockertest.ExecOptions{})
require.NoError(t, err)

// Fix ownership and permissions (PostgreSQL requires key file to be owned by postgres with mode 0600)
_, err = resource.Exec([]string{"chown", "postgres:postgres", "/var/lib/postgresql/server.key", "/var/lib/postgresql/server.crt", "/var/lib/postgresql/ca.crt"}, dockertest.ExecOptions{})
require.NoError(t, err)
_, err = resource.Exec([]string{"chmod", "0600", "/var/lib/postgresql/server.key"}, dockertest.ExecOptions{})
require.NoError(t, err)
_, err = resource.Exec([]string{"chmod", "0644", "/var/lib/postgresql/server.crt", "/var/lib/postgresql/ca.crt"}, dockertest.ExecOptions{})
require.NoError(t, err)

// Update postgresql.conf to enable SSL
_, err = resource.Exec([]string{"bash", "-c", `cat >> /var/lib/postgresql/data/postgresql.conf << 'EOF'
ssl = on
ssl_cert_file = '/var/lib/postgresql/server.crt'
ssl_key_file = '/var/lib/postgresql/server.key'
ssl_ca_file = '/var/lib/postgresql/ca.crt'
EOF
`}, dockertest.ExecOptions{})
require.NoError(t, err)

// Close the old connection before restart
require.NoError(t, db.Close())

// Restart PostgreSQL to enable SSL (SSL requires restart, not just reload)
require.NoError(t, pool.Client.RestartContainer(resource.Container.ID, 10))

// Reconnect after restart (SSL is now enabled, but pg_hba.conf still allows non-SSL)
require.NoError(t, pool.Retry(func() error {
var err error
db, err = sql.Open("postgres", dsn)
Expand All @@ -165,7 +193,57 @@ hostssl all all all cert clientcert=%s
_, err = db.Exec("CREATE TABLE IF NOT EXISTS test_table (id serial PRIMARY KEY, content VARCHAR(50));")
require.NoError(t, err)

return resource, db
// Now close the non-SSL connection before enforcing SSL-only via pg_hba.conf
require.NoError(t, db.Close())

// Overwrite pg_hba.conf to enforce SSL
for i := range 10 {
if i > 0 {
time.Sleep(2 * time.Second)
}
_, err = resource.Exec([]string{"bash", "-c", fmt.Sprintf("cat > /var/lib/postgresql/data/pg_hba.conf << 'EOF'\n%s\nEOF", pgHbaContent)}, dockertest.ExecOptions{})
if err != nil {
t.Logf("Failed to write pg_hba.conf: %v", err)
continue
}
_, err = resource.Exec([]string{"su", "-", "postgres", "-c", "pg_ctl reload -D /var/lib/postgresql/data"}, dockertest.ExecOptions{})
if err != nil {
t.Logf("Failed to reload pg_ctl: %v", err)
continue
}
break // Success! Exit retry loop
}
require.NoError(t, err, "Exhausted all retries updating container configuration")

// Wait a moment for pg_hba.conf changes to fully take effect
time.Sleep(2 * time.Second)

// Create a new SSL connection with client cert for use in the test
sslDsn := fmt.Sprintf(
"host=%s port=%s user=testuser password='l]YLSc|4[i56_@{gY' dbname=dbname sslmode=verify-full sslrootcert=%s sslcert=%s sslkey=%s",
strings.Split(hostAndPort, ":")[0],
strings.Split(hostAndPort, ":")[1],
certs.caCert,
certs.clientCert,
certs.clientKey,
)

var sslDB *sql.DB
pool.MaxWait = 120 * time.Second
require.NoError(t, pool.Retry(func() error {
var err error
sslDB, err = sql.Open("postgres", sslDsn)
if err != nil {
return err
}
return sslDB.Ping()
}))

t.Cleanup(func() {
_ = sslDB.Close()
})

return resource, sslDB
}

func TestIntegrationSSLVerifyFull(t *testing.T) {
Expand Down
Loading