The deployments definition deployments.json is invalid

I’m new to Apigee X and testing it to see if it fits our needs.

I’ve set up an Apigee X archive.

When I’m running the following command:

$ gcloud beta apigee archives deploy --environment=test

I get the following error:

ERROR: (gcloud.beta.apigee.archives.deploy) Failed to create archive deployment (Bad Request):

ArchiveDeployment(organization='xxxxxxx', environment='test')

Details: The deployments definition src/main/apigee/environments/test/deployments.json is invalid.

json: unknown field "serviceAccount"

It’s deploying fine on the emulator v1.15.2 but fails on Google Cloud.

The deployments.json file structure follows the documentation here: Configurer et déployer des environnements  |  Apigee  |  Google Cloud Documentation

The file looks like :

{

  "proxies": [
    {
      "name": "graphql"
    },
    {
      "name": "graphql-passthrough"
    },
    {
      "name": "rest"
    }
  ],
  "sharedflows": [
    {
      "name": "sf-common-gcloud-logging",
      "serviceAccount": "(PII Removed by Staff)"
    }
    {
      "name": "sf-common-security"
    }
  ]
}

I don’t understand why the json schema get validated by the emulator 1.15.2 but not when deploying on the Apigee environment. I can’t neither find further documentation about the expected json structure expected by the Apigee environment.

2 Likes

Hey @bonepain, welcome to the Apigee community :smiley: we’ve noticed your question hasn’t been answered yet, but we’ll keep it on our radar and reach out to others in the community to chime in.

You are invited to join our Community Tech Talk this Thursday, March 19 :right_arrow: Mobile Device Flow implementation for Apigee X/Hybrid.

We’ll be doing a deep dive into the RFC 8628 Device Authorization Grant (Mobile Device Flow for Apigee X/Hybrid). It’s a great chance to see the platform in action.

Register Today!

1 Like

You’re likely hitting two different issues here.

First, the Google doc you followed is for Apigee local development / VS Code + emulator. That page explicitly documents deployments.json for local environments, and it shows that serviceAccount can be attached to a proxy or shared flow in that file. It even notes that this feature requires emulator 1.9.2+.

Second, your target environment is an Apigee X archive-deployment environment, and those behave differently. Google’s archive-deployment docs say that when an environment is enabled for archive deployment, Apigee blocks a subset of management actions in that environment, including managing API proxy or shared flow revision deployments through the normal UI/API/gcloud paths. The shared flows page also says that in archive-enabled environments, shared flows can’t be managed through the Apigee UI, API, or gcloud the usual way.

So the most likely explanation is:

  • The emulator accepts a local-development extension of deployments.json

  • The server-side validator for Apigee X archive deployment does not accept serviceAccount in deployments.json

  • That is why you see: json: unknown field “serviceAccount” on Google Cloud, even though it works locally.

There is also a plain JSON syntax error in the sample you pasted: you are missing a comma between the two shared flow entries.

Your pasted block has:

{
  "sharedflows": [
    {
      "name": "sf-common-gcloud-logging",
      "serviceAccount": "(PII Removed by Staff)"
    }
    {
      "name": "sf-common-security"
    }
  ]
}

It must be:

{
  "sharedflows": [
    {
      "name": "sf-common-gcloud-logging",
      "serviceAccount": "(PII Removed by Staff)"
    },
    {
      "name": "sf-common-security"
    }
  ]
}

That missing comma is real, but it is not the reason for the specific unknown field “serviceAccount” error. That error points to schema validation, not just malformed JSON.

What to do next:

  1. Remove serviceAccount from deployments.json for archive deployment and try again.

  2. Keep the file to the archive-deployment-safe shape, for example:

{
  "proxies": [
    { "name": "graphql" },
    { "name": "graphql-passthrough" },
    { "name": "rest" }
  ],
  "sharedflows": [
    { "name": "sf-common-gcloud-logging" },
    { "name": "sf-common-security" }
  ]
}
  1. If you need Google auth from policies, configure it in the proxy/shared-flow implementation using the supported Apigee runtime auth mechanism, rather than expecting archive deployment to bind a service account through deployments.json. The local-development doc’s serviceAccount support appears to be an emulator/VS Code feature, not something the archive deployment backend currently honors.

So the core answer is: the emulator and Apigee X archive deployment are not validating against the same schema here. The doc page you used is describing local-development behavior, and Google Cloud archive deployment is rejecting that extra field.

A practical rule for now: for archive deployments to Apigee X, treat deployments.json as containing only the deployable artifact list (proxies, sharedflows) and not runtime binding metadata like serviceAccount.

2 Likes

It appears that the gcloud apigee archives deploy command does not allow for assigning a dedicated service account to a specific proxy or shared flow.

Therefore, to enable desired functionality (e.g., logging), the service account used for the archive deployment would necessarily require broad permissions, such as the Log Writer role, which would then be accessible to all other proxies and shared flows.

Is this understanding correct?

2 Likes

Yes — your understanding is directionally correct, but it’s worth clarifying the identity model more precisely.

Apigee X archive deployments do not support assigning a per-proxy or per-shared-flow serviceAccount via deployments.json. While this field is accepted by the local emulator (as part of the VS Code/local development workflow), it is not recognized by the archive deployment API, which enforces a different schema.

As a result, archive deployments do not provide a documented mechanism for per-artifact identity binding. This means you cannot achieve fine-grained, least-privilege IAM separation at the proxy or shared flow level through deployments.json.

For Google-authenticated operations (e.g., Cloud Logging), this implies that a shared runtime identity must be used. Consequently, roles such as roles/logging.logWriter would be effectively available to all proxies and shared flows deployed within that archive context.

One important distinction: this does not imply that the identity used to execute gcloud apigee archives deploy becomes the runtime identity. Deployment-time credentials and runtime execution identity are separate concerns. The limitation is specifically the absence of a per-proxy service account binding mechanism in the archive deployment model.

If there is an alternative archive-specific approach to associate distinct service accounts with individual proxies or shared flows, that would be valuable to confirm, as it would enable proper least-privilege design in archive-based deployments.

2 Likes

Thank you very much.

Your clear and valuable explanations have been very helpful; I now have a much better understanding of how it works.

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.