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

security: Stabilize AdvancedTlsX509TrustManager. #11216

Open
wants to merge 16 commits into
base: master
Choose a base branch
from

Conversation

erm-g
Copy link
Contributor

@erm-g erm-g commented May 16, 2024

This PR is a part of 'Stabilize Advanced TLS' effort.
Clean up, improve javadoc, de-experimentalize of AdvancedTlsX509TrustManager, add a unit test (e2e already exists).

Copy link
Contributor

@matthewstevenson88 matthewstevenson88 left a comment

Choose a reason for hiding this comment

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

Thanks for the PR @erm-g! Generally LG, just a few minor comments.

@@ -135,8 +144,7 @@ public void updateTrustCredentials(X509Certificate[] trustCerts) throws IOExcept
keyStore.setCertificateEntry(alias, cert);
i++;
}
X509ExtendedTrustManager newDelegateManager = createDelegateTrustManager(keyStore);
this.delegateManager = newDelegateManager;
this.delegateManager = createDelegateTrustManager(keyStore);
Copy link
Contributor

Choose a reason for hiding this comment

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

Pre-existing readability nit: this. is redundant here and can be removed. There seem to be a few other instances of this pattern in this file, feel free to clean them all up if you like.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed, it's redundant here and the G style guide suggest to omit it.
I code it that way because it was the style here and at KeyManager, plus it also exists at

this.keyManagers = keyManagerList;

Let's defer to Eric

@@ -43,30 +44,38 @@
/**
* AdvancedTlsX509TrustManager is an {@code X509ExtendedTrustManager} that allows users to configure
* advanced TLS features, such as root certificate reloading, peer cert custom verification, etc.
* We expect only one of {@link AdvancedTlsX509TrustManager#useSystemDefaultTrustCerts()},
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you elaborate on what happens if the user does not respect this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Theoretically speaking, a user can do the following trick:

  1. Some process (non gRPC) updates the cert file
  2. User spawns a thread to periodically call updateTrustCredentialsFromFile(file)
  3. User calls updateTrustCredentialsFromFile(File trustCertFile, long period, TimeUnit unit,
    ScheduledExecutorService executor) multiple times without cancelling the result

As a result an outdated version of creds might be used till the next update. It's not truly a synchronization issue (that's why we don't guard this methods with locks) but a similar to it - so we decided to add a warning. Definitely the example is a made up one and we don't expect a user do anything like that

Copy link
Contributor

Choose a reason for hiding this comment

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

Makes sense, thanks for clarifying.

@@ -43,30 +44,38 @@
/**
* AdvancedTlsX509TrustManager is an {@code X509ExtendedTrustManager} that allows users to configure
* advanced TLS features, such as root certificate reloading, peer cert custom verification, etc.
* We expect only one of {@link AdvancedTlsX509TrustManager#useSystemDefaultTrustCerts()},
Copy link
Contributor

Choose a reason for hiding this comment

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

Optional presentation suggestion: Consider structuring the Javadoc as:

AdvancedTlsX509TrustManager is an {@code X509ExtendedTrustManager} that allows users to configure
advanced TLS features, such as root certificate reloading, peer cert custom verification, etc.

For Android users: this class is only supported in API level 24 and above.

We expect only one of {@link AdvancedTlsX509TrustManager#useSystemDefaultTrustCerts()},
{@link AdvancedTlsX509TrustManager#updateTrustCredentials(X509Certificate[])},
 {@link AdvancedTlsX509TrustManager#updateTrustCredentialsFromFile(File, long, TimeUnit,
 ScheduledExecutorService)},
{@link AdvancedTlsX509TrustManager#updateTrustCredentialsFromFile(File)} methods to be called
 after instantiation of this class.


Copy link
Contributor Author

Choose a reason for hiding this comment

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

I like the idea of extra empty LOCs for separation (pushed). But I prefer the current order because of

  1. Overall description
  2. Impl notes (for all users, including Android)
  3. Extra note (for Android users only)

Copy link
Contributor

Choose a reason for hiding this comment

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

SG, just an optional suggestion. :)

@@ -211,12 +218,15 @@ private void checkTrusted(X509Certificate[] chain, String authType, SSLEngine ss

/**
* Schedules a {@code ScheduledExecutorService} to read trust certificates from a local file path
* periodically, and update the cached trust certs if there is an update.
* periodically, and update the cached trust certs if there is an update. Please make sure to
Copy link
Contributor

Choose a reason for hiding this comment

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

micro-nit: s/and update the/and updates the

Copy link
Contributor Author

Choose a reason for hiding this comment

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

2 instances fixed, thank you!

@IgnoreJRERequirement
public final class AdvancedTlsX509TrustManager extends X509ExtendedTrustManager {
private static final Logger log = Logger.getLogger(AdvancedTlsX509TrustManager.class.getName());

// Minimum allowed period for refreshing files with credential information.
private static final int MINIMUM_REFRESH_PERIOD = 1;
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Prefer using Duration here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Same problem with the KeyManager - they use 'period' as a param name (plus it's long + TimeUnit) -

public Closeable updateTrustCredentialsFromFile(File trustCertFile, long period, TimeUnit unit,

Let's defer to Eric if I need to refactor all of it.

@RunWith(JUnit4.class)
public class AdvancedTlsX509TrustManagerTest {

public static final String CA_PEM_FILE = "ca.pem";
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Constants generally should be private unless we have a need for them to be visible.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed - nothing in the codebase depends on this const. However this style is in AdvancedTlsTest -

public static final String CA_PEM_FILE = "ca.pem";

Let's defer to Eric, I can also refactor the AdvancedTlsTest to make it consistent

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed here and in AdvancedTlsTest (#11139)

}

@Test
public void credentialSetting() throws Exception {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same style nits here RE test structure as in the key manager PR, but we can defer to Eric if you prefer.

@erm-g erm-g requested review from ejona86 May 16, 2024 19:20
Copy link
Contributor

@matthewstevenson88 matthewstevenson88 left a comment

Choose a reason for hiding this comment

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

LGTM modulo readability concerns, for which I'll defer to @ejona86.

@ejona86
Copy link
Member

ejona86 commented May 30, 2024

API review meeting notes:

CERTIFICATE_ONLY_VERIFICATION and INSECURELY_SKIP_ALL_VERIFICATION

Should document that these are dangerous to us, unless also specifying your own cert validation. Yes, one has INSECURELY in its name, but there should be some javadoc.

INSECURELY_SKIP_ALL_VERIFICATION

Mention that any loaded trust certs will be ignored. Yes, that's what it says, but just "those other methods that you use all the time stop doing anything" is helpful to point out.

  • Add docs to say that after build, no trust certs are loaded. You need to call one of the update/usesystem methods.
  • Builder needs more docs. For example, to explain that setSslSocketAndEnginePeerVerifier is called in addition to verifying certs as specified by Verification.
  • Should make clear that it is normal for nothing in the builder needs to be called? That should be the common case. Maybe just improve the AdvancedTlsX509TrustManager javadoc with a code snippet?

The minimum refresh period of 1 minute is enforced.

"enforced" could mean several different things, including "causes an error." Probably want to tweak that to be more clear.

@erm-g
Copy link
Contributor Author

erm-g commented Jun 1, 2024

API review meeting notes:

CERTIFICATE_ONLY_VERIFICATION and INSECURELY_SKIP_ALL_VERIFICATION

Should document that these are dangerous to us, unless also specifying your own cert validation. Yes, one has INSECURELY in its name, but there should be some javadoc.

INSECURELY_SKIP_ALL_VERIFICATION

Mention that any loaded trust certs will be ignored. Yes, that's what it says, but just "those other methods that you use all the time stop doing anything" is helpful to point out.

  • Add docs to say that after build, no trust certs are loaded. You need to call one of the update/usesystem methods.
  • Builder needs more docs. For example, to explain that setSslSocketAndEnginePeerVerifier is called in addition to verifying certs as specified by Verification.
  • Should make clear that it is normal for nothing in the builder needs to be called? That should be the common case. Maybe just improve the AdvancedTlsX509TrustManager javadoc with a code snippet?

The minimum refresh period of 1 minute is enforced.

"enforced" could mean several different things, including "causes an error." Probably want to tweak that to be more clear.

Done - I also reworded few comments before 'bumping up' to javadoc level. PTAL

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

Successfully merging this pull request may close these issues.

None yet

3 participants