Access GCP Secret Manager from Apigee

Hi everyone,

I'm just wondering how I can retrieve a secret value from GCP Secret Manager using existing policies (not third parties).

We'd like to get the secret and issue a JWT token.

Thanks.

1 2 1,180
2 REPLIES 2

Hi @rezak 

Currently there are no policies to retrieve from Secret Manager. Your best bet is to use the Secret Manager API. You can use GoogleAuthentication in the Apigee proxy to make the API call.

yep, so in a ServiceCallout, this would look something like so:  

 

<ServiceCallout name='SC-Access-Secret'>
  <Request variable='secretAccessRequest'>
    <Set>
      <Verb>GET</Verb>
      <!-- Path is a Message Template -->
      <Path>/v1/projects/{gcp-project-with-secret}/secrets/{secret-name}/versions/{secret-version}:access</Path>
    </Set>
  </Request>

  <Response>secretResponse</Response>

  <HTTPTargetConnection>

    <!-- this will use the Service Account you specified at deployment time -->
    <Authentication>
      <GoogleAccessToken>
        <Scopes>
          <Scope>https://www.googleapis.com/auth/cloud-platform</Scope>
        </Scopes>
      </GoogleAccessToken>
    </Authentication>

    <SSLInfo>
      <Enabled>true</Enabled>
      <IgnoreValidationErrors>false</IgnoreValidationErrors>
    </SSLInfo>
    <Properties>
      <Property name='success.codes'>2xx</Property>
    </Properties>
    <URL>https://secretmanager.googleapis.com</URL>
  </HTTPTargetConnection>
</ServiceCallout>

 

And you would need to set these variables prior to that serviceCallout in order for the path to resolve properly: 

  • gcp-project-with-secret
  • secret-name
  • secret-version

Of course you could read those things from a properties file implicitly, if you are using X or hybrid. 

Because this ServiceCallout is using the Authentication/GoogleAccessToken configuration, to get this to work, you will need to deploy the API proxy with a service account, that has "Secret Manager Secret Accessor" role in the project in which the secret is stored. 

And then what you receive in the secretResponse content is a JSON payload, which is of this form: 

 

{
  "name": "projects/28957237831/secrets/secret-name/versions/1",
  "payload": {
    "data": "aS1sb3ZlLWFwaXM=",
    "dataCrc32c": "4263821604"
  }
}

 

The values shown there are just examples - yours will be different of course. That data member is the base64 encoded blob that you loaded in, as a secret to begin with, and it might be quite large. You may want to decode that thing to get... oh, maybe an RSA Private key, or the password for an encrypted privatekey.  To do that you can use AssignMessage like this: 

 

<AssignMessage name='AM-Decode-Secret'>
  <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>

  <AssignVariable>
    <Name>jsonpath1</Name>
    <Value>$.payload.data</Value>
  </AssignVariable>
  <AssignVariable>
    <Name>retrieved-secret</Name>
    <Template>{jsonPath(jsonpath1,secretResponse.content)}</Template>
  </AssignVariable>
  <AssignVariable>
    <Name>retrieved-secret-decoded</Name>
    <Template>{decodeBase64(retrieved-secret)}</Template>
  </AssignVariable>
</AssignMessage>

 

And at that point you could use the decoded thing as a private key or a password or whatever.  I think the GenerateJWT policy requires the private key, or the private key password, to be in a variable that uses the private. prefix, so you'd need to modify that AssignMessage policy accordingly.