Skip to content

Commit

Permalink
feat: Adds support for SSL to address issue MeltanoLabs#71. (MeltanoL…
Browse files Browse the repository at this point in the history
…abs#131)

Two types of SSL are supported:

- Checking the server's certificate against a certificate authority
using `ssl_enable`, for verifying the server's identity to the client.
- Passing a client certificate and private key to the server using
`ssl_client_certificate_enable`, for verifying the client's identity to
the server.

Each can be configured independently of the other. Using either or both
precludes the use of `sqlalchemy_url`.

Closes MeltanoLabs#71.

---------

Co-authored-by: Derek Visch <[email protected]>
  • Loading branch information
sebastianswms and visch authored Jun 23, 2023
1 parent c8c4e67 commit 409e8e8
Show file tree
Hide file tree
Showing 18 changed files with 599 additions and 53 deletions.
20 changes: 8 additions & 12 deletions .github/workflows/ci_workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,23 +39,19 @@ jobs:
pytest:
runs-on: ubuntu-latest
services:
postgres:
image: postgres
env:
POSTGRES_PASSWORD: postgres
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
strategy:
matrix:
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"]
steps:
- uses: actions/checkout@v3
- name: Fix key permissions
run: |
chmod 600 ssl/server.key
sudo chown 999:999 ssl/server.key
chmod 600 ssl/pkey.key
- name: Set up Postgres container
run: |
docker compose -f docker-compose.yml up -d
- name: Set up Python '${{ matrix.python-version }}'
uses: actions/setup-python@v4
with:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
smoke-test
.meltano/**
.tox/**
.secrets/**
.vscode/**
output/**
.env
Expand Down
Empty file added .secrets/.gitkeep
Empty file.
50 changes: 34 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,28 @@ Built with the [Meltano SDK](https://sdk.meltano.com) for Singer Taps and Target
* `schema-flattening`

## Settings
| Setting | Required | Default | Description |
| :-------------------- | :------: | :-----------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| host | False | None | Hostname for postgres instance. Note if sqlalchemy_url is set this will be ignored. |
| port | False | 5432 | The port on which postgres is awaiting connection. Note if sqlalchemy_url is set this will be ignored. |
| user | False | None | User name used to authenticate. Note if sqlalchemy_url is set this will be ignored. |
| password | False | None | Password used to authenticate. Note if sqlalchemy_url is set this will be ignored. |
| database | False | None | Database name. Note if sqlalchemy_url is set this will be ignored. |
| sqlalchemy_url | False | None | SQLAlchemy connection string. This will override using host, user, password, port,dialect. Note that you must escape password special characters properly. See https://docs.sqlalchemy.org/en/20/core/engines.html#escaping-special-characters-such-as-signs-in-passwords |
| dialect+driver | False | postgresql+psycopg2 | Dialect+driver see https://docs.sqlalchemy.org/en/20/core/engines.html. Generally just leave this alone. Note if sqlalchemy_url is set this will be ignored. |
| default_target_schema | False | None | Postgres schema to send data to, example: tap-clickup |
| hard_delete | False | 0 | When activate version is sent from a tap this specefies if we should delete the records that don't match, or mark them with a date in the `_sdc_deleted_at` column. |
| add_record_metadata | False | 1 | Note that this must be enabled for activate_version to work!This adds _sdc_extracted_at, _sdc_batched_at, and more to every table. See https://sdk.meltano.com/en/latest/implementation/record_metadata.html for more information. |
| stream_maps | False | None | Config object for stream maps capability. For more information check out [Stream Maps](https://sdk.meltano.com/en/latest/stream_maps.html). |
| stream_map_config | False | None | User-defined config values to be used within map expressions. |
| flattening_enabled | False | None | 'True' to enable schema flattening and automatically expand nested properties. |
| flattening_max_depth | False | None | The max depth to flatten schemas. |
| Setting | Required | Default | Description |
|:-----------------------------|:--------:|:-------:|:------------|
| host | False | None | Hostname for postgres instance. Note if sqlalchemy_url is set this will be ignored. |
| port | False | 5432 | The port on which postgres is awaiting connection. Note if sqlalchemy_url is set this will be ignored. |
| user | False | None | User name used to authenticate. Note if sqlalchemy_url is set this will be ignored. |
| password | False | None | Password used to authenticate. Note if sqlalchemy_url is set this will be ignored. |
| database | False | None | Database name. Note if sqlalchemy_url is set this will be ignored. |
| sqlalchemy_url | False | None | SQLAlchemy connection string. This will override using host, user, password, port, dialect, and all ssl settings. Note that you must escape password special characters properly. See https://docs.sqlalchemy.org/en/20/core/engines.html#escaping-special-characters-such-as-signs-in-passwords |
| dialect+driver | False | postgresql+psycopg2 | Dialect+driver see https://docs.sqlalchemy.org/en/20/core/engines.html. Generally just leave this alone. Note if sqlalchemy_url is set this will be ignored. |
| default_target_schema | False | None | Postgres schema to send data to, example: tap-clickup |
| hard_delete | False | 0 | When activate version is sent from a tap this specefies if we should delete the records that don't match, or mark them with a date in the `_sdc_deleted_at` column. |
| add_record_metadata | False | 1 | Note that this must be enabled for activate_version to work!This adds _sdc_extracted_at, _sdc_batched_at, and more to every table. See https://sdk.meltano.com/en/latest/implementation/record_metadata.html for more information. |
| ssl_enable | False | 0 | Whether or not to use ssl to verify the server's identity. Use ssl_certificate_authority and ssl_mode for further customization. To use a client certificate to authenticate yourself to the server, use ssl_client_certificate_enable instead. Note if sqlalchemy_url is set this will be ignored. |
| ssl_client_certificate_enable| False | 0 | Whether or not to provide client-side certificates as a method of authentication to the server. Use ssl_client_certificate and ssl_client_private_key for further customization. To use SSL to verify the server's identity, use ssl_enable instead. Note if sqlalchemy_url is set this will be ignored. |
| ssl_mode | False | verify-full | SSL Protection method, see [postgres documentation](https://www.postgresql.org/docs/current/libpq-ssl.html#LIBPQ-SSL-PROTECTION) for more information. Must be one of disable, allow, prefer, require, verify-ca, or verify-full. Note if sqlalchemy_url is set this will be ignored. |
| ssl_certificate_authority | False | None | The certificate authority that should be used to verify the server's identity. Can be provided either as the certificate itself (in .env) or as a filepath to the certificate. Note if sqlalchemy_url is set this will be ignored. |
| ssl_client_certificate | False | None | The certificate that should be used to verify your identity to the server. Can be provided either as the certificate itself (in .env) or as a filepath to the certificate. Note if sqlalchemy_url is set this will be ignored. |
| ssl_client_private_key | False | None | The private key for the certificate you provided. Can be provided either as the certificate itself (in .env) or as a filepath to the certificate. Note if sqlalchemy_url is set this will be ignored. |
| stream_maps | False | None | Config object for stream maps capability. For more information check out [Stream Maps](https://sdk.meltano.com/en/latest/stream_maps.html). |
| stream_map_config | False | None | User-defined config values to be used within map expressions. |
| flattening_enabled | False | None | 'True' to enable schema flattening and automatically expand nested properties. |
| flattening_max_depth | False | None | The max depth to flatten schemas. |

A full list of supported settings and capabilities is available by running: `target-postgres --about`

Expand All @@ -43,6 +49,14 @@ pipx install -e .

## Configuration

### An Explanation of Various SSL Configuration Options

There are two distinct processes which both fall under the banner of SSL. One process occurs when the client wishes to ensure the identity of the server, and is the more common reason that SSL is used. Another is when the server wishes to ensure the identity of the client, for authentication/authorization purposes.

If your server is set up with a certificate and private key, and you wish to check their certificate against a root certificate which you posess, use `ssl_enable`. You may then further customize this process using the `ssl_certificate_authority` and `ssl_mode` settings. See the [documentation](https://www.postgresql.org/docs/current/libpq-ssl.html#LIBQ-SSL-CERTIFICATES) for further details.

If your server is set up with a root certificate, and you wish to provide a certificate to the server to verify your identity, use `ssl_client_certificate_enable`. You may then further customize this process using the `ssl_client_certificate` and `ssl_client_private_key` settings. See the [documentation](https://www.postgresql.org/docs/current/libpq-ssl.html#LIBPQ-SSL-CLIENTCERT) for further details.

### Configure using environment variables

This Singer target will automatically import any environment variables within the working directory's
Expand Down Expand Up @@ -70,6 +84,10 @@ pipx install git+https://gitlab.com/meltano/tap-carbon-intensity
tap-carbon-intensity | target-postgres --config /path/to/target-postgres-config.json
```

### Using Docker Compose

`docker-compose.yml` provides the commands to create two empty sample databases using [Docker](https://docs.docker.com/engine/install/). These can be a starting point to create your own database running in Docker, or can be used to run the tap's [built-in tests](#create-and-run-tests).

## Developer Resources

### Initialize your Development Environment
Expand Down
27 changes: 27 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
# docker compose -f docker-compose.yml up -d
version: "2.1"
services:
postgres:
image: postgres:latest
command: postgres -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 -c hba_file=/var/lib/postgresql/pg_hba.conf
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: postgres
POSTGRES_HOST_AUTH_METHOD: cert clientcert=verify-full
POSTGRES_INITDB_ARGS: --auth-host=cert
# Not placed in the data directory (/var/lib/postgresql/data) because of https://gist.github.com/mrw34/c97bb03ea1054afb551886ffc8b63c3b?permalink_comment_id=2678568#gistcomment-2678568
volumes:
- ./ssl/server.crt:/var/lib/postgresql/server.crt # Certificate verifying the server's identity to the client.
- ./ssl/server.key:/var/lib/postgresql/server.key # Private key to verify the server's certificate is legitimate.
- ./ssl/ca.crt:/var/lib/postgresql/ca.crt # Certificate authority to use when verifying the client's identity to the server.
- ./ssl/pg_hba.conf:/var/lib/postgresql/pg_hba.conf # Configuration file to allow connection over SSL.
ports:
- "5432:5432"
postgres_no_ssl: # Borrowed from https://github.com/MeltanoLabs/tap-postgres/blob/main/.github/workflows/test.yml#L13-L23
image: postgres:latest
environment:
POSTGRES_PASSWORD: postgres
ports:
- 5433:5432
11 changes: 11 additions & 0 deletions meltano.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,17 @@ plugins:
settings:
- name: sqlalchemy_url
kind: password
- name: ssl_enable
kind: boolean
- name: ssl_client_certificate_enable
kind: boolean
- name: ssl_mode
- name: ssl_certificate_authority
kind: password
- name: ssl_client_certificate
kind: password
- name: ssl_client_private_key
kind: password
config:
host: localhost
port: 5432
Expand Down
3 changes: 0 additions & 3 deletions podman.sh

This file was deleted.

19 changes: 19 additions & 0 deletions ssl/ca.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDBzCCAe+gAwIBAgIUHoTp2HQfKSdJ9MdrvWvWW9FLLHMwDQYJKoZIhvcNAQEL
BQAwEzERMA8GA1UEAwwIcG9zdGdyZXMwHhcNMjMwNTE2MjMyNjAzWhcNMjQwNTE1
MjMyNjAzWjATMREwDwYDVQQDDAhwb3N0Z3JlczCCASIwDQYJKoZIhvcNAQEBBQAD
ggEPADCCAQoCggEBAJwSeW2XRRlP5DDNqwqKSZncXigDo0zBJyYs9flAGfoPPI7V
uaWaEfhpF9uoQ6RKuWJ4IrqXTVFhZmMvygfakMVhl4cYfE2ApB7qRk8vNhQ9K/c9
ks1zL7FddqfwaARCww3LuE+j9Mh2cI8FHQPYtonmRmFIo7hbuL2ZWXOeEqPf4RDE
n10nXx7XlKO52zLFPYJ0guv0todxbuAWVNFfuFXtUANmzhoq0lYwt/kT4/bfLRXu
G24dUA60fCjm0YpFJtv/rAKPcIRpo7VEpCFq6+rUMQZKVVhX8tcZ+SbmKdWPx5I5
41HMPPBDH8XuDJvtuKzd5Hnj7qfEg0L3Xy414EUCAwEAAaNTMFEwHQYDVR0OBBYE
FIPvcMua9Wec95+dbdBUX6EDwCsUMB8GA1UdIwQYMBaAFIPvcMua9Wec95+dbdBU
X6EDwCsUMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAH+TrUQD
POYPAzcropUbtYV40pjTK7k6Q9OXwDfVNNsQhBE+TGuk0YpJzpaRQPzyosD/eFYU
UEfsbCifhSb5h5AQB3V0MnQmC3/Oeao6On17wncM48V7BZ8o6HA8wa7bDs7tVMW5
+lS+CqCEzdWmqWX7batImU8yVmmhIRL/Rp4Yz8WiOSZxq/ALTlAjsecVFug4MS33
5r5G1LfYId387vy9wGchYaY3cVLuJypMf2IzXS0t7BWK6rP8VxWYlnKqRksmPhvN
1JBStTo+cRsCCqs2Hv/1cYynW2VWgNBndsw4h9Ni8dfJbLTsObixFMjzWhOYPk4Q
aE7neVvEqUwG6rE=
-----END CERTIFICATE-----
19 changes: 19 additions & 0 deletions ssl/cert.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDBzCCAe+gAwIBAgIUHoTp2HQfKSdJ9MdrvWvWW9FLLHMwDQYJKoZIhvcNAQEL
BQAwEzERMA8GA1UEAwwIcG9zdGdyZXMwHhcNMjMwNTE2MjMyNjAzWhcNMjQwNTE1
MjMyNjAzWjATMREwDwYDVQQDDAhwb3N0Z3JlczCCASIwDQYJKoZIhvcNAQEBBQAD
ggEPADCCAQoCggEBAJwSeW2XRRlP5DDNqwqKSZncXigDo0zBJyYs9flAGfoPPI7V
uaWaEfhpF9uoQ6RKuWJ4IrqXTVFhZmMvygfakMVhl4cYfE2ApB7qRk8vNhQ9K/c9
ks1zL7FddqfwaARCww3LuE+j9Mh2cI8FHQPYtonmRmFIo7hbuL2ZWXOeEqPf4RDE
n10nXx7XlKO52zLFPYJ0guv0todxbuAWVNFfuFXtUANmzhoq0lYwt/kT4/bfLRXu
G24dUA60fCjm0YpFJtv/rAKPcIRpo7VEpCFq6+rUMQZKVVhX8tcZ+SbmKdWPx5I5
41HMPPBDH8XuDJvtuKzd5Hnj7qfEg0L3Xy414EUCAwEAAaNTMFEwHQYDVR0OBBYE
FIPvcMua9Wec95+dbdBUX6EDwCsUMB8GA1UdIwQYMBaAFIPvcMua9Wec95+dbdBU
X6EDwCsUMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAH+TrUQD
POYPAzcropUbtYV40pjTK7k6Q9OXwDfVNNsQhBE+TGuk0YpJzpaRQPzyosD/eFYU
UEfsbCifhSb5h5AQB3V0MnQmC3/Oeao6On17wncM48V7BZ8o6HA8wa7bDs7tVMW5
+lS+CqCEzdWmqWX7batImU8yVmmhIRL/Rp4Yz8WiOSZxq/ALTlAjsecVFug4MS33
5r5G1LfYId387vy9wGchYaY3cVLuJypMf2IzXS0t7BWK6rP8VxWYlnKqRksmPhvN
1JBStTo+cRsCCqs2Hv/1cYynW2VWgNBndsw4h9Ni8dfJbLTsObixFMjzWhOYPk4Q
aE7neVvEqUwG6rE=
-----END CERTIFICATE-----
4 changes: 4 additions & 0 deletions ssl/pg_hba.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
local all postgres peer
host all all 127.0.0.1/32 trust
host all all ::1/128 trust
hostssl all all all cert clientcert=verify-full
28 changes: 28 additions & 0 deletions ssl/pkey.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCcEnltl0UZT+Qw
zasKikmZ3F4oA6NMwScmLPX5QBn6DzyO1bmlmhH4aRfbqEOkSrlieCK6l01RYWZj
L8oH2pDFYZeHGHxNgKQe6kZPLzYUPSv3PZLNcy+xXXan8GgEQsMNy7hPo/TIdnCP
BR0D2LaJ5kZhSKO4W7i9mVlznhKj3+EQxJ9dJ18e15SjudsyxT2CdILr9LaHcW7g
FlTRX7hV7VADZs4aKtJWMLf5E+P23y0V7htuHVAOtHwo5tGKRSbb/6wCj3CEaaO1
RKQhauvq1DEGSlVYV/LXGfkm5inVj8eSOeNRzDzwQx/F7gyb7bis3eR54+6nxINC
918uNeBFAgMBAAECggEAGjPz1RVvkXdbTWJKVCOxhbZ8zGUH9qv7IaqsxWMguV3z
gduaJpZ+a+FhEwzmBmBRTZnz4rXiUkZzBTYRyk3Evo7K/PB8dhqh81rL4SGBB9bZ
WdIponqzSCjz8fAn1odK7jcEw8I4J6vS7AAkxe+Nfgt+R3kFm78yfgqP/RxN7ts1
czGT2ezOJNr7Wk6d4DDAy2hTYIc89eqir+epfx1e5EnhdVeg2SPBwSTppbXIp8F1
51jXNv60pP64Ieu7QTCR283btkQxMvUQ8i9LKVNh6EECd2bBPEt0xCWVyL8exc1u
MUtIpblhs17ziNBHNs1YQLX8Z73xbnyxO+IsAvf4gQKBgQDKpbueiPW0uQ77iesR
NkUWZNvqTXl9tWnlUeNBdcWvhOeP2OeAFyeCLCmKXE7vPiKn4C/2PMHlmUS0JdET
TV2nlUJIv78Rl26gCcYdLjwAUfmmH+BgNHw/cP58kkTiegNYd84reva0AGz7I/c2
mim2KlzZLKCHPopZJ99KZY9HYQKBgQDFKZwFv+npFcp0W0G+c2COsZ0vRbSttQaR
wYRb6FfXaBisDwSGCujQsKG92XYZAS9q7GPJ8iTpPoT/TSUePKERlwPxUpc9sqVB
tysb7vWcGrSOGeunIHH6F2OXPHPfux9Eq/bURUF1MIB6fbgzxL+Kl/M7m/EtMESq
AtFalGUXZQKBgB09LIUDXfBlgzPoAnLJUc6ZXuG/q/fnZRAhcJjRVWSt2Ht44G4q
6RhvJs8/4mPCo111i3YL7i4inzce/bu7PfggISA+CmOPZfbRcjRjp2Skb1D46Hb5
G7RLqWxv7mB/Glx5bNX5N/9g0FisJ89JDxupoRv0xHS/IVcb2avyW2oBAoGBAIgB
I/dzY0++EGIjcT6HKFxGeT9avj/1WArDiyI7LB0TWbGWynAMpn0O2wOzNpwZDTSc
zFlKB9w9nFDgTnKFMDaKDdYyOtH8obKrP7mNJTAB2/sKNlybLQRvjeuNcAEte2xL
k4DqJTVJt9bHUoGjft2D4+2CrOOXIEaGmxP4uaNhAoGBAJHDjgvXi2j0DloQh8hR
6+c/wRV3lMfg4joQ7tnI8HWyncUfmcl6Ei5jdgYT3VqTfqYMWKqIqlxeOqaPh/6j
me7Odgcc52pQaLYGEiwl4cd+pYXSyxGozVR9INf2KveUtiCDKlxKswbWaZ/ywTpI
9uR9je0KdLsSQ4e4D5k2JkPV
-----END PRIVATE KEY-----
Loading

0 comments on commit 409e8e8

Please sign in to comment.