Java callouts limitations. Difference between Cloud customers and Private Cloud customers.

Not applicable

I'm working on a java callout for XML encrypt-decrypt, so I need access to public and private keys. I found limitations on java callouts, like not access to the keystore, for security reasons. I was wondering if that limitation is just for Cloud customers.

If the limitations are the same, which is the best way to store and get a private key? The best solution I found so far is create a keystore file, with the key, and then embed it as a jar, then upload the jar as a resource. Is there any other option? Can I save a private key in a Vault? (and if I can, can I access in java? I found just one example in Node.js)

Solved Solved
4 7 475
1 ACCEPTED SOLUTION

Hi Ivan - We're aware of the limitation you describe, and are looking at removing it. That won't happen for a while, though.

In the meantime, you can store your keys or secrets in the Vault. To do so, you'd need to:

  • serialize the key in PEM format
  • upload it to the vault
  • use nodejs to retrieve the secret from the vault
  • in your Java code, instantiate a Key or SecretKey from the PEM-encoded string
  • proceed as normal

In general the Vault is the way to store secrets in Apigee Edge. Unfortunately the Vault is not directly accessible from a Java callout.

If you don't mind embedding the key as a resource in the JAR that you upload - in other words if your uploaded JAR can be viewed as "secret enough", then just serialize the key as PEM and embed the PEM as a resource, and use getResourceAsStream() to read the PEM string.

like this;

    private static InputStream getResourceAsStream(String resourceName)
      throws IOException {
        // forcibly prepend a slash
        if (!resourceName.startsWith("/")) {
            resourceName = "/" + resourceName;
        }
        if (!resourceName.startsWith("/resources")) {
            resourceName = "/resources" + resourceName;
        }
        InputStream in = MyCalloutClassName.class.getResourceAsStream(resourceName);
        if (in == null) {
            throw new IOException("resource \"" + resourceName + "\" not found");
        }
        return in;
    }

@Mukundha Madhavan and @Joel D'sa - you may wish to be aware.

View solution in original post

7 REPLIES 7

Hi Ivan - We're aware of the limitation you describe, and are looking at removing it. That won't happen for a while, though.

In the meantime, you can store your keys or secrets in the Vault. To do so, you'd need to:

  • serialize the key in PEM format
  • upload it to the vault
  • use nodejs to retrieve the secret from the vault
  • in your Java code, instantiate a Key or SecretKey from the PEM-encoded string
  • proceed as normal

In general the Vault is the way to store secrets in Apigee Edge. Unfortunately the Vault is not directly accessible from a Java callout.

If you don't mind embedding the key as a resource in the JAR that you upload - in other words if your uploaded JAR can be viewed as "secret enough", then just serialize the key as PEM and embed the PEM as a resource, and use getResourceAsStream() to read the PEM string.

like this;

    private static InputStream getResourceAsStream(String resourceName)
      throws IOException {
        // forcibly prepend a slash
        if (!resourceName.startsWith("/")) {
            resourceName = "/" + resourceName;
        }
        if (!resourceName.startsWith("/resources")) {
            resourceName = "/resources" + resourceName;
        }
        InputStream in = MyCalloutClassName.class.getResourceAsStream(resourceName);
        if (in == null) {
            throw new IOException("resource \"" + resourceName + "\" not found");
        }
        return in;
    }

@Mukundha Madhavan and @Joel D'sa - you may wish to be aware.

Thanks for replying Dino, I'll try the Vault solution, it seems to be more secure.

Hi Dino, I was trying your first solution, but I'm stuck at point 4 (in your Java code, instantiate a Key or SecretKey from the PEM-encoded string), everything was ok until that, I used nodejs to retrieve the secret from the vault, but node.js is the target end point, so, how can I get the secret value (retrieved in node) in my java callout?

Thanks in advance

Hi Ivan - yes in the case that you are retrieving the secret from within nodejs, then you need the Java callout to run AFTER the nodejs target. Which means it must be in the response flow, either on the target endpoint or in the proxy endpoint.

Does this make sense?

I'm not sure, what I need to do is: get the xml encrypted from the request, decrypt it with the private key, and then send the xml decrypted to the backend service, so I'm not sure if the response flow is the place for the decryption. Or at least I don't know how to continue the flow to the backend service with the xml decrypted in the request

adas
New Member

@Ivan Beerli Vault is only accessible via nodejs at the moment. We are going to add a new policy to access vault data so it should be available to Java and other custom policies. But that feature is still in design/development phase and not available yet.

Thanks Arghya, looking forward for that policy 🙂