diff --git a/README.MD b/README.MD index 73d43c0..77755af 100644 --- a/README.MD +++ b/README.MD @@ -10,53 +10,101 @@ lives separately in another repository. - Rust source code available [on GitHub](https://github.com/ambarltd/pgt-proxy) - Read why we open sourced PGT Proxy [on our website](https://ambar.cloud/blog/connect-to-postgresql-securely-with-pgt-proxy) +### Architecture Diagram + ![Architecture Diagram](PGT-Proxy-Diagram.png) ## Usage -**Step 1.** Create a Dockerfile based on pgt-proxy. - -```Dockerfile -FROM ambarltd/pgt-proxy:latest +**Step 1.** Run the Docker image ambarltd/pgt-proxy, overriding the Docker CMD with the arguments +that PGT-Proxy requires. You will need to mount volumes for: -# PGT-Proxy will need to trust a set of certificate authorities -# (to be specified at runtime through "--client-ca-roots-path") -# -# Use a prepackaged set of root authorities such as RDS's CAs or Firefox's default trusted CAs, living at these directories: -# /etc/pgt_proxy/client_tls/aws_rds/ -# /etc/pgt_proxy/client_tls/firefox/ -# Or specify trusted CAs in the directory /etc/pgt_proxy/client_tls/custom_cas/ (e.g., Google Cloud SQL uses a custom CA) -RUN COPY path/to/postgres_destination_server/certificate_authority_certificates_in_pem_format/ /etc/pgt_proxy/client_tls/custom_cas/ +1. PGT-Proxy's private key +2. PGT-Proxy's certificate, +3. The certificate authority/authorities that PGT-Proxy should trust (optional, you can also choose preset CAs). -# PGT-Proxy will need to serve TLS traffic, which requires a certificate and its corresponding private key -# (to be specified at runtime through "--server-private-key-path", "--server-certificate-path") -# -# The certificate needs to be trusted by all pg clients connecting through PGT-Proxy. -# Thus it is recommended to use a genuine TLS certificate issued by a public certificate authority -# that is already trusted by default by pg clients. -RUN COPY path/to/pgt_proxy/tls_certificate.pem /etc/pgt_proxy/server_tls/certificate.pem -RUN COPY path/to/pgt_proxy/tls_private_key.pem /etc/pgt_proxy/server_tls/key.pem +See below, 4 examples using docker compose. -# Set the arguments passed to PGT-Proxy. -CMD ["--server-private-key-path", "/etc/pgt_proxy/server_tls/key.key", \ - "--server-certificate-path", "/etc/pgt_proxy/server_tls/certificate.pem", \ - "--server-port", "5432", \ - "--client-connection-host-or-ip", "destination.host.example.amazonaws.com", \ - "--client-connection-port", "5432", \ - "--client-tls-validation-host", "destination.host.example.amazonaws.com", \ - "--client-ca-roots-path", "/etc/pgt_proxy/client_tls/custom_cas/"] # keep in mind only files ending in .pem will be read +```yaml +services: + pgt-proxy-conecting-to-aws-rds: + image: ambarltd/pgt-proxy:latest + ports: + - "5432:5432" + volumes: + - ./path/to/pgt_proxy/your_tls_private_key.pem:/etc/pgt_proxy/server_tls/key.pem + - ./path/to/pgt_proxy/your_tls_certificate.pem:/etc/pgt_proxy/server_tls/certificate.pem + command: [ + "--server-private-key-path", "/etc/pgt_proxy/server_tls/key.key", \ + "--server-certificate-path", "/etc/pgt_proxy/server_tls/certificate.pem", \ + "--server-port", "5432", \ + "--client-connection-host-or-ip", "destination.host.example.amazonaws.com", \ + "--client-connection-port", "5432", \ + "--client-tls-validation-host", "destination.host.example.amazonaws.com", \ + "--client-ca-roots-path", "/etc/pgt_proxy/client_tls/aws_rds/" + ] + pgt-proxy-connecting-to-azure-digicert: + image: ambarltd/pgt-proxy:latest + ports: + - "5433:5432" + volumes: + - ./path/to/pgt_proxy/your_tls_private_key.pem:/etc/pgt_proxy/server_tls/key.pem + - ./path/to/pgt_proxy/your_tls_certificate.pem:/etc/pgt_proxy/server_tls/certificate.pem + command: [ + "--server-private-key-path", "/etc/pgt_proxy/server_tls/key.key", \ + "--server-certificate-path", "/etc/pgt_proxy/server_tls/certificate.pem", \ + "--server-port", "5432", \ + "--client-connection-host-or-ip", "destination.host.example.azure.com", \ + "--client-connection-port", "5432", \ + "--client-tls-validation-host", "destination.host.example.azure.com", \ + "--client-ca-roots-path", "/etc/pgt_proxy/client_tls/azure_digicert/" + ] + pgt-proxy-connecting-to-database-with-certificate-authorities-trusted-by-firefox-web-browser: + image: ambarltd/pgt-proxy:latest + ports: + - "5433:5432" + volumes: + - ./path/to/pgt_proxy/your_tls_private_key.pem:/etc/pgt_proxy/server_tls/key.pem + - ./path/to/pgt_proxy/your_tls_certificate.pem:/etc/pgt_proxy/server_tls/certificate.pem + command: [ + "--server-private-key-path", "/etc/pgt_proxy/server_tls/key.key", \ + "--server-certificate-path", "/etc/pgt_proxy/server_tls/certificate.pem", \ + "--server-port", "5432", \ + "--client-connection-host-or-ip", "destination.host.example.com", \ + "--client-connection-port", "5432", \ + "--client-tls-validation-host", "destination.host.example.com", \ + "--client-ca-roots-path", "/etc/pgt_proxy/client_tls/firefox/" + ] + pgt-proxy-connecting-to-database-with-custom-certificate-authorities: + image: ambarltd/pgt-proxy:latest + ports: + - "5432:5432" + volumes: + - ./path/to/pgt_proxy/your_tls_private_key.pem:/etc/pgt_proxy/server_tls/key.pem + - ./path/to/pgt_proxy/your_tls_certificate.pem:/etc/pgt_proxy/server_tls/certificate.pem + - ./path/to/postgres_destination_server/your_certificate_authority_certificates_in_pem_format/:/etc/pgt_proxy/client_tls/custom_cas/ + command: [ + "--server-private-key-path", "/etc/pgt_proxy/server_tls/key.key", \ + "--server-certificate-path", "/etc/pgt_proxy/server_tls/certificate.pem", \ + "--server-port", "5432", \ + "--client-connection-host-or-ip", "destination.host.example.com", \ + "--client-connection-port", "5432", \ + "--client-tls-validation-host", "destination.host.example.com", \ + "--client-ca-roots-path", "/etc/pgt_proxy/client_tls/custom_cas/" + ] ``` -**Step 2.** Deploy your Dockerfile to a machine that allows inbound and outbound traffic on the `--server-port` -(e.g., 5432). +**Step 2.** Make sure the machine in which you have deployed ambarltd/pgt-proxy allows incoming traffic on the port you +picked. In the examples above, PGT-Proxy's server serves traffic on port 5432. -**Step 3.** Using DNS, point the hostname inside `/etc/pgt_proxy/server_tls/certificate.pem` to the IP address -of the machine in step 2. +**Step 3.** Using DNS, point the hostname associated with the certificate in `/etc/pgt_proxy/server_tls/certificate.pem` +to the IP address of the machine in step 2. -**Step 4.** Connect to PGT-Proxy via the machine in step 2, using your favorite pg client. E.g., +**Step 4.** Connect to PGT-Proxy from another machine, using your favorite pg client. E.g., ```bash psql 'sslmode=verify-full host=pgtproxy.example.com port=5432 user=admin password=pass dbname=postgres channel_binding=disable' +# Notice that channel binding needs to be disabled for PGT-Proxy to work. ``` **Suggestions** diff --git a/build/Dockerfile b/build/Dockerfile index 987284f..eb22897 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -7,7 +7,8 @@ RUN git clone https://github.com/ambarltd/pgt-proxy.git RUN mv pgt-proxy /pgt_proxy WORKDIR /pgt_proxy -RUN git checkout tags/v1.2 +RUN git fetch +RUN git checkout tags/v1.3 RUN cargo build --release # Here we are keeping images small (and secure), by only copying the executable to a new barebones image. @@ -30,9 +31,16 @@ RUN cp /etc/ssl/certs/ca-certificates.crt /etc/pgt_proxy/client_tls/firefox/fire # Option to Trust RDS Certificates # It can only be activated deliberately by passing "--client-ca-roots-path" at runtime +# From https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.SSL.html#UsingWithRDS.SSL.CertificatesAllRegions RUN mkdir -p /etc/pgt_proxy/client_tls/aws_rds COPY client_tls/aws_rds/ /etc/pgt_proxy/client_tls/aws_rds/ +# Option to Trust Azure + Digicert Certificates +# It can only be activated deliberately by passing "--client-ca-roots-path" at runtime +# From: https://learn.microsoft.com/en-us/azure/postgresql/flexible-server/concepts-networking-ssl-tls#read-replicas-with-certificate-pinning-scenarios +RUN mkdir -p /etc/pgt_proxy/client_tls/azure_digicert +COPY client_tls/azure_digicert/ /etc/pgt_proxy/client_tls/azure_digicert/ + # Self Issued Certificate (for testing only) # It can only be activated deliberately by passing "--server-private-key-path", "--server-certificate-path" at runtime COPY server_tls/self_issuing_openssl.conf /tmp/self_issuing_openssl.conf diff --git a/build/client_tls/azure_digicert/DigiCertGlobalRootCA.pem b/build/client_tls/azure_digicert/DigiCertGlobalRootCA.pem new file mode 100644 index 0000000..fd4341d --- /dev/null +++ b/build/client_tls/azure_digicert/DigiCertGlobalRootCA.pem @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD +QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT +MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j +b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB +CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97 +nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt +43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P +T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4 +gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO +BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR +TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw +DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr +hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg +06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF +PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls +YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk +CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= +-----END CERTIFICATE----- diff --git a/build/client_tls/azure_digicert/DigiCertGlobalRootG2.pem b/build/client_tls/azure_digicert/DigiCertGlobalRootG2.pem new file mode 100644 index 0000000..798e002 --- /dev/null +++ b/build/client_tls/azure_digicert/DigiCertGlobalRootG2.pem @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH +MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT +MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j +b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI +2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx +1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ +q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz +tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ +vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP +BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV +5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY +1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4 +NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG +Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91 +8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe +pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl +MrY= +-----END CERTIFICATE----- diff --git a/build/client_tls/azure_digicert/Microsoft-RSA-Root-Certificate-Authority-2017.pem b/build/client_tls/azure_digicert/Microsoft-RSA-Root-Certificate-Authority-2017.pem new file mode 100644 index 0000000..fd4341d --- /dev/null +++ b/build/client_tls/azure_digicert/Microsoft-RSA-Root-Certificate-Authority-2017.pem @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD +QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT +MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j +b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB +CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97 +nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt +43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P +T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4 +gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO +BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR +TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw +DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr +hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg +06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF +PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls +YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk +CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= +-----END CERTIFICATE-----