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

Query S2A Address from MDS #1400

Open
wants to merge 13 commits into
base: main
Choose a base branch
from

Conversation

rmehta19
Copy link

@rmehta19 rmehta19 commented May 9, 2024

Add utility to get S2A address from MDS MTLS autoconfiguration endpoint.

This utility will be used when creating mTLS channel using S2A Java Client, which takes S2A Address as input to create S2AChannelCredentials.

Parallel change in go: googleapis/google-api-go-client#1874
S2A Java client: grpc/grpc-java#11113

@rmehta19 rmehta19 requested a review from a team as a code owner May 9, 2024 00:20
@product-auto-label product-auto-label bot added the size: l Pull request size is large. label May 9, 2024
@rmehta19
Copy link
Author

cc: @xmenxk

public static final String GOOGLE = "Google";
private static final String PARSE_ERROR_S2A = "Error parsing Mtls Auto Config response.";

private MtlsConfig config;
Copy link

Choose a reason for hiding this comment

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

nit: MTLS?

oauth2_http/java/com/google/auth/oauth2/S2A.java Outdated Show resolved Hide resolved
oauth2_http/java/com/google/auth/oauth2/S2A.java Outdated Show resolved Hide resolved
Comment on lines 67 to 89
if (transportFactory == null) {
transportFactory =
Iterables.getFirst(
ServiceLoader.load(HttpTransportFactory.class), OAuth2Utils.HTTP_TRANSPORT_FACTORY);
}
String url = getMdsMtlsEndpoint();
GenericUrl genericUrl = new GenericUrl(url);
HttpRequest request =
transportFactory.create().createRequestFactory().buildGetRequest(genericUrl);
JsonObjectParser parser = new JsonObjectParser(OAuth2Utils.JSON_FACTORY);
request.setParser(parser);
request.getHeaders().set(METADATA_FLAVOR, GOOGLE);
request.setThrowExceptionOnExecuteError(false);
HttpResponse response = request.execute();

if (!response.isSuccessStatusCode()) {
return MtlsConfig.createBuilder().build();
}

InputStream content = response.getContent();
if (content == null) {
return MtlsConfig.createBuilder().build();
}
Copy link

Choose a reason for hiding this comment

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

is it possible to reuse the code below for querying mds endpoint?

private HttpResponse getMetadataResponse(String url) throws IOException {

Copy link
Author

Choose a reason for hiding this comment

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

We could use this function to get the MDS HttpResponse, but it would only replace a few lines (~7) in this function:

creating the HttpRequest and executing it to get the response, replaced with

response = getMetadataResponse(url).

However, in order to do this, we would also have to:

  • ignore the ComputeEngineCredentials specific errors thrown by the function, because we only care if we are able to successfully create a response (aligning with Go implementation, return empty S2A Address if any error). This technically works, although I am not sure it is best practice.
  • getMetadataResponse(String url) is not static, so we would have to create an instance of ComputeEngineCredentials to use it.

WDYT?

Copy link

sonarcloud bot commented May 17, 2024

@rmehta19
Copy link
Author

@westarle, friendly ping :). Please review when you get a chance.

import com.google.errorprone.annotations.CanIgnoreReturnValue;

/** Holds an mTLS configuration (consists of address of S2A) retrieved from the Metadata Server. */
public final class MtlsConfig {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this should be re-branded to S2AConfig. MtlsConfig is much more generic than the settings in this class.

Comment on lines +25 to +28
public static final String METADATA_FLAVOR = "Metadata-Flavor";
public static final String GOOGLE = "Google";
private static final int MAX_MDS_PING_TRIES = 3;
private static final String PARSE_ERROR_S2A = "Error parsing Mtls Auto Config response.";
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there any existing code for these constants?

*/
@ThreadSafe
public final class S2A {
public static final String MTLS_CONFIG_ENDPOINT =
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
public static final String MTLS_CONFIG_ENDPOINT =
public static final String S2A_CONFIG_ENDPOINT_POSTFIX =

public static final String METADATA_FLAVOR = "Metadata-Flavor";
public static final String GOOGLE = "Google";
private static final int MAX_MDS_PING_TRIES = 3;
private static final String PARSE_ERROR_S2A = "Error parsing Mtls Auto Config response.";
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this error message should be expanded to explain what went wrong and how it can be triaged.

Comment on lines +42 to +45
if (config == null) {
config = getMdsMtlsConfig();
}
return config.getMtlsS2AAddress();
Copy link
Contributor

Choose a reason for hiding this comment

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

Could a valid config be a requirement to instantiate this class?

*
* @return the {@link MtlsConfig}.
*/
private MtlsConfig getMdsMtlsConfig() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
private MtlsConfig getMdsMtlsConfig() {
private MtlsConfig getS2AConfigFromMDS() {

Comment on lines +72 to +76
if (transportFactory == null) {
transportFactory =
Iterables.getFirst(
ServiceLoader.load(HttpTransportFactory.class), OAuth2Utils.HTTP_TRANSPORT_FACTORY);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this be outside of the loop?

}
HttpRequest request =
transportFactory.create().createRequestFactory().buildGetRequest(genericUrl);
JsonObjectParser parser = new JsonObjectParser(OAuth2Utils.JSON_FACTORY);
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this be outside of the loop?

.setMtlsS2AAddress(mtlsS2AAddress)
.build();
}
return MtlsConfig.createBuilder().build();
Copy link
Contributor

Choose a reason for hiding this comment

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

How will callers know if a valid config is returned?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
size: l Pull request size is large.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants