libredb / libredb/libredb-studio

[FEATURE] openGauss support: the SHA256 and MD5_SHA256 authentication handshakes

Open
#815 0 comments 0 reactions 0 assignees View on GitHub
enhancement
Dominant language
TypeScript
Stars
726
Forks
119
Avg merge
7h 41m
Merged PRs (30d)
284

Description

One code path, the SHA256 and MD5_SHA256 authentication handshakes, opens openGauss and the engines derived from it, Huawei GaussDB and Vastbase among them. Those are the engines Chinese public sector and banking are required to run, and they have few good clients. That ratio is the reason to look at this at all: the work is confined to the connection handshake, and everything behind it is already in place.

I measured what is behind it. The summary is at the end of the first section.

## Is your feature request related to a problem?

We cannot connect to openGauss at all. A stock install refuses the driver before any query is sent.

Measured on `opengauss/opengauss:5.0.0`, default configuration, using `pg` (node-postgres), the driver the product already ships:

```
SASL: Only mechanism(s) SCRAM-SHA-256 are supported
```

**That message is misleading and it matters for whoever picks this up.** The server never asked for SCRAM. PostgreSQL and openGauss use the same authentication request numbers for different things:

| Code | PostgreSQL | openGauss |
| --- | --- | --- |
| 10 | SASL (SCRAM) | SHA256 |
| 11 | SASL continue | MD5_SHA256 |
| 13 | - | SM3 |

openGauss sends request 10 meaning SHA256. `pg` reads 10 as SASL, looks for a mechanism list, finds nothing it knows and prints the SCRAM line. So this is not "add SCRAM support" and not "the server wants a newer PostgreSQL". It is a distinct handshake that happens to collide on the number.

The server default is `password_encryption_type = 2`, SHA256 only.

## Describe the solution you'd like

Handle authentication requests 10 and 11 in the PostgreSQL connection path, as openGauss defines them, selected by connection type rather than guessed.

## Describe alternatives you've considered

**Ask operators to set `password_encryption_type = 1`.** This works. I verified it: set the parameter, create a new user, and the stock driver connects. It is still the wrong answer to ship. The audience is banking and public sector, and the request amounts to asking them to weaken authentication for our benefit. It also needs a new user, because an existing password hash is not converted in place.

**Detect the engine automatically.** Not possible here. `version()` reports `9.2.4` and is only readable after the handshake completes, so there is nothing to detect before the point where we fail. The connection type has to be a choice the user makes when creating the connection.

## Use Case

An operator in a Chinese bank or state agency runs openGauss because policy requires it, and has no browser based SQL client with SSO and an audit trail. Today they cannot open a connection at all.

## Additional Context

This is the part that decides whether the handshake is worth writing. I relaxed the server setting only to see what sits behind the wall, then measured each layer separately.

openGauss 5.0.0, `password_encryption_type = 1`, new user, stock `pg` driver:

| Layer | Result |
| --- | --- |
| Connection | Works. `server_version` reports `9.2.4`, transactions, rollback and parameterised queries all behave |
| Object browser | Works. Foreign keys read back correctly, so ER diagrams have what they need |
| Query | Works. `EXPLAIN (FORMAT JSON)` is supported, and `pg_cancel_backend` genuinely cancels |
| Monitoring | Half. `pg_stat_activity` works, `pg_stat_statements` does not exist |
| Numbers | Correct |

**On the numbers, since the project treats this as a first class question.** I loaded a table with exactly 2000 rows and checked by hand:

| Reading | Value | Correct |
| --- | --- | --- |
| `count(*)` | 2000 | measured |
| `reltuples` | 2000 | yes, exact |
| `pg_relation_size` | 155648 | yes, a real figure |
| `pg_total_relation_size` | 253952 | yes |
| Cache hit ratio | 99.5% | yes |

This is worth stating plainly against the engines already documented: Citus and TimescaleDB report row counts and sizes that are wrong rather than missing, and YugabyteDB reports 0 until `ANALYZE` runs. openGauss reports the truth. If it is ever listed, that line belongs in the measurement table.

Three smaller findings for whoever implements this:

- **`regnamespace` does not exist.** The type arrived in PostgreSQL 9.4 and openGauss is 9.2 based, so `'public'::regnamespace` fails. Joining `pg_namespace` works.
- **The default schema is not `public`.** `search_path` is `"$user",public` and openGauss gives every user a schema named after them, so tables land there. An object browser that assumes `public` shows an empty database.
- **Monitoring cannot be complete.** openGauss keeps its statistics in the `dbe_perf` schema, which held 177 tables in my instance and refused reads even to a sysadmin user. This is not a defect to fix, it is the existing pattern where a surface reports that the engine does not publish the figure.

Two notes to save the next person time:

- **Pin the image to `5.0.0`.** `opengauss/opengauss:latest` (7.0.0-RC3) fails to start on both arm64 and amd64 with `libopenblas.so.0: cannot open shared object file`. It is a packaging fault in the image, not an architecture problem.
- **KingBase and Vastbase are the same code path but cannot be measured yet.** Neither publishes an open image; both want a licence file obtained from the vendor. Vastbase is openGauss derived, so it should follow once this handshake exists, and I will measure them rather than assume before any name is published.

## Implementation Notes (Optional)

openGauss ships its own Go driver, which implements all three handshakes, so the algorithm is published and has a reference implementation to check against rather than being reverse engineered.

One constraint worth knowing early: `pg` has no extension point for custom authentication, so this cannot be a plug in on top of the existing driver and means owning the connection path for this connection type.

## Related Issues

None yet. Filed after measuring, and no name should go in the README until the handshake exists and a live instance has answered, which is the rule the engine list already follows.

Contributor guide

Open the contributing guide

Research direction

Start by tracing the PostgreSQL connection path and how the bundled pg (node-postgres) driver handles authentication requests 10 and 11. Compare the behavior with openGauss's Go driver, using the pinned opengauss/opengauss:5.0.0 image as the test target. Done means a user-selected connection type can complete both SHA256 and MD5_SHA256 handshakes without weakening password encryption.

Written by the indexing model from the issue text.

Assessment

Tech stack
node.js, postgresql, typescript
Domain
authentication, backend, databases
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.