Skip to content

Conversation

@hasnain-db
Copy link
Contributor

What changes were proposed in this pull request?

This PR adds a separate way of configuring the private key for RPC SSL support when using openssl.

Why are the changes needed?

Right now with config inheritance we support:

  • JKS with password A, PEM with password B
  • JKS with no password, PEM with password A
  • JKS and PEM with no password

But we do not support the case where JKS has a password and PEM does not. If we set keyPassword we will attempt to use it, and cannot set spark.ssl.rpc.keyPassword to null to override the password. So let's make it a separate flag as the easiest workaround.

This was noticed while migrating some existing deployments to the RPC SSL support where we use openssl support for RPC and use a key with no password

Does this PR introduce any user-facing change?

Yes, this affects how the (currently unreleased) RPC SSL feature is configured going forward

How was this patch tested?

Updated test configs to match the issue I saw, which would fail SSLFactory.init() saying key was invalid. Tests now pass.

build/sbt
> project network-common
> testOnly
> project network-shuffle
> testOnly
> project core
> test *Ssl*

Was this patch authored or co-authored using generative AI tooling?

No

@hasnain-db
Copy link
Contributor Author

cc @mridulm @JoshRosen let me know if this makes sense or if there's a way to do this purely via existing configs (in which case I can abandon this PR and just update docs)

Copy link
Contributor

@JoshRosen JoshRosen Nov 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change makes sense and I agree that this seems like the right thing to do for PEM-based authentication.

After this change, though, I don't see any additional usages of b.keyPassword in RPL SSL code.

That code was added in cfea300.

There, it looks like it influences both Akka and Jetty.

In the Jetty code, which hasn't changed to this day, it does

      keyStorePassword.foreach(sslContextFactory.setKeyStorePassword)
      keyPassword.foreach(sslContextFactory.setKeyManagerPassword)

and flows to the "key manager" password.

Within Jetty, that password is read at once place:

protected KeyManager[] getKeyManagers(KeyStore keyStore) throws Exception
    {
        KeyManager[] managers = null;

        if (keyStore != null)
        {
            KeyManagerFactory keyManagerFactory = getKeyManagerFactoryInstance();
            keyManagerFactory.init(keyStore, _keyManagerPassword == null ? (_keyStorePassword == null ? null : _keyStorePassword.toString().toCharArray()) : _keyManagerPassword.toString().toCharArray());
            managers = keyManagerFactory.getKeyManagers();

So based this Jetty code, it looks like the right place to thread this password is to use it when initializing the KeyManagerFactory.

Given that, do you think we need to have similar logic in our own code at

  private static KeyManager[] keyManagers(File keyStore, String keyStorePassword)
      throws NoSuchAlgorithmException, CertificateException,
          KeyStoreException, IOException, UnrecoverableKeyException {
    KeyManagerFactory factory = KeyManagerFactory.getInstance(
      KeyManagerFactory.getDefaultAlgorithm());
    char[] passwordCharacters = keyStorePassword != null? keyStorePassword.toCharArray() : null;
    factory.init(loadKeyStore(keyStore, passwordCharacters), passwordCharacters);
    return factory.getKeyManagers();
  }

to use the key password if provided and fall back on the key store password if empty?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Within Jetty, that password is read at once place:

Thanks!! This is what I had missed earlier and I wasn't sure how to pass the password.

To keep this change focused, and unblocked, though (I'll need to do more work to test this) I've filed https://issues.apache.org/jira/browse/SPARK-46132 - hope it's fine for me to put up a separate PR with just that change (+ additional tests)

Copy link
Contributor

@JoshRosen JoshRosen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes sense overall, and from a compatibility perspective I think this is fine since this new feature has yet to ship in a Apache Spark release.

I left two comments, one about a doc typo and another about a potential bug related to keyPassword possibly being ignored in JKS SSL.

@hasnain-db
Copy link
Contributor Author

Thank you @JoshRosen ! I've fixed the typo and filed a ticket to track the additional item - you have shown me how to fix it (I'd gotten confused in my last look). Hope it's OK to punt that change to a different PR.

@hasnain-db hasnain-db requested a review from JoshRosen November 28, 2023 18:41
@hasnain-db
Copy link
Contributor Author

CI failure is in generating docs but that looks unrelated to this PR

Copy link
Contributor

@JoshRosen JoshRosen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

I agree that the documentation build failure appears to be unrelated: it looks like we also hit this in another PR at #43978 (comment)

/cc @mridulm, in case you want to give this a review as well.

@hasnain-db
Copy link
Contributor Author

cc @mridulm in case you want to take a look.

Copy link
Contributor

@mridulm mridulm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missed out on this, looks good to me.

@mridulm
Copy link
Contributor

mridulm commented Dec 6, 2023

Can you check on the build failure @hasnain-db ? If it unrelated to the PR, it might be something which is fixed in master (in which case, a rebase should help).

@hasnain-db
Copy link
Contributor Author

@mridulm the failure was a docs failure that was unrelated to this PR but it's been long enough that a rebase is warranted. I'll do that and re-request review once CI is green again.

@hasnain-db
Copy link
Contributor Author

@mridulm CI is now green

@mridulm mridulm closed this in 9c9020e Dec 7, 2023
@mridulm
Copy link
Contributor

mridulm commented Dec 7, 2023

Merged to master.
Thanks for adding this @hasnain-db !
Thanks for the review @JoshRosen :-)

dbatomic pushed a commit to dbatomic/spark that referenced this pull request Dec 11, 2023
### What changes were proposed in this pull request?

This PR adds a separate way of configuring the private key for RPC SSL support when using openssl.

### Why are the changes needed?

Right now with config inheritance we support:

* JKS with password A, PEM with password B
* JKS with no password, PEM with password A
* JKS and PEM with no password

But we do not support the case where JKS has a password and PEM does not. If we set `keyPassword` we will attempt to use it, and cannot set `spark.ssl.rpc.keyPassword` to null to override the password. So let's make it a separate flag as the easiest workaround.

This was noticed while migrating some existing deployments to the RPC SSL support where we use openssl support for RPC and use a key with no password

### Does this PR introduce _any_ user-facing change?

Yes, this affects how the (currently unreleased) RPC SSL feature is configured going forward

### How was this patch tested?

Updated test configs to match the issue I saw, which would fail `SSLFactory.init()` saying key was invalid. Tests now pass.

```
build/sbt
> project network-common
> testOnly
> project network-shuffle
> testOnly
> project core
> test *Ssl*
```

### Was this patch authored or co-authored using generative AI tooling?

No

Closes apache#43998 from hasnain-db/new-flag.

Authored-by: Hasnain Lakhani <[email protected]>
Signed-off-by: Mridul Muralidharan <mridul<at>gmail.com>
mridulm pushed a commit that referenced this pull request Dec 13, 2023
### What changes were proposed in this pull request?

Add support for a separate key password in addition to the key store password for JKS keys. This is needed for keys which may have a key password in addition to a key store password. We already had this support for the UI SSL support, so for compatibility we should have it here.

This wasn't done earlier as I wasn't sure how to implement it but the discussion in #43998 (comment) suggested the right way.

### Why are the changes needed?

These are needed to support users who may have such keys configured.

### Does this PR introduce _any_ user-facing change?

No

### How was this patch tested?

Added some unit tests

```
build/sbt
> project network-common
> testOnly
```

### Was this patch authored or co-authored using generative AI tooling?

No

Closes #44264 from hasnain-db/separate-pw.

Authored-by: Hasnain Lakhani <[email protected]>
Signed-off-by: Mridul Muralidharan <mridul<at>gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants