Get hands-on experience with 20+ free Google Cloud products and $300 in free credit for new customers.

Dynamically change TargetServer

I have a Use Case in which an API proxy can route to one of potentially hundreds of backend servers, depending on the client app.

These backend servers will all need to be secured using mutual TLS, and therefore will be set up as named Target Servers in Apigee. There's a KVM which maps the client app ID to a named Target Server.

I want to be able to dynamically change the Target Server at run time:

 

<TargetEndpoint name="default">
    <PreFlow name="PreFlow">
     <Step>
         <Name>KV-GetTargetServer</Name>
     </Step>
     <Step>
         <Name>JS-TargetSwap</Name>
     </Step>
     ...

    <HTTPTargetConnection>
        <LoadBalancer>
            <Server name="ReplaceMe"/>
        </LoadBalancer>
    </HTTPTargetConnection>

 

But I can't seem to figure out a way to override the Server name in the LoadBalancer section of the TargetEndpoint programmatically.

Note: I know I can use route rules and create multiple TargetEndpoints, but I don't want to have hundreds (potentially) thousands of Target Endpoints in an API proxy. I'd also like to be able to add new Targets without having to redeploy the proxy.

If this is not possible, then I guess the alternative would be to define the Target URL programmatically, but my question then would be how to add the TLS Keystore reference to the target in order to support mutual TLS?

Solved Solved
1 2 1,673
1 ACCEPTED SOLUTION

I can't seem to figure out a way to override the Server name in the LoadBalancer section of the TargetEndpoint programmatically.

yes, there's a good reason for that! It's not possible !

I guess the alternative would be to define the Target URL programmatically,

Yes, you can do this by setting target.url, at some point in the target request flow.

how to add the TLS Keystore reference to the target in order to support mutual TLS?

The SSLInfo is all dynamic, so you can specify something like this:

 

    <SSLInfo>
        <Enabled>true</Enabled>
        <ClientAuthEnabled>true</ClientAuthEnabled>
        <KeyStore>{variable-containing-keystore-name}</KeyStore>
        <KeyAlias>{variable-containing-key-alias}</KeyAlias>
        <TrustStore>{variable-containing-truststore-name}</TrustStore>
        <IgnoreValidationErrors>false</IgnoreValidationErrors>
    </SSLInfo>

 

The curly braces are important. The variable name goes within the curlies. Here's an older article describing this in more detail.

At the time you set the target.url, you will also want to set the other variables you reference here. The keystores and truststores you reference must exist. You cannot dynamically create those things at runtime. But you can "select them" at runtime.

I don't believe that the Ciphers and Protocols are dynamically selectable. check this doc for the reference on SSLInfo.

But.... you may not NEED to set the keystore and truststore dynamically, if all of your upstream targets use a common root CA, or one of a few common root CAs. This is how web browsers work. They can connect with literally millions of endpoints on the web, and they use a single truststore to do so. That truststore is just loaded with the right set of root CA certificates. You could do the same kind of thing with Apigee. In this case you can vary the target.url without varying the truststore or keystore. This might be simpler.

But either way works. It's up to you.

View solution in original post

2 REPLIES 2

I can't seem to figure out a way to override the Server name in the LoadBalancer section of the TargetEndpoint programmatically.

yes, there's a good reason for that! It's not possible !

I guess the alternative would be to define the Target URL programmatically,

Yes, you can do this by setting target.url, at some point in the target request flow.

how to add the TLS Keystore reference to the target in order to support mutual TLS?

The SSLInfo is all dynamic, so you can specify something like this:

 

    <SSLInfo>
        <Enabled>true</Enabled>
        <ClientAuthEnabled>true</ClientAuthEnabled>
        <KeyStore>{variable-containing-keystore-name}</KeyStore>
        <KeyAlias>{variable-containing-key-alias}</KeyAlias>
        <TrustStore>{variable-containing-truststore-name}</TrustStore>
        <IgnoreValidationErrors>false</IgnoreValidationErrors>
    </SSLInfo>

 

The curly braces are important. The variable name goes within the curlies. Here's an older article describing this in more detail.

At the time you set the target.url, you will also want to set the other variables you reference here. The keystores and truststores you reference must exist. You cannot dynamically create those things at runtime. But you can "select them" at runtime.

I don't believe that the Ciphers and Protocols are dynamically selectable. check this doc for the reference on SSLInfo.

But.... you may not NEED to set the keystore and truststore dynamically, if all of your upstream targets use a common root CA, or one of a few common root CAs. This is how web browsers work. They can connect with literally millions of endpoints on the web, and they use a single truststore to do so. That truststore is just loaded with the right set of root CA certificates. You could do the same kind of thing with Apigee. In this case you can vary the target.url without varying the truststore or keystore. This might be simpler.

But either way works. It's up to you.

Hi John,

I have a similar need. Could you please share your code for the two steps KV-GetTargetServer and JS-TargetSwap?