Setting the Service mode to POSTGRES
enables it to operate in application-layer aware PostgreSQL mode. This mode enables you to provide secretless access for Users to the protected upstream PostgreSQL-based server without having to share the upstream's password. This mode also provides you with clear application-layer aware visibility where your Postgres sessions and queries are logged and audited in real-time.
Secretless Access
Secretless access enables you to provide secretless access for authorized Users to POSTGRES
-based Service by automatically injecting passwords to authenticate to the upstream PostgreSQL database, and force the User to connect to the upstream as a specific user, possibly with a certain role corresponding to specific permissions, to a specific database.
First, you need to create a Secret to store the password of your upstream SSH server (read more here) as follows:
octeliumctl create secret pg-password# OR via a --value flagocteliumctl create secret --value <PASSWORD> pg-password# OR via a --file flagocteliumctl create secret --file /PATH/TO/PASSWORD pg-password
Now, you define your Service as follows:
1kind: Service2metadata:3name: pg-db4spec:5mode: POSTGRES6port: 54327config:8upstream:9url: postgres://address-to-pg10postgres:11user: postgres12database: db0113auth:14password:15fromSecret: pg-password16sslMode: REQUIRE
Now, the above configuration forces the User to authenticate as postgres
with the password value set in the Secret pg-password
and connect to the db01
database regardless of the information supplied by the downstream.
For internal/private PostgreSQL upstreams behind NAT, you need to remotely serve them via a connected octelium
client or container as discussed here.
SSL Mode
By default, the Service attempts to use prefer
ssl mode (read more here). You can, however, override that default behavior via the sslMode
field and explicitly set it to either REQUIRE
to force using TLS or DISABLE
to disable using TLS. Here is an example:
1kind: Service2metadata:3name: pg-db4spec:5mode: POSTGRES6port: 54327config:8upstream:9url: postgres://address-to-pg10postgres:11user: postgres12database: db0113auth:14password:15fromSecret: pg-password16sslMode: REQUIRE
Access Control
You can control access based on the Postgres request information. Such information are stored in ctx.request.postgres
where it contains the username and database. Here is a detailed example of a inline Policy that controls access based on Postgres-specific information:
1kind: Service2metadata:3name: svc14spec:5mode: POSTGRES6config:7# Your config....8authorization:9inlinePolicies:10- spec:11rules:12- effect: ALLOW13condition:14any:15of:16- match: ctx.request.postgres.connect.user == "db-user-1"17- match: ctx.request.postgres.connect.database == "db-01"
You do not actually to control access by checking against the database user since you already override the database user in your Service configuration as illustrated above regardless of the database user value provided by the User. You can also use dynamic configuration in order to map different databases and/or database users to different Users under different conditions. You can read more about dynamic configuration here
Dynamic Configuration
You can use dynamic configuration (read more about dynamic configuration here) to, for example, route to different upstreams or different database users with different privileges and roles (e.g. more privileged Users can automatically delete tables or databases while other Users cannot do so) based on identity and/or context. Here is an example:
1kind: Service2metadata:3name: example-svc4spec:5mode: POSTGRES6dynamicConfig:7configs:8- name: prod9upstream:10url: postgres://address-to-pg11postgres:12user: prod13database: prod-db14auth:15password:16fromSecret: prod-password17- name: dev18upstream:19url: postgres://address-to-pg20postgres:21user: dev22database: dev-db23auth:24password:25fromSecret: dev-password26rules:27- condition:28match: '"prod" in ctx.user.spec.groups'29configName: prod30- condition:31matchAny: true32configName: dev
Visibility
The Service emits access logs in real time to the audit collector. Each log provides PostgreSQL application-layer aware information about the request such as the command type, the query details, etc.... Here is an example:
1{2"apiVersion": "core/v1",3"entry": {4"common": {5"connectionID": "dnm3-09gn-6rt58k768x9cns8fxbu1w54v-v446-a6fy",6"endedAt": "2025-03-21T22:15:32.000550409Z",7"isAuthenticated": true,8"isAuthorized": true,9"namespaceRef": {10"apiVersion": "core/v1",11"kind": "Namespace",12"name": "default",13"resourceVersion": "0195b81d-43ec-7ba7-81f7-9b77202b3612",14"uid": "bff0768e-eec8-4044-a972-9f7af81b79d8"15},16"reason": {17"details": {18"policyMatch": {19"inlinePolicy": {20"name": "allow-all",21"resourceRef": {22"apiVersion": "core/v1",23"kind": "Group",24"name": "g1",25"resourceVersion": "0195b821-209b-76f7-bde9-b078e870621c",26"uid": "972e1808-7248-468a-ba7c-8da43d33c626"27}28}29}30},31"type": "POLICY_MATCH"32},33"regionRef": {34"apiVersion": "core/v1",35"kind": "Region",36"name": "default",37"uid": "6e233d12-2fd6-4670-a82d-8c712e1f7374"38},39"serviceRef": {40"apiVersion": "core/v1",41"kind": "Service",42"name": "pg1.default",43"resourceVersion": "0195bac5-10c2-7cb5-a59b-216d19ea7001",44"uid": "d4293385-2aa7-4b42-a1a2-4a85803ee21b"45},46"sessionRef": {47"apiVersion": "core/v1",48"kind": "Session",49"name": "usr1-3pt93j",50"resourceVersion": "0195bac2-c5c8-7206-9076-191558cfc9be",51"uid": "e8bea7be-b858-4457-a8ee-a0cb7f6c91da"52},53"startedAt": "2025-03-21T22:15:32.000470456Z",54"userRef": {55"apiVersion": "core/v1",56"kind": "User",57"name": "usr1",58"resourceVersion": "0195b821-228d-79b2-92f3-4bb458944f97",59"uid": "e0f251b2-6952-4a46-a771-2712a45c47f5"60}61},62"info": {63"postgres": {64"query": {65"query": "CREATE DATABASE db01;"66},67"type": "QUERY"68}69}70},71"kind": "AccessLog",72"metadata": {73"actorRef": {74"apiVersion": "core/v1",75"kind": "Session",76"name": "usr1-3pt93j",77"resourceVersion": "0195bac2-c5c8-7206-9076-191558cfc9be",78"uid": "e8bea7be-b858-4457-a8ee-a0cb7f6c91da"79},80"createdAt": "2025-03-21T22:15:32.000522377Z",81"id": "qz07-s8ho-pf8t84xm5rhqrmnpttybpspx-aqnp-rkeg",82"targetRef": {83"apiVersion": "core/v1",84"kind": "Service",85"name": "pg1.default",86"resourceVersion": "0195bac5-10c2-7cb5-a59b-216d19ea7001",87"uid": "d4293385-2aa7-4b42-a1a2-4a85803ee21b"88}89}90}
As you can see in the above example, the type of this POSTGRES
access Log is a QUERY
. The POSTGRES
mode has currently 8 Log types: SESSION_START
, SESSION_END
, QUERY
, PARSE
, CLOSE
, EXECUTE
, BIND
, FUNCTION_CALL
and some of these types include different detailed information according to their type. You can read more in the API reference.