All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.rt.storage.auth.oauth2.IamUtils Maven / Gradle / Ivy
package com.rt.storage.auth.oauth2;
import com.rt.storage.api.client.http.GenericUrl;
import com.rt.storage.api.client.http.HttpRequest;
import com.rt.storage.api.client.http.HttpResponse;
import com.rt.storage.api.client.http.HttpStatusCodes;
import com.rt.storage.api.client.http.HttpTransport;
import com.rt.storage.api.client.http.json.JsonHttpContent;
import com.rt.storage.api.client.json.GenericJson;
import com.rt.storage.api.client.json.JsonObjectParser;
import com.rt.storage.api.client.util.GenericData;
import com.rt.storage.auth.Credentials;
import com.rt.storage.auth.ServiceAccountSigner;
import com.rt.storage.auth.http.HttpCredentialsAdapter;
import com.google.common.io.BaseEncoding;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
/**
* This internal class provides shared utilities for interacting with the IAM API for common
* features like signing.
*/
class IamUtils {
private static final String SIGN_BLOB_URL_FORMAT =
"https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/%s:signBlob";
private static final String ID_TOKEN_URL_FORMAT =
"https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/%s:generateIdToken";
private static final String PARSE_ERROR_MESSAGE = "Error parsing error message response. ";
private static final String PARSE_ERROR_SIGNATURE = "Error parsing signature response. ";
/**
* Returns a signature for the provided bytes.
*
* @param serviceAccountEmail the email address for the service account used for signing
* @param credentials credentials required for making the IAM call
* @param transport transport used for building the HTTP request
* @param toSign bytes to sign
* @param additionalFields additional fields to send in the IAM call
* @return signed bytes
* @throws ServiceAccountSigner.SigningException if signing fails
*/
static byte[] sign(
String serviceAccountEmail,
Credentials credentials,
HttpTransport transport,
byte[] toSign,
Map additionalFields) {
BaseEncoding base64 = BaseEncoding.base64();
String signature;
try {
signature =
getSignature(
serviceAccountEmail, credentials, transport, base64.encode(toSign), additionalFields);
} catch (IOException ex) {
throw new ServiceAccountSigner.SigningException("Failed to sign the provided bytes", ex);
}
return base64.decode(signature);
}
private static String getSignature(
String serviceAccountEmail,
Credentials credentials,
HttpTransport transport,
String bytes,
Map additionalFields)
throws IOException {
String signBlobUrl = String.format(SIGN_BLOB_URL_FORMAT, serviceAccountEmail);
GenericUrl genericUrl = new GenericUrl(signBlobUrl);
GenericData signRequest = new GenericData();
signRequest.set("payload", bytes);
for (Map.Entry entry : additionalFields.entrySet()) {
signRequest.set(entry.getKey(), entry.getValue());
}
JsonHttpContent signContent = new JsonHttpContent(OAuth2Utils.JSON_FACTORY, signRequest);
HttpCredentialsAdapter adapter = new HttpCredentialsAdapter(credentials);
HttpRequest request =
transport.createRequestFactory(adapter).buildPostRequest(genericUrl, signContent);
JsonObjectParser parser = new JsonObjectParser(OAuth2Utils.JSON_FACTORY);
request.setParser(parser);
request.setThrowExceptionOnExecuteError(false);
HttpResponse response = request.execute();
int statusCode = response.getStatusCode();
if (statusCode >= 400 && statusCode < HttpStatusCodes.STATUS_CODE_SERVER_ERROR) {
GenericData responseError = response.parseAs(GenericData.class);
Map error =
OAuth2Utils.validateMap(responseError, "error", PARSE_ERROR_MESSAGE);
String errorMessage = OAuth2Utils.validateString(error, "message", PARSE_ERROR_MESSAGE);
throw new IOException(
String.format(
"Error code %s trying to sign provided bytes: %s", statusCode, errorMessage));
}
if (statusCode != HttpStatusCodes.STATUS_CODE_OK) {
throw new IOException(
String.format(
"Unexpected Error code %s trying to sign provided bytes: %s",
statusCode, response.parseAsString()));
}
InputStream content = response.getContent();
if (content == null) {
// Throw explicitly here on empty content to avoid NullPointerException from parseAs call.
// Mock transports will have success code with empty content by default.
throw new IOException("Empty content from sign blob server request.");
}
GenericData responseData = response.parseAs(GenericData.class);
return OAuth2Utils.validateString(responseData, "signedBlob", PARSE_ERROR_SIGNATURE);
}
/**
* Returns an IdToken issued to the serviceAccount with a specified targetAudience
*
* @param serviceAccountEmail the email address for the service account to get an ID Token for
* @param credentials credentials required for making the IAM call
* @param transport transport used for building the HTTP request
* @param targetAudience the audience the issued ID token should include
* @param additionalFields additional fields to send in the IAM call
* @return IdToken issed to the serviceAccount
* @throws IOException if the IdToken cannot be issued.
*/
static IdToken getIdToken(
String serviceAccountEmail,
Credentials credentials,
HttpTransport transport,
String targetAudience,
boolean includeEmail,
Map additionalFields)
throws IOException {
String idTokenUrl = String.format(ID_TOKEN_URL_FORMAT, serviceAccountEmail);
GenericUrl genericUrl = new GenericUrl(idTokenUrl);
GenericData idTokenRequest = new GenericData();
idTokenRequest.set("audience", targetAudience);
idTokenRequest.set("includeEmail", includeEmail);
for (Map.Entry entry : additionalFields.entrySet()) {
idTokenRequest.set(entry.getKey(), entry.getValue());
}
JsonHttpContent idTokenContent = new JsonHttpContent(OAuth2Utils.JSON_FACTORY, idTokenRequest);
HttpCredentialsAdapter adapter = new HttpCredentialsAdapter(credentials);
HttpRequest request =
transport.createRequestFactory(adapter).buildPostRequest(genericUrl, idTokenContent);
JsonObjectParser parser = new JsonObjectParser(OAuth2Utils.JSON_FACTORY);
request.setParser(parser);
request.setThrowExceptionOnExecuteError(false);
HttpResponse response = request.execute();
int statusCode = response.getStatusCode();
if (statusCode >= 400 && statusCode < HttpStatusCodes.STATUS_CODE_SERVER_ERROR) {
GenericData responseError = response.parseAs(GenericData.class);
Map error =
OAuth2Utils.validateMap(responseError, "error", PARSE_ERROR_MESSAGE);
String errorMessage = OAuth2Utils.validateString(error, "message", PARSE_ERROR_MESSAGE);
throw new IOException(
String.format("Error code %s trying to getIDToken: %s", statusCode, errorMessage));
}
if (statusCode != HttpStatusCodes.STATUS_CODE_OK) {
throw new IOException(
String.format(
"Unexpected Error code %s trying to getIDToken: %s",
statusCode, response.parseAsString()));
}
InputStream content = response.getContent();
if (content == null) {
// Throw explicitly here on empty content to avoid NullPointerException from
// parseAs call.
// Mock transports will have success code with empty content by default.
throw new IOException("Empty content from generateIDToken server request.");
}
GenericJson responseData = response.parseAs(GenericJson.class);
String rawToken = OAuth2Utils.validateString(responseData, "token", PARSE_ERROR_MESSAGE);
return IdToken.create(rawToken);
}
}