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

Adding more options to the SSL configuration #2039

Closed
user5100 opened this issue Mar 14, 2023 · 11 comments · Fixed by #3139
Closed

Adding more options to the SSL configuration #2039

user5100 opened this issue Mar 14, 2023 · 11 comments · Fixed by #3139
Labels
Milestone

Comments

@user5100
Copy link

Is your feature request related to a problem? Please describe.
Hi all, I would need to have more parameterization of the SSL context than it is currently available. Basically I would need the server to also use a trustStore, to enable/disable mutual authentication between client and server, and to define other additional options, including setting a custom cipher suite.

Describe the solution you'd like
The solution I would need should allow the following options to be added to the ssl configuration:

  • Add an option to directly pass objects of type javax.net.ssl.keyManagerFactory and javax.net.ssl.trustManagerFactory (both for both client and server contexts)
  • Add an option to allow the creation and parameterization of a javax.net.ssl.SSLEngine, so as to indicate enabled cipher suites, enabled ssl protocols, client authentication, etc...
  • Allow the SSL context to be changed during application execution (although I do not know if it is already possible to do this)

Describe alternatives you've considered
none

Additional context
Thank you for the support

@user5100 user5100 added the enhancement New feature or request label Mar 14, 2023
@jdegoes
Copy link
Member

jdegoes commented Mar 17, 2023

We need to think of a way to do this in such a fashion as to minimize the imprint of the JVM in the public API, for Scala Native, etc.

@jdegoes jdegoes added this to the 1.1 milestone Mar 17, 2023
@LannyRipple
Copy link

Could also use this feature. My company has implemented a custom KeyStore to be update-aware of short-term credentials injected into K8S pods. No telling what else they are doing under the hood but we're supposed to use it to initialize a KeyManagerFactory for SSLContext initialization. We'd like zio-http instead of our current akka-http but this is a showstopper short of forking zio-http for an in-house workaround.

@jdegoes
Copy link
Member

jdegoes commented Jan 3, 2024

@LannyRipple How would you like to specify this? KeyManagerFactory and SSLContext are not Netty-specific so could be used in ZIO HTTP.

@jdegoes
Copy link
Member

jdegoes commented Jan 3, 2024

/bounty $250

Copy link

algora-pbc bot commented Jan 3, 2024

💎 $250 bounty • ZIO

Steps to solve:

  1. Start working: Comment /attempt #2039 with your implementation plan
  2. Submit work: Create a pull request including /claim #2039 in the PR body to claim the bounty
  3. Receive payment: 100% of the bounty is received 2-5 days post-reward. Make sure you are eligible for payouts

Thank you for contributing to zio/zio-http!

Add a bountyShare on socials

Attempt Started (GMT+0) Solution
🟢 @varshith257 #3139

@LannyRipple
Copy link

LannyRipple commented Jan 4, 2024

I'm a bit at a loss there. We aren't using Scala Native and such so for us it's just adding to ClientSSLConfig and modifying ClientSSLConverter to do the needful and not worrying that our zio-http would be leaking JVM types. Sadly there's no way my team will agree to us maintaining a fork (I don't blame them).

Looking at my company's example code (SSL/PKI newbie here) it looks like we need

keyStoreInstanceName: String
keyStoreInputStreamtoLoad: => InputStream
// keyManagerFactoryAlgorithm -- going with default for now
// sslContextInstanceVersion: String -- going with latest.  suspect this doesn't change much

Looks like the exact same pattern for TrustStoreFactory which you would want for mTLS setup. The following certainly leaks JVM intent but I think stays away from JVM specifics until you would be down at the Netty/Jetty/Other-JVM-Lib level.

ClientSSLConfig.FromJavaxNetSsl.builder()
  .keyStoreFactoryInfo(keyStoreInstanceName, keyStoreInputStreamThunk)
  .trustStoreFactoryInfo(trustStoreInstanceName, trustStoreInputStreamThunk)
  .build()

Or maybe the InputStreams are just the paths and Netty handles the reads at SslContext creation.

LannyRipple added a commit to LannyRipple/zio-http that referenced this issue Feb 6, 2024
* Provides ClientSSLConfig FromJavaxNetSsl to allow configuring
  client SSLContext using a javax.net.ssl.KeyManagerFactory and/or
  a javax.net.ssl.TrustManagerFactory.
* Only partially addresses zio#2039.
@asr2003
Copy link
Contributor

asr2003 commented Jul 1, 2024

/attempt #2039

Copy link

algora-pbc bot commented Jul 1, 2024

@asr2003: We appreciate your enthusiasm but since you already have 3 active bounty attempts, we're going to keep this open for other contributors to attempt. 🫡

Copy link

algora-pbc bot commented Sep 15, 2024

💡 @varshith257 submitted a pull request that claims the bounty. You can visit your bounty board to reward.

Copy link

algora-pbc bot commented Sep 27, 2024

🎉🎈 @varshith257 has been awarded $250! 🎈🎊

@constantinos-p
Copy link

constantinos-p commented Jan 21, 2025

Hi, I see the requirement says: for both client and server contexts
Was the server side "symmetrical" SSLConfig implemented?
Similarly to @LannyRipple my company is also moving from akka to zio.

Using akka http we could create the SslConfig and pass it to the akka server which is pretty standard (shown below).
Are you guys planning to support these on server side? I could open an MR myself if you want.

def fromConfig(config: KeystoreConfiguration): SSLContext = {
    val ks = KeyStore.getInstance(config.`type`)

    val keyStream = (config.file, config.binary) match {
      case (_, Some(binary)) =>
        new ByteArrayInputStream(Base64.getDecoder.decode(binary.getBytes(StandardCharsets.UTF_8)))
      case (Some(filePath), None) => new FileInputStream(filePath)
      case _ => throw new IllegalArgumentException("Either file or binary must be provided for SSL keystore")
    }

    ks.load(keyStream, config.password.toCharArray)

    val kmf = KeyManagerFactory.getInstance("SunX509")
    kmf.init(ks, config.password.toCharArray)

    val tmf = TrustManagerFactory.getInstance("SunX509")
    tmf.init(ks)

    val sslContext: SSLContext = SSLContext.getInstance("TLSv1.2")
    sslContext.init(
      kmf.getKeyManagers,
      tmf.getTrustManagers,
      new SecureRandom
    )

    sslContext
  }  

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

Successfully merging a pull request may close this issue.

5 participants