Skip to content

Commit 3dae3d0

Browse files
authored
Separate server and client passwords optionally (#407)
* Separate server and user passwords * config
1 parent a18eb42 commit 3dae3d0

File tree

7 files changed

+76
-74
lines changed

7 files changed

+76
-74
lines changed

CONFIG.md

+29-63
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# PgCat Configurations
1+
# PgCat Configurations
22
## `general` Section
33

44
### host
@@ -108,7 +108,7 @@ If we should log client disconnections
108108
### autoreload
109109
```
110110
path: general.autoreload
111-
default: false
111+
default: 15000
112112
```
113113

114114
When set to true, PgCat reloads configs if it detects a change in the config file.
@@ -127,7 +127,7 @@ path: general.tcp_keepalives_idle
127127
default: 5
128128
```
129129

130-
Number of seconds of connection idleness to wait before sending a keepalive packet to the server and client.
130+
Number of seconds of connection idleness to wait before sending a keepalive packet to the server.
131131

132132
### tcp_keepalives_count
133133
```
@@ -175,41 +175,11 @@ Connecting to that database allows running commands like `SHOW POOLS`, `SHOW DAT
175175
### admin_password
176176
```
177177
path: general.admin_password
178-
default: <UNSET>
178+
default: "admin_pass"
179179
```
180180

181181
Password to access the virtual administrative database
182182

183-
### auth_query (experimental)
184-
```
185-
path: general.auth_query
186-
default: <UNSET>
187-
```
188-
189-
Query to be sent to servers to obtain the hash used for md5 authentication. The connection will be
190-
established using the database configured in the pool. This parameter is inherited by every pool
191-
and can be redefined in pool configuration.
192-
193-
### auth_query_user (experimental)
194-
```
195-
path: general.auth_query_user
196-
default: <UNSET>
197-
```
198-
199-
User to be used for connecting to servers to obtain the hash used for md5 authentication by sending the query
200-
specified in `auth_query_user`. The connection will be established using the database configured in the pool.
201-
This parameter is inherited by every pool and can be redefined in pool configuration.
202-
203-
### auth_query_password (experimental)
204-
```
205-
path: general.auth_query_password
206-
default: <UNSET>
207-
```
208-
209-
Password to be used for connecting to servers to obtain the hash used for md5 authentication by sending the query
210-
specified in `auth_query_user`. The connection will be established using the database configured in the pool.
211-
This parameter is inherited by every pool and can be redefined in pool configuration.
212-
213183
## `pools.<pool_name>` Section
214184

215185
### pool_mode
@@ -243,7 +213,7 @@ If the client doesn't specify, PgCat routes traffic to this role by default.
243213
`replica` round-robin between replicas only without touching the primary,
244214
`primary` all queries go to the primary unless otherwise specified.
245215

246-
### query_parser_enabled (experimental)
216+
### query_parser_enabled
247217
```
248218
path: pools.<pool_name>.query_parser_enabled
249219
default: true
@@ -264,7 +234,7 @@ If the query parser is enabled and this setting is enabled, the primary will be
264234
load balancing of read queries. Otherwise, the primary will only be used for write
265235
queries. The primary can always be explicitly selected with our custom protocol.
266236

267-
### sharding_key_regex (experimental)
237+
### sharding_key_regex
268238
```
269239
path: pools.<pool_name>.sharding_key_regex
270240
default: <UNSET>
@@ -286,7 +256,7 @@ Current options:
286256
`pg_bigint_hash`: PARTITION BY HASH (Postgres hashing function)
287257
`sha1`: A hashing function based on SHA1
288258

289-
### automatic_sharding_key (experimental)
259+
### automatic_sharding_key
290260
```
291261
path: pools.<pool_name>.automatic_sharding_key
292262
default: <UNSET>
@@ -311,47 +281,43 @@ default: 3000
311281

312282
Connect timeout can be overwritten in the pool
313283

314-
### auth_query (experimental)
315-
```
316-
path: general.auth_query
317-
default: <UNSET>
318-
```
319-
320-
Auth query can be overwritten in the pool
284+
## `pools.<pool_name>.users.<user_index>` Section
321285

322-
### auth_query_user (experimental)
286+
### username
323287
```
324-
path: general.auth_query_user
325-
default: <UNSET>
288+
path: pools.<pool_name>.users.<user_index>.username
289+
default: "sharding_user"
326290
```
327291

328-
Auth query user can be overwritten in the pool
292+
PostgreSQL username used to authenticate the user and connect to the server
293+
if `server_username` is not set.
329294

330-
### auth_query_password (experimental)
295+
### password
331296
```
332-
path: general.auth_query_password
333-
default: <UNSET>
297+
path: pools.<pool_name>.users.<user_index>.password
298+
default: "sharding_user"
334299
```
335300

336-
Auth query password can be overwritten in the pool
301+
PostgreSQL password used to authenticate the user and connect to the server
302+
if `server_password` is not set.
337303

338-
## `pools.<pool_name>.users.<user_index>` Section
339-
340-
### username
304+
### server_username
341305
```
342-
path: pools.<pool_name>.users.<user_index>.username
343-
default: "sharding_user"
306+
path: pools.<pool_name>.users.<user_index>.server_username
307+
default: <UNSET>
308+
example: "another_user"
344309
```
345310

346-
Postgresql username
311+
PostgreSQL username used to connect to the server.
347312

348-
### password
313+
### server_password
349314
```
350-
path: pools.<pool_name>.users.<user_index>.password
351-
default: "sharding_user"
315+
path: pools.<pool_name>.users.<user_index>.server_password
316+
default: <UNSET>
317+
example: "another_password"
352318
```
353319

354-
Postgresql password
320+
PostgreSQL password used to connect to the server.
355321

356322
### pool_size
357323
```
@@ -382,7 +348,7 @@ default: [["127.0.0.1", 5432, "primary"], ["localhost", 5432, "replica"]]
382348

383349
Array of servers in the shard, each server entry is an array of `[host, port, role]`
384350

385-
### mirrors (experimental)
351+
### mirrors
386352
```
387353
path: pools.<pool_name>.shards.<shard_index>.mirrors
388354
default: <UNSET>

pgcat.toml

+14-2
Original file line numberDiff line numberDiff line change
@@ -125,10 +125,22 @@ connect_timeout = 3000
125125
# User configs are structured as pool.<pool_name>.users.<user_index>
126126
# This section holds the credentials for users that may connect to this cluster
127127
[pools.sharded_db.users.0]
128-
# Postgresql username
128+
# PostgreSQL username used to authenticate the user and connect to the server
129+
# if `server_username` is not set.
129130
username = "sharding_user"
130-
# Postgresql password
131+
132+
# PostgreSQL password used to authenticate the user and connect to the server
133+
# if `server_password` is not set.
131134
password = "sharding_user"
135+
136+
pool_mode = "session"
137+
138+
# PostgreSQL username used to connect to the server.
139+
# server_username = "another_user"
140+
141+
# PostgreSQL password used to connect to the server.
142+
# server_password = "another_password"
143+
132144
# Maximum number of server connections that can be established for this user
133145
# The maximum number of connection from a single Pgcat process to any database in the cluster
134146
# is the sum of pool_size across all users.

src/auth_passthrough.rs

+2
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ impl AuthPassthrough {
7272
let auth_user = crate::config::User {
7373
username: self.user.clone(),
7474
password: Some(self.password.clone()),
75+
server_username: None,
76+
server_password: None,
7577
pool_size: 1,
7678
statement_timeout: 0,
7779
pool_mode: None,

src/client.rs

+5
Original file line numberDiff line numberDiff line change
@@ -1128,6 +1128,11 @@ where
11281128
self.buffer.put(&message[..]);
11291129
}
11301130

1131+
// Close the prepared statement.
1132+
'C' => {
1133+
self.buffer.put(&message[..]);
1134+
}
1135+
11311136
// Execute
11321137
// Execute a prepared statement prepared in `P` and bound in `B`.
11331138
'E' => {

src/config.rs

+4
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,8 @@ impl Address {
178178
pub struct User {
179179
pub username: String,
180180
pub password: Option<String>,
181+
pub server_username: Option<String>,
182+
pub server_password: Option<String>,
181183
pub pool_size: u32,
182184
pub pool_mode: Option<PoolMode>,
183185
#[serde(default)] // 0
@@ -189,6 +191,8 @@ impl Default for User {
189191
User {
190192
username: String::from("postgres"),
191193
password: None,
194+
server_username: None,
195+
server_password: None,
192196
pool_size: 15,
193197
statement_timeout: 0,
194198
pool_mode: None,

src/server.rs

+21-9
Original file line numberDiff line numberDiff line change
@@ -103,19 +103,32 @@ impl Server {
103103
trace!("Sending StartupMessage");
104104

105105
// StartupMessage
106-
startup(&mut stream, &user.username, database).await?;
106+
let username = match user.server_username {
107+
Some(ref server_username) => server_username,
108+
None => &user.username,
109+
};
110+
111+
let password = match user.server_password {
112+
Some(ref server_password) => Some(server_password),
113+
None => match user.password {
114+
Some(ref password) => Some(password),
115+
None => None,
116+
},
117+
};
118+
119+
startup(&mut stream, username, database).await?;
107120

108121
let mut server_info = BytesMut::new();
109122
let mut process_id: i32 = 0;
110123
let mut secret_key: i32 = 0;
111-
let server_identifier = ServerIdentifier::new(&user.username, &database);
124+
let server_identifier = ServerIdentifier::new(username, &database);
112125

113126
// We'll be handling multiple packets, but they will all be structured the same.
114127
// We'll loop here until this exchange is complete.
115-
let mut scram: Option<ScramSha256> = None;
116-
if let Some(password) = &user.password.clone() {
117-
scram = Some(ScramSha256::new(password));
118-
}
128+
let mut scram: Option<ScramSha256> = match password {
129+
Some(password) => Some(ScramSha256::new(password)),
130+
None => None,
131+
};
119132

120133
loop {
121134
let code = match stream.read_u8().await {
@@ -172,11 +185,10 @@ impl Server {
172185
}
173186
};
174187

175-
match &user.password {
188+
match password {
176189
// Using plaintext password
177190
Some(password) => {
178-
md5_password(&mut stream, &user.username, password, &salt[..])
179-
.await?
191+
md5_password(&mut stream, username, password, &salt[..]).await?
180192
}
181193

182194
// Using auth passthrough, in this case we should already have a

utilities/requirements.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
tomli

0 commit comments

Comments
 (0)