Details
-
Improvement
-
Status: Open
-
Minor
-
Resolution: Unresolved
-
3.14.0
-
None
-
Unknown
Description
I work for a cloud service provider that includes an integration application that uses Camel for the core operations of an integration. Because of factors such as industry regulation and customer InfoSec policies/requirements, placing access keys within an application, its filesystem, associated direct data stores, etc. is not permitted. This requires credentials to be provided by a lookup service that provides decrypted values to an application, exposed through variables. While our SaaS offering does provide an identity hub that integrates with customer IdPs, these integration applications will not use those as credential stores, directly.
With that, the serviceAccountKey would need to be provided via a variable, environment variable, etc., where the JSON string would be passed into that field value.
I've made a modification to allow for this by modifying the getCredentialsProvider method of the GooglePubsubCompenent.java file of the camel-google-pubsub component. This would respond to a prefix and then take the value from the passed parameter and use it for the credentials.
private CredentialsProvider getCredentialsProvider(GooglePubsubEndpoint endpoint) throws IOException { CredentialsProvider credentialsProvider; // The original method logic // if (endpoint.isAuthenticate()) { // credentialsProvider = FixedCredentialsProvider.create(ObjectHelper.isEmpty(endpoint.getServiceAccountKey()) // ? GoogleCredentials.getApplicationDefault() : ServiceAccountCredentials.fromStream(ResourceHelper // .resolveMandatoryResourceAsInputStream(getCamelContext(), endpoint.getServiceAccountKey()))); // } else { // credentialsProvider = NoCredentialsProvider.create(); // } // Modified for JSON input if (endpoint.isAuthenticate()) { if (ObjectHelper.isEmpty(endpoint.getServiceAccountKey())) { credentialsProvider = FixedCredentialsProvider.create(GoogleCredentials.getApplicationDefault()); } else if (endpoint.getServiceAccountKey().startsWith("json:")) { // <- For the JSON string credentialsProvider = FixedCredentialsProvider.create(ServiceAccountCredentials.fromStream( new ByteArrayInputStream(Base64.getUrlDecoder().decode(endpoint.getServiceAccountKey().substring(5))))); } else { credentialsProvider = FixedCredentialsProvider.create(ServiceAccountCredentials.fromStream( ResourceHelper.resolveResourceAsInputStream(getCamelContext(), endpoint.getServiceAccountKey()))); } } else { credentialsProvider = NoCredentialsProvider.create(); } return credentialsProvider; }
This would then allows for the component to be defined with the serviceAccountKey as below. The JSON string would need to be encoded via Base64 to allow the internal encoded key to be properly passed through.
@Override public void configure() throws Exception { from("direct:gcpTest").id("gcpTest") .setHeader(GooglePubsubConstants.ATTRIBUTES, constant(Map.of("testKey1", "testValue1", "testKey2", "testValue2"))) .setBody(simple("{\"someKey\": \"someValue\"}")) .toD("google-pubsub:{{PROJECT_NAME}}:{{TOPIC_NAME}}?serviceAccountKey=json:{{BASE64_CREDS}}") .log("Message ID: ${header." + GooglePubsubConstants.MESSAGE_ID + "}"); }
I understand the concern around using an environment variable to pass credentials to a container. There is, however, a common pattern of cloud providers that expose external configuration to containers through environment variables.