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

s2a: Add gRPC S2A #11113

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

s2a: Add gRPC S2A #11113

wants to merge 11 commits into from

Conversation

rmehta19
Copy link

@rmehta19 rmehta19 commented Apr 18, 2024

Add S2A Java client to gRPC Java.

Context: https://github.com/google/s2a-go/blob/main/README.md

Copy link

linux-foundation-easycla bot commented Apr 18, 2024

CLA Signed

The committers listed above are authorized under a signed CLA.

@matthewstevenson88
Copy link
Contributor

Thanks @rmehta19. Can you PTAL at the test failures?

@rmehta19
Copy link
Author

rmehta19 commented Apr 22, 2024

@matthewstevenson88, I made 2 changes and it looks like 2/3 linux runs are passing. tests(11) is failing with an error in code that was not affected by this PR, so I don't think that failure is related.

The changes:

  • The build originally failed because the generated grpc code in this PR did not match the code generated by the codegen plugin. I couldn't easily compile the codegen myself(due to reasons explained in: protoc-gen-grpc-java not available on apple m1 #7690). So instead I used the latest published binary available on https://mvnrepository.com/artifact/io.grpc/protoc-gen-grpc-java (1.63) to generate S2AServiceGrpc.java (Created and used a separate simple maven project just to run the plugin and get grpc gen code). Then I changed line 8 & 9 of S2AServiceGrpc.java to match other generated code in this repo (ex:

    value = "by gRPC proto compiler",
    comments = "Source: grpc/gcp/handshaker.proto")
    ). This resolved the errors thrown by
    - name: Check for modified codegen
    run: test -z "$(git status --porcelain)" || (git status && echo Error Working directory is not clean. Forget to commit generated files? && false)

  • A failure in the tests was caused when IntegrationTest.java is in package io.grpc.s2a: GetAuthenticationMechanismsTest.java fails because the flag is not being set by JCommander (or perhaps it is getting overwritten). When I moved IntegrationTest.java into the same package as GetAuthenticationMechanismsTest.java: io.grpc.s2a.handshaker, this error does not happen.

@@ -0,0 +1,79 @@
// Copyright 2022 Google LLC
Copy link
Contributor

Choose a reason for hiding this comment

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

Just to confirm, this proto will be removed from this PR once the other PR is merged?

Copy link
Author

Choose a reason for hiding this comment

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

I believe we will maintain a copy of the protos in this directory. IIUC, there is an automated process that syncs protos in grpc-proto to protos here. Context: grpc/grpc-proto#12

E.g. ALTS protos are maintained here: alts/src/main/proto/grpc/gcp

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!

Copy link
Member

Choose a reason for hiding this comment

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

You'll want to add s2a to the list of modules we copy protos for:

for project in alts grpclb services rls interop-testing; do

Copy link
Author

Choose a reason for hiding this comment

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

Done

@matthewstevenson88
Copy link
Contributor

LGTM, thanks @rmehta19! When you have a chance, please remove "draft" to the PR title and can we say a bit more in the CL description including pointing to the S2A-Go README (similar to what we did in the proto PR)?

After that, can we get sign-off from @erm-g and @ejona86?

@rmehta19 rmehta19 changed the title [DRAFT]s2a: Add gRPC S2A s2a: Add gRPC S2A Apr 26, 2024
@rmehta19
Copy link
Author

LGTM, thanks @rmehta19! When you have a chance, please remove "draft" to the PR title and can we say a bit more in the CL description including pointing to the S2A-Go README (similar to what we did in the proto PR)?

After that, can we get sign-off from @erm-g and @ejona86?

Done -- thank you for the review @matthewstevenson88!

Channel getChannel();

/** Returns a channel to the channel pool. */
void returnChannel(Channel channel);
Copy link
Contributor

Choose a reason for hiding this comment

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

Not really sure about naming conventions here, but does 'releaseChannel' or 'returnToPool' sound better?

Copy link
Author

Choose a reason for hiding this comment

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

Changed naming to returnToPool.

See commit: S2AChannelPool returnChannel --> returnToPool name change.

cc: @matthewstevenson88

*/
@ThreadSafe
public final class S2AGrpcChannelPool implements S2AChannelPool {
private static final int MAX_NUMBER_USERS_OF_CACHED_CHANNEL = 100000;
Copy link
Contributor

Choose a reason for hiding this comment

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

Are we ok to keep it hardcoded instead of exposing it via some param/flag?

Copy link
Author

Choose a reason for hiding this comment

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

hardcoding 100000 seems fine to me, @matthewstevenson88 WDYT?

Copy link
Contributor

Choose a reason for hiding this comment

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

If it's OK with you all, I'd prefer to keep it hardcoded until we have a use case that requires us to expose it.

public synchronized Channel getChannel() {
checkState(state.equals(State.OPEN), "Channel pool is not open.");
checkState(
numberOfUsersOfCachedChannel >= 0,
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure how numberOfUsersOfCachedChannel can be negative. It's a private var, and you decrease it by -1 in LOC 96 after checking that it's >0 in LOC 93. Am I missing something?

Copy link
Author

Choose a reason for hiding this comment

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

You are right, thanks for pointing this out -- removed this unnecessary state check.

public final class S2AHandshakerServiceChannel {
private static final ConcurrentMap<String, Resource<Channel>> SHARED_RESOURCE_CHANNELS =
Maps.newConcurrentMap();
private static final Duration DELEGATE_TERMINATION_TIMEOUT = Duration.ofSeconds(2);
Copy link
Contributor

Choose a reason for hiding this comment

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

Are we ok to keep these 2 hardcoded instead of exposing it via some param/flag?

Copy link
Author

Choose a reason for hiding this comment

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

Hardcoding these two timeouts is ok with me, keeping it as is might help readability. @matthewstevenson88 WDYT?

Copy link
Contributor

Choose a reason for hiding this comment

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

If it's OK with you all, I'd prefer to keep it hardcoded until we have a use case that requires us to expose it.


/** Indicates that a connection has been closed. */
@SuppressWarnings("serial") // This class is never serialized.
final class ConnectionIsClosedException extends IOException {
Copy link
Contributor

Choose a reason for hiding this comment

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

Never seen such naming, typically in Java it's 'ConnectionClosedException'

Copy link
Author

Choose a reason for hiding this comment

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

Done. Changed to ConnectionClosedException.

}

/** Returns the proto {@link Identity} representation of this identity instance. */
public Identity identity() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like a getter, should it be 'getIdentity'?

Copy link
Author

Choose a reason for hiding this comment

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

Done.

description = "The access token used to authenticate to S2A.")
private static String accessToken = System.getenv(ENVIRONMENT_VARIABLE);

public synchronized void reset() {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure I understand why 'synchronized' is needed here.

Copy link
Author

Choose a reason for hiding this comment

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

This code doesn't exist anymore, as we removed the dependency on Jcommander and replaced it with a private field & setter

distinguished_name = req_distinguished_name
req_extensions = req_ext

[req_distinguished_name]
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you add the values you entered while generating certs?

Copy link
Author

Choose a reason for hiding this comment

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

Done, as discussed offline, I updated the README with the the values used to populate these fields.

@ejona86, does this sound ok to you? @erm-g pointed me to something similar he has done in go: https://github.com/grpc/grpc-go/pull/6670/files#diff-ac85255b49c8d65b03b560d9959b99c6d9338de1400da6fc2d4133a434a376ad

@BeforeClass
public static void setUpClass() {
// Set the token that the client will use to authenticate to the S2A.
JCommander.newBuilder().addObject(FLAGS).build().parse(SET_TOKEN);
Copy link
Member

Choose a reason for hiding this comment

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

You're using jcommander to just set a static field. This is many more steps than just having a package-private field/setter. Let's not add a dependency on jcommander.

Copy link
Author

Choose a reason for hiding this comment

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

Done: refactored and removed the JCommander dependency.

Copy link
Member

@ejona86 ejona86 left a comment

Choose a reason for hiding this comment

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

To make sure I understand, s2a is the public API, and s2a/channel and s2a/handshaker are internal APIs. Are those internal APIs to be used anywhere, even within Google?

* Configures gRPC to use S2A for transport security when establishing a secure channel. Only for
* use on the client side of a gRPC connection.
*/
@NotThreadSafe
Copy link
Member

Choose a reason for hiding this comment

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

Credentials must be thread-safe. Should this be on the Builder instead?

Copy link
Author

Choose a reason for hiding this comment

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

Yes, the Builder is the one that's not thread safe -- done.

@@ -0,0 +1,79 @@
// Copyright 2022 Google LLC
Copy link
Member

Choose a reason for hiding this comment

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

You'll want to add s2a to the list of modules we copy protos for:

for project in alts grpclb services rls interop-testing; do

ejona86 pushed a commit to grpc/grpc-proto that referenced this pull request Apr 29, 2024
@rmehta19
Copy link
Author

To make sure I understand, s2a is the public API, and s2a/channel and s2a/handshaker are internal APIs. Are those internal APIs to be used anywhere, even within Google?

Correct s2a is the public api, s2a/handshaker and s2a/channel are internal APIs to only be used within the s2a package.

cc: @matthewstevenson88

@rmehta19
Copy link
Author

Thank you for reviewing @erm-g, @ejona86 ! I have addressed the comments in separate commits. PTAL when you get a chance, and provide any additional feedback.

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

4 participants