Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement SASL SCRAM SHA 256 PLUS #21

Closed
thenonameguy opened this issue Oct 29, 2024 · 13 comments
Closed

Implement SASL SCRAM SHA 256 PLUS #21

thenonameguy opened this issue Oct 29, 2024 · 13 comments

Comments

@thenonameguy
Copy link

It's currently not possible to connect to neon.tech Postgres databases, for the lack of this support.

I'll have a stab at implementing it, will open a PR.

@igrishaev
Copy link
Owner

Implementing the PLUS version of SASL SCRAM would be amazing! I tried it once but didn't manage to make it work. Could you please take this file as a reference? https://github.com/igrishaev/pg2/blob/master/pg-core/src/java/org/pg/auth/ScramSha256.java

Ideally, your implementation should follow it's structure. It's a static file with methods called step1, step2, etc. Then you reuse that class in the auth pipeline:

https://github.com/igrishaev/pg2/blob/master/pg-core/src/java/org/pg/Connection.java#L766

In the "handleAuthenticationSASL" method of the Connection class, you extend the "isScramSha256Plus" branch.

@igrishaev
Copy link
Owner

I know that SASL SCRAM PLUS is implemented in Python, Node.JS, and Rust drivers for Postgres. Perhaps you can peek the details from there.

@thenonameguy
Copy link
Author

thenonameguy commented Nov 3, 2024

https://github.com/ongres/scram would you be willing to accept a PR that uses this dependency, instead of hand-rolling this auth method? PGJdbc uses the same library.

@igrishaev
Copy link
Owner

I'd like to clarify: do you really get an error when connecting a neon.tech-hosted database? I've checked the docs and they say, they use SCRAM 256. They don't mention the PLUS version of the algorithm:

https://neon.tech/blog/serverless-driver-for-postgres

Could please share an error that appears when connecting the database?

@thenonameguy
Copy link
Author

Sure, here you go:

SASL SCRAM SHA 256 PLUS method is not implemented yet
 :via
 [{:type org.pg.error.PGError
   :message SASL SCRAM SHA 256 PLUS method is not implemented yet
   :at [org.pg.Connection handleAuthenticationSASL Connection.java 772]}]
 :trace
 [[org.pg.Connection handleAuthenticationSASL Connection.java 772]
  [org.pg.Connection handleMessage Connection.java 699]
  [org.pg.Connection interact Connection.java 671]
  [org.pg.Connection interact Connection.java 681]
  [org.pg.Connection authenticate Connection.java 227]
  [org.pg.Connection <init> Connection.java 80]
  [org.pg.Connection <init> Connection.java 85]
  [pg.core$connect invokeStatic core.clj 393]
  [pg.core$connect invoke core.clj 383]

Using these connect params:

{:host ep-round-pond-a2yzni81.eu-central-1.aws.neon.tech, :port 5432, :database schemamap-demo, :user schemamap-demo_owner, :so-timeout 3000, :use-ssl? true}

When connecting with psql, this is the SSL connection that's built up:
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)

@igrishaev
Copy link
Owner

Grief, they don't allow the standard "SCRAM-SHA-256" algorithm.

I spent some time on looking at the library you shared above. In general, implementing our own version of -PLUS algorithm won't be difficult because I already have non-PLUS code working.

The real problem is, the -PLUS method accepts something which is called bindingData. This is a byte array fetched from a socket. The library doesn't care about how this data was fetched. It's done on JDBC side by this method:

https://github.com/jorsol/pgjdbc/blob/2f7511504c8eff34e55ed4b72df369687a09e3a8/pgjdbc/src/main/java/org/postgresql/core/v3/ScramAuthenticator.java#L95

@igrishaev
Copy link
Owner

The most critical part of the code is the following:

      SSLSession session = ((SSLSocket) socket).getSession();
      try {
        Certificate[] certificates = session.getPeerCertificates();
        if (certificates != null && certificates.length > 0) {
          Certificate peerCert = certificates[0]; // First certificate is the peer's certificate
          if (peerCert instanceof X509Certificate) {
            X509Certificate cert = (X509Certificate) peerCert;
            return TlsServerEndpoint.getChannelBindingData(cert);
          }
        }

and here is an excerpt from the library:

  public static byte @NotNull [] getChannelBindingData(final @NotNull X509Certificate serverCert)
      throws CertificateEncodingException {
    MessageDigest digestAlgorithm = getDigestAlgorithm(serverCert.getSigAlgName());
    if (digestAlgorithm == null) {
      return new byte[0];
    }
    return digestAlgorithm.digest(serverCert.getEncoded());
  }

If I have this working in PG2, than I'll be able to implement the -PLUS version of SCRUM

@igrishaev
Copy link
Owner

I'm going to register a free neon.tech installation and reproduce it locally. Don't know how long it will take, I'll keep posting my updated here.

@igrishaev
Copy link
Owner

igrishaev commented Nov 5, 2024

OK so I've fixed it. There was a bug in the Connection.java class. Although the PLUS method is not implemented yet, the code tried to use it even when the non-PLUS version of SCRAM was available. It was a messy if/else branching.

I've setup a database on neon.tech site and managed to reach it from REPL with this config:

{:host "ep-fancy-queen-a2kw7zqr.eu-central-1.aws.neon.tech"
 :port 5432
 :user "test_owner"
 :password "<my password>"
 :database "test"
 :use-ssl? true} ;; mandatory!

Could you please try it with the latest release 0.1.19?

@igrishaev
Copy link
Owner

igrishaev commented Nov 5, 2024

@thenonameguy Once you confirm it works, I'll close that issue and will create another one to implement -PLUS version of SCRAM.

@thenonameguy
Copy link
Author

Screenshot 2024-11-05 at 09 45 05

Works, thanks so much!

@igrishaev
Copy link
Owner

Cool, closing in favor of #22

@Neustradamus
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants