Skip to main content

Configuration reference

This page documents every configuration option available in the VAMS deployment configuration file located at infra/config/config.json. Options are organized by functional area. For deployment instructions, see Deploy the solution.

Configuration resolution order

Configuration values are resolved using a fallback chain: CDK context parameters (-c key=value) take highest priority, followed by values in config.json, then environment variables, and finally hardcoded defaults.

Top-level settings

FieldTypeDefaultDescription
namestringvamsBase application name used in the full CDK stack name.

Environment (env)

FieldTypeDefaultDescription
env.accountstringnullAWS account ID for CDK deployment. If null, pulled from CDK_DEFAULT_ACCOUNT environment variable.
env.regionstringus-east-1AWS Region for CDK deployment. If null, pulled from CDK_DEFAULT_REGION, REGION, or defaults to us-east-1.
env.loadContextIgnoreVPCStacksbooleanfalseWhen true, skips synthesis and deployment of VPC-dependent nested stacks. Used during the first phase of an external VPC import. See Deploy the solution.
Partition auto-detection

The env.partition field is automatically derived from the Region and should not be set manually. VAMS supports the aws, aws-us-gov, aws-eusc (AWS European Sovereign Cloud), aws-cn, and aws-iso* partitions. The aws-us-gov, aws-eusc, and ISO partitions additionally require app.govCloud.enabled to be true — see GovCloud (app.govCloud) and AWS European Sovereign Cloud deployment.

Stack identification (app)

FieldTypeDefaultDescription
app.baseStackNamestringprodStack environment name appended to resource names. Combined with the Region to form the full CloudFormation stack name (for example, vams-core-prod-us-east-1). Can be overridden with the STACK_NAME environment variable or CDK context stack-name.
app.adminUserIdstringadministratorUsername for the initial super administrator account. Can be an email address. Can be overridden with the ADMIN_USER_ID environment variable. Immutable after the first deployment — changing it replaces the Cognito user, which either fails the deployment or leaves the previous administrator behind as an unmanaged account. Synthesis rejects a username Amazon Cognito would refuse. See Update the solution.
app.adminEmailAddressstring(required)Email address for the initial admin account. A temporary password is sent to this address during first deployment. Can be overridden with the ADMIN_EMAIL_ADDRESS environment variable. Immutable after the first deployment for the same reason as adminUserId.

Asset buckets (app.assetBuckets)

Controls how Amazon S3 asset storage buckets are provisioned.

Implemented by

Nested stack: infra/lib/nestedStacks/storage/storageBuilder-nestedStack.ts (StorageResourcesBuilderNestedStack) — Amazon S3 asset buckets plus a DynamoDB bucket registry populated by the custom resource customResources/populateS3AssetBucketsTable.ts.

FieldTypeDefaultDescription
app.assetBuckets.createNewBucketbooleantrueWhen true, VAMS creates a new Amazon S3 bucket for asset storage. When false, you must define at least one external asset bucket.
app.assetBuckets.defaultNewBucketSyncDatabaseIdstringdefaultDatabase ID to synchronize with the newly created bucket. Required when createNewBucket is true.
app.assetBuckets.externalAssetBucketsarraynullArray of external Amazon S3 bucket configurations to register with VAMS. Each bucket requires the fields described below.
app.assetBuckets.presignedUrlNetworkRestrictionsobject{allowedIpRanges: [], allowedVpceIds: []}Optional network restrictions on presigned URLs for the VAMS-created asset bucket and the auxiliary bucket. Uses a bucket policy deny statement that applies only to presigned (query-string authenticated) requests; backend operations unaffected. See the restriction object below.

External asset bucket object

Each element in externalAssetBuckets has the following fields:

FieldTypeDescription
bucketArnstringAmazon Resource Name (ARN) of the existing Amazon S3 bucket. Must use the same partition as the deployment. May be repeated to register the bucket under multiple non-overlapping prefixes.
baseAssetsPrefixstringBase prefix to use for cataloging and syncing assets. Use / for the bucket root. Must end with /.
defaultSyncDatabaseIdstringDatabase ID to associate with asset changes synced from this bucket. If the database does not exist, VAMS creates it.
isDefaultbooleanOptional. Marks this bucket as the VAMS default asset bucket, which holds all pipeline template bodies and execution run I/O (manifests, config, auxiliary output) under the pipelines/ prefix. At most one entry may set isDefault to true. When createNewBucket is false, exactly one entry must set it to true; when createNewBucket is true, an entry that sets it to true overrides the created bucket as the default.
bucketAccountIdstringOptional. The 12-digit AWS account ID that owns the bucket. Set for cross-account buckets so VAMS imports them as cross-account and scopes notification source policies.
bucketRegionstringOptional. The AWS Region of the bucket. Defaults to the deployment Region when omitted.
bucketKmsKeyArnstringOptional. ARN of the AWS KMS key the bucket is encrypted with. When set, VAMS grants this key to its Lambda and pipeline roles. Required if the bucket uses SSE-KMS.

Presigned URL restriction object

Optional network restrictions on presigned URL access. Used in app.assetBuckets.presignedUrlNetworkRestrictions for the created asset bucket and auxiliary bucket.

FieldTypeDefaultDescription
allowedIpRangesarray[]Array of IPv4 and IPv6 CIDR blocks (e.g., ["192.168.1.0/24", "2001:db8::/32"]) permitted to use presigned URLs. Empty array means no IP restrictions. Mutually exclusive with allowedVpceIds.
allowedVpceIdsarray[]Array of Amazon S3 VPC endpoint IDs (e.g., ["vpce-1234abcd"]) permitted to use presigned URLs. Accepts both interface and gateway VPC endpoint IDs. Empty array means no VPC endpoint restrictions. Mutually exclusive with allowedIpRanges.

Example configuration with restrictions:

{
"app": {
"assetBuckets": {
"createNewBucket": true,
"defaultNewBucketSyncDatabaseId": "default",
"presignedUrlNetworkRestrictions": {
"allowedIpRanges": ["203.0.113.0/24"],
"allowedVpceIds": []
},
"externalAssetBuckets": null
}
}
}

Restrict on one network dimension per deployment: configuration validation rejects setting both allowedIpRanges and allowedVpceIds (a request arrives either over the public path, evaluated against aws:SourceIp, or through a VPC endpoint, evaluated against aws:SourceVpce). Restrictions are enforced at URL use time through bucket policy deny statements. Restriction changes applied through a redeployment take effect immediately for both newly issued URLs and previously issued URLs that have not yet expired.

Adding external buckets

External buckets can be added incrementally across deployments. Each bucket requires additional IAM bucket policies. A bucket ARN may be registered more than once to map multiple databases to non-overlapping prefixes within it. See External Amazon S3 bucket setup for the full bucket policy, KMS, cross-account requirements, and (if desired) how to restrict presigned URLs on external buckets.

Security and compliance

WAF and FIPS (app)

FieldTypeDefaultDescription
app.useWafbooleantrueEnables AWS WAF. Always protects the Amazon API Gateway API and, when present, the Amazon CloudFront distribution or Application Load Balancer. Disabling this generates a deployment warning.
app.useFipsbooleanfalseEnables FIPS-compliant AWS partition endpoints. Must be combined with the AWS_USE_FIPS_ENDPOINT=true environment variable.
app.addStackCloudTrailLogsbooleantrueCreates a dedicated Amazon CloudWatch Logs group and associated AWS CloudTrail trail for this stack.
Implemented by

These three keys do not map to a single nested stack:

  • app.useWaf — standalone WAF stack(s) infra/lib/cf-waf-stack.ts (CfWafStack), gated in infra/bin/infra.ts. The regional web ACL attaches to the API Gateway stage in apiLambda/constructs/rest-api-gateway-construct.ts and to the ALB in staticWebApp/staticWebBuilder-nestedStack.ts; the CloudFront web ACL attaches to the distribution in staticWebApp/constructs/cloudfront-s3-website-construct.ts.
  • app.useFips — global endpoint resolution in infra/lib/helper/service-helper.ts (no stack of its own).
  • app.addStackCloudTrailLogs — created inline in the root stack infra/lib/core-stack.ts (CoreVAMSStack). :::

How many web ACLs are created

When app.useWaf is enabled, VAMS always creates a regional-scoped web ACL in the deployment Region and associates it with the API Gateway API stage — for both REGIONAL and PRIVATE endpoint types, and regardless of whether a CloudFront distribution or ALB fronts the application. This protects the API's execute-api endpoint, which remains directly reachable in every fronting configuration.

The number of web ACLs depends on the front-end distribution:

Front-end (app.useCloudFront / app.useAlb)Web ACLs createdAttached to
CloudFront enabled2 — a regional ACL (deployment Region) and a CloudFront ACL (us-east-1)API Gateway stage; CloudFront distribution
ALB enabled1 — a regional ACL (deployment Region)API Gateway stage; ALB
Neither1 — a regional ACL (deployment Region)API Gateway stage

AWS WAF scopes are not interchangeable, so a CloudFront deployment requires two web ACLs. A web ACL associated with a CloudFront distribution is CLOUDFRONT-scoped, lives in us-east-1, and — per AWS WAF — cannot be associated with any other resource type. API Gateway and ALB require a REGIONAL-scoped web ACL in the deployment Region. This holds even when the deployment Region is us-east-1: the CloudFront ACL and the regional ACL are different scopes, so a single ACL cannot cover both the distribution and the API Gateway. Both web ACLs are built from the same wafPolicyConfig.json policy, so their rule sets are identical.

The two web ACLs are created as separate CloudFormation stacks. The regional stack is named {name}-waf-{baseStackName} when CloudFront is disabled, or {name}-waf-regional-{baseStackName} when CloudFront is enabled; the CloudFront stack (when present) is named {name}-waf-{baseStackName} and deployed to us-east-1.

WAF rule policy (config/policy/wafPolicyConfig.json)

When app.useWaf is enabled, the rules attached to the web ACL(s) are defined by the file infra/config/policy/wafPolicyConfig.json. This keeps the firewall posture in a dedicated policy file, separate from the main config.json, alongside the S3 bucket-policy and IAM-role customization files. The same policy file is applied to both the regional and CloudFront web ACLs.

The file has two sections:

SectionPurpose
managedRuleGroupsAWS or third-party managed rule groups to attach. Each entry sets name, vendorName, managedRuleGroupName, priority, and block (true applies the group's own block actions; false runs the group in count-only mode). An optional ruleActionOverrides array changes individual rules inside the group without disabling the whole group: each override sets name (a rule within the group, for example SizeRestrictions_BODY) and action (count, allow, or block). This runs a single rule in count mode while every other rule in the group still blocks.
rateBasedRulesRate-based rules for L7 DDoS and brute-force throttling. Each entry sets name, priority, and limit (requests per 5-minute window per source IP address), and may set blockResponseCode (default 429). Every rule is applied per connection IP address.

The shipped file applies the AWS Common Rule Set, Known Bad Inputs, and Amazon IP Reputation List in block mode, plus a rate-based rule limiting each client to 10,000 requests per 5-minute window. Within the AWS Common Rule Set, two rules are overridden to count (through ruleActionOverrides) while every other rule continues to block:

  • SizeRestrictions_BODY — so that large request bodies, such as the multi-part upload initialize and complete requests up to the Amazon API Gateway REST API maximum payload of 10 MB, are observed rather than blocked. This is the only Common Rule Set rule that acts on body size alone; the remaining body-inspecting rules match on attack signatures, not size, so leaving them in block mode does not affect large payloads.
  • SizeRestrictions_QUERYSTRING — so that requests with a long query string are observed rather than blocked. The rule blocks any query string over 2048 bytes. The SuperSplat viewer loads a file by passing a presigned Amazon S3 URL in a ?load= parameter, and a presigned URL that carries a session security token exceeds that threshold, so the request for the viewer page is rejected with an HTTP 403 before the file is ever fetched. The web ACL default action remains allow, so only requests matching a rule are blocked or counted.

The rate-based rule aggregates on the IP address AWS WAF observes on the connection, and the same policy applies to both the CloudFront-scoped and regional web ACLs. An X-Forwarded-For aggregation key is accepted in the policy file for compatibility but is not applied, because the value is supplied by the caller — a client can rotate it to evade the limit — and AWS WAF omits any request that does not carry the header from the rule's evaluation. Where VAMS is fronted by Amazon CloudFront or an Application Load Balancer, or reached through a shared NAT gateway or VPN egress address, requests from behind that address share a counter, so set the limit with that in mind. VAMS is chatty per active user (the executions board polls for live status, uploads issue multi-part requests, and viewers stream large files), so the limit is set well above a single user's normal request rate while still stopping request floods. When the rule blocks, it returns HTTP 429 Too Many Requests with a small JSON body — the correct throttle status, distinct from the 403 returned for an authorization denial — so clients can recognize throttling and retry. The VAMS web application and the VAMS CLI both treat a 429 as a transient, retryable condition: they honor the Retry-After header and retry with backoff rather than surfacing it as an authentication or permission failure.

If the file is empty or absent, VAMS applies its baseline rule set: a single AWS Common Rule Set in count-only mode. Populate the file to enable enforced protection.

Validate before enabling block mode

Managed rule groups can match legitimate traffic (for example, large multipart uploads or presigned-URL flows). Set a rule group's block to false to observe its matches in Amazon CloudWatch first, then switch to true once you confirm normal VAMS traffic is not caught, adding scoped rule exclusions for any false positives. When only a single rule is the source of false positives, prefer a ruleActionOverrides entry that sets that rule's action to count over dropping the whole group to count mode — this is how the shipped policy handles SizeRestrictions_BODY, allowing multi-part upload bodies up to the Amazon API Gateway REST 10 MB limit while the rest of the Common Rule Set keeps blocking.

KMS encryption (app.useKmsCmkEncryption)

Implemented by

Nested stack: infra/lib/nestedStacks/storage/storageBuilder-nestedStack.ts (StorageResourcesBuilderNestedStack) — provisions (or imports) the AWS KMS CMK and applies it to all Amazon S3, DynamoDB, SQS, SNS, and OpenSearch resources.

FieldTypeDefaultDescription
app.useKmsCmkEncryption.enabledbooleanfalseEnables a customer-managed AWS KMS key for encryption at rest. The key is auto-generated and applied to Amazon S3, Amazon DynamoDB, Amazon SQS, Amazon SNS, and Amazon OpenSearch Service.
app.useKmsCmkEncryption.optionalExternalCmkArnstringnullARN of an existing customer-managed KMS key to import instead of generating a new one. The key must be in the same Region as the deployment.
External CMK key policy

When importing an external KMS key, the key policy must grant the following actions to the relevant service principals (Amazon S3, Amazon DynamoDB, AWS STS, Amazon SQS, Amazon SNS, Amazon ECS, Amazon EKS, Amazon CloudWatch Logs, AWS Lambda, Amazon CloudFront, Amazon OpenSearch Service):

kms:GenerateDataKey*
kms:Decrypt
kms:ReEncrypt*
kms:DescribeKey
kms:ListKeys
kms:CreateGrant

GovCloud (app.govCloud)

Implemented by

GovCloud is a cross-cutting switch, not a dedicated nested stack. It is validated in getConfig() (infra/config/config.ts) and applied as feature flags and partition selection in the root stack infra/lib/core-stack.ts (CoreVAMSStack), which in turn constrains the VPC, web distribution, and Location Service stacks.

FieldTypeDefaultDescription
app.govCloud.enabledbooleanfalseEnables restricted-partition deployment mode. Enforces: VPC must be enabled, Amazon CloudFront must be disabled, Amazon Location Service must be disabled, and AWS Deadline Cloud must be disabled. Required to be true when the deployment Region belongs to the AWS GovCloud (aws-us-gov), AWS European Sovereign Cloud (aws-eusc), or an ISO (aws-iso*) partition; configuration validation rejects the deployment otherwise. The flag also gates the resource-level adjustments those partitions require, such as removing tags from Amazon EventBridge event source mappings, so leaving it false produces resources the partition rejects during stack creation.
app.govCloud.il6CompliantbooleanfalseApplies the additional DoD Impact Level 6 control set: Amazon Cognito must be disabled (app.authProvider.useCognito.enabled = false), AWS WAF must be disabled (app.useWaf = false), and customer managed KMS encryption must be enabled (app.useKmsCmkEncryption.enabled = true). Required to be true when the deployment Region belongs to an ISO (aws-iso*) partition. Optional in the AWS GovCloud and AWS European Sovereign Cloud partitions.

Restricted-partition constraints

Configuration validation enforces the following when app.govCloud.enabled is true, or when the deployment Region resolves to a partition other than aws. This is the complete set; a configuration that violates any of them is rejected before synthesis with an error naming the field.

ConstraintSetting requiredReason
VPC requiredapp.useGlobalVpc.enabled: trueThe partitions place VAMS resources inside a VPC.
No Amazon CloudFrontapp.useCloudFront.enabled: falseAmazon CloudFront is not offered. Use the ALB web deployment (app.useAlb).
No Amazon Location Serviceapp.useLocationService.enabled: falseAmazon Location Service is not offered, so map features are unavailable.
No AWS Deadline Cloudapp.pipelines.deadlineCloudExecutionTypeEnabled: falseAWS Deadline Cloud is offered only in the commercial aws partition.
No Amazon Cognito SAML or OIDC federationapp.authProvider.useCognito.useSaml: false and useOidc: falseBoth use the Amazon Cognito hosted UI, which is unavailable. Use app.authProvider.useExternalOAuthIdp for federated sign-in.
No next-generation OpenSearch Serverlessapp.openSearch.useServerless.nextGen: falseNext-generation Serverless collection groups are unavailable.
No OpenSearch Serverless in the European Sovereign Cloudapp.openSearch.useServerless.enabled: false (use app.openSearch.useProvisioned)Amazon OpenSearch Serverless has no endpoint in the aws-eusc partition. Applies to aws-eusc only; AWS GovCloud supports Serverless.

Amazon Cognito advanced security (AdvancedSecurityMode) is also unavailable in these partitions. VAMS does not configure it and suppresses the corresponding CDK Nag check automatically, so it needs no configuration change.

AWS European Sovereign Cloud

For now, also set app.govCloud.enabled = true when deploying to the AWS European Sovereign Cloud (Region eusc-de-east-1). The European Sovereign Cloud is a separate, isolated partition (aws-eusc) with the same constraints that the GovCloud mode already enforces — VPC required, no Amazon CloudFront (use the ALB web deployment), and no Amazon Location Service — so the existing GovCloud guardrails apply. A dedicated EU Sovereign Cloud deployment mode may be introduced in a future release; until then, the GovCloud flag is the supported way to enable these constraints, and the config.template.eusovereign.json template sets it accordingly.

IAM role customization (app.iamRoleConfig)

These options support environments that restrict or centrally manage AWS Identity and Access Management (IAM) role creation. Both default to false, and when both are false VAMS manages all IAM roles itself (the recommended default). Each flag toggles whether VAMS reads its corresponding mappings from the separate infra/config/policy/iamRoleConfig.json file, keeping the long role ARNs and construct-path maps out of the main configuration.

FieldTypeDefaultDescription
app.iamRoleConfig.useCustomBootstrapRolesbooleanfalseWhen true, VAMS configures the CDK stack synthesizer from the bootstrap section of iamRoleConfig.json to use pre-created CDK bootstrap roles (or no bootstrap roles at all).
app.iamRoleConfig.useCustomVamsStackRolesbooleanfalseWhen true, VAMS applies iam.Role.customizeRoles using the vamsStacks section of iamRoleConfig.json to generate an IAM policy report and/or substitute pre-created application roles.
Advanced configuration

Letting VAMS manage IAM roles is the recommended default — grants stay automatically in sync with the resources they protect. Use these options only in environments where IAM role creation is centralized or restricted. See Advanced IAM role customization for the full workflow, the structure of iamRoleConfig.json, and how the settings apply across the VAMS WAF stack, core stack, and nested stacks.

VPC (app.useGlobalVpc)

Implemented by

Nested stack: infra/lib/nestedStacks/vpc/vpcBuilder-nestedStack.ts (VPCBuilderNestedStack) — Amazon VPC, subnets, VPC interface/gateway endpoints, and the shared security group.

FieldTypeDefaultDescription
app.useGlobalVpc.enabledbooleanfalseCreates or imports a VPC for VAMS resources. Must be true when ALB, OpenSearch Provisioned, a private OpenSearch Serverless collection, or any container-based pipeline is enabled; configuration validation otherwise rejects the deployment and lists the offending features.
app.useGlobalVpc.useForAllLambdasbooleanfalseDeploys all AWS Lambda functions inside the VPC and creates required VPC interface endpoints. Recommended only for FedRAMP or external component VPC-only access requirements.
app.useGlobalVpc.addVpcEndpointsbooleantrueCreates all required VPC endpoints on the VPC (new or imported). Set to false if your imported VPC already has the necessary endpoints.
app.useGlobalVpc.optionalExternalVpcIdstringnullID of an existing VPC to import (for example, vpc-0123456789abcdef0). When set, overrides internal VPC creation. Requires isolated subnet IDs to be provided.
app.useGlobalVpc.optionalExternalIsolatedSubnetIdsstringnullComma-delimited list of isolated subnet IDs in the imported VPC. Required when using an external VPC.
app.useGlobalVpc.optionalExternalPrivateSubnetIdsstringnullComma-delimited list of private subnet IDs. Required when using RapidPipeline or ModelOps with an imported VPC.
app.useGlobalVpc.optionalExternalPublicSubnetIdsstringnullComma-delimited list of public subnet IDs. Required when using ALB with public subnets or RapidPipeline/ModelOps with an imported VPC.
app.useGlobalVpc.vpcCidrRangestring10.1.0.0/16CIDR range for the VAMS-created VPC. Ignored when importing an external VPC.
Subnet requirements

Each subnet must reside in its own Availability Zone. VAMS spreads every subnet type across a baseline of 2 Availability Zones, which also covers ALB, the EKS pipelines, and a private OpenSearch Serverless collection. Enabling OpenSearch Provisioned sets the count from app.openSearch.useProvisioned.availabilityZoneCount instead — 2 by default, optionally 3.

VPC Resource Usage by Feature

The following table shows which VPC resources are created based on enabled features and pipelines.

Subnet Requirements

VAMS provisions every subnet type across a fixed Availability Zone count (a baseline of 2) so that toggling individual features does not add or remove subnets between deployments. Amazon OpenSearch Service (Provisioned) sets the count from availabilityZoneCount (2 or 3).

Feature / PipelinePrivate SubnetsPublic SubnetsMin AZsNotes
ALB (useAlb.enabled)Yes (if usePublicSubnet)Yes2Public subnets for ALB
RapidPipeline ECS (useRapidPipeline.useEcs)YesYes2Batch compute
RapidPipeline EKS (useRapidPipeline.useEks)YesYes2EKS cluster
ModelOps (useModelOps)YesYes2Batch compute
Gaussian Splatting (useSplatToolbox)YesYes2Batch compute + CodeBuild
Coordinate Transform (useConversionCoordinateTransform)YesYes2Batch compute
Isaac Lab Training (useIsaacLabTraining)YesYes2Batch compute + CodeBuild
NVIDIA Cosmos (useNvidiaCosmos)YesYes2Batch compute + EFS + CodeBuild
NVIDIA Gr00t (useNvidiaGr00t)YesYes2Batch compute + EFS + CodeBuild
OpenSearch Provisioned (openSearch.useProvisioned)NoNoavailabilityZoneCount (2 or 3)Zone-aware Multi-AZ domain
All other featuresIsolated onlyNo2Lambda VPC endpoints

VPC Interface Endpoints

EndpointCreated WhenSubnet Type
API GatewayaddVpcEndpoints=trueIsolated
SSMaddVpcEndpoints=trueIsolated
LambdaaddVpcEndpoints=trueIsolated
STSaddVpcEndpoints=trueIsolated
CloudWatch LogsaddVpcEndpoints=trueIsolated
Step FunctionsaddVpcEndpoints=trueIsolated
SNSaddVpcEndpoints=trueIsolated
SQSaddVpcEndpoints=trueIsolated
KMSuseKmsCmkEncryption.enabled=trueIsolated
KMS FIPSuseKmsCmkEncryption.enabled=true + useFips=trueIsolated
AWS BatchAny pipeline enabledIsolated
ECR APIAny pipeline enabledIsolated
ECR DockerAny pipeline enabledIsolated
EFSuseNvidiaCosmos.enabled=trueIsolated
ECSPipelines with Batch computePrivate (preferred) or Isolated
ECS AgentuseIsaacLabTraining.enabled=trueIsolated
ECS TelemetryuseIsaacLabTraining.enabled=trueIsolated
Bedrock RuntimeuseGenAiMetadata3dLabeling.enabled=true + useForAllLambdas=trueIsolated
RekognitionuseGenAiMetadata3dLabeling.enabled=true + useForAllLambdas=trueIsolated

Gateway Endpoints (Always Created)

EndpointNotes
S3Created when addVpcEndpoints=true (no cost)
DynamoDBCreated when addVpcEndpoints=true (no cost)
note

Only one Amazon ECS interface endpoint can exist per VPC when private DNS is enabled. VAMS consolidates ECS endpoint subnets across pipeline types, with private subnets taking priority over isolated subnets when both are needed.

Cognito MFA requires the authorizer to run outside the VPC

VAMS does not create Amazon Cognito VPC interface endpoints. When Lambda functions run in the VPC (useForAllLambdas=true), the API Gateway authorizer has no path to Amazon Cognito, so VAMS disables the Cognito MFA check and mfaRequired on a role has no effect. The MFA check and MFA-aware role enforcement apply only when the authorizer runs outside the VPC.

Amazon OpenSearch Service (app.openSearch)

Implemented by

Nested stack: infra/lib/nestedStacks/searchAndIndexing/searchBuilder-nestedStack.ts (SearchBuilderNestedStack) — Amazon OpenSearch Serverless collection or a provisioned OpenSearch Service domain.

FieldTypeDefaultDescription
app.openSearch.useServerless.enabledbooleanfalseDeploys Amazon OpenSearch Serverless for pay-per-use search capability. Not available in the AWS European Sovereign Cloud, where Amazon OpenSearch Serverless is not offered — use app.openSearch.useProvisioned there. Configuration validation rejects the combination.
app.openSearch.useServerless.nextGenbooleantrueSets the generation of the Serverless collection group. true uses the NEXTGEN generation, which supports scaling compute to zero (a minimum OCU of 0); false uses the CLASSIC generation. The collection is placed in a collection group in both cases. Defaults to true for commercial partitions and must be false for AWS GovCloud and the AWS European Sovereign Cloud, where the next-generation generation is not available.
app.openSearch.useServerless.allowPublicbooleantrueControls whether the Serverless collection accepts public network access. When true, the collection is reachable over the public internet (subject to data-access policies). When false, the collection is reachable only through a VPC endpoint, which requires app.useGlobalVpc.enabled to be true. As with provisioned OpenSearch, only the OpenSearch-facing Lambda functions (search and indexers) are placed in the VPC — app.useGlobalVpc.useForAllLambdas does not need to be true. Set to false for production deployments. A fully network-isolated deployment (app.useGlobalVpc.enabled and app.useGlobalVpc.useForAllLambdas both true) must set allowPublic to false; configuration validation rejects a public collection in that topology.
app.openSearch.useServerless.enableStandbyReplicasbooleantracks nextGenEnables standby replicas on the collection group for cross-Availability-Zone redundancy. Required for the NEXTGEN generation — when nextGen is true, this must be true (OpenSearch Serverless rejects a NEXTGEN collection group with standby replicas disabled), and configuration validation enforces it. For the CLASSIC generation it is optional: false favors lower cost, true adds production high availability. Defaults to the value of nextGen (true for NEXTGEN, false for CLASSIC).
app.openSearch.useServerless.minIndexingOcunumber2Minimum indexing capacity in OpenSearch Compute Units (OCU) for the collection group. Must be one of the allowed OCU values: 0, 2, 4, 8, 16, or any multiple of 16. A value of 0 enables scale-to-zero and is supported only when nextGen is true (the NEXTGEN generation).
app.openSearch.useServerless.maxIndexingOcunumber16Maximum indexing capacity in OCU for the collection group. Must be one of the allowed OCU values: 2, 4, 8, 16, or any multiple of 16 (and at least minIndexingOcu).
app.openSearch.useServerless.minSearchOcunumber2Minimum search capacity in OCU for the collection group. Must be one of the allowed OCU values: 0, 2, 4, 8, 16, or any multiple of 16. A value of 0 enables scale-to-zero and is supported only when nextGen is true (the NEXTGEN generation).
app.openSearch.useServerless.maxSearchOcunumber16Maximum search capacity in OCU for the collection group. Must be one of the allowed OCU values: 2, 4, 8, 16, or any multiple of 16 (and at least minSearchOcu).
app.openSearch.useServerless.deployDeferredIndexSchemabooleanfalseUsed only to finish a deferred private next-gen setup (a deployment made with allowPublic=false, nextGen=true, and app.useGlobalVpc.addVpcEndpoints=false, where VAMS skipped index creation). After you manually create the aoss-data VPC endpoint and network policy, set this to true for one deployment so the schema-deploy resource creates the index mappings against the now-reachable collection, then set it back to false. Ignored when addVpcEndpoints=true (nothing is deferred). Can be overridden with CDK context deployDeferredIndexSchema=true. See OpenSearch — deferred next-gen setup.
app.openSearch.useProvisioned.enabledbooleanfalseDeploys a provisioned Amazon OpenSearch Service domain. Requires a VPC with at least availabilityZoneCount Availability Zones.
app.openSearch.useProvisioned.availabilityZoneCountnumber2Number of Availability Zones the zone-aware provisioned domain and its VPC subnets span (one data node per zone). Must be 2 or 3. At 2 the domain runs Multi-AZ without Standby; at 3 it runs Multi-AZ with Standby (the asset/file indexes are created with two replicas to give the multiple-of-three copies Standby requires). Switching an existing domain to 3 in place is rejected by the service — a 3-AZ Standby domain must be created fresh (disable and re-enable OpenSearch, then reindex). Keep 2 for Regions or partitions that expose only two Availability Zones, such as the AWS European Sovereign Cloud Region eusc-de-east-1.
app.openSearch.useProvisioned.numberOfShardsnumber1Number of primary shards per provisioned OpenSearch index (asset and file). Must be an integer of 1 or greater. Defaults to 1. Increase for large indexes — as a guideline, an index expected to exceed roughly 60 GB (about 3 million asset or file records for VAMS) should use more than one shard. Changing this value requires re-creating the index: disable and re-enable OpenSearch (or otherwise recreate the domain), then reindex. Existing indexes are not re-sharded in place.
app.openSearch.useProvisioned.dataNodeInstanceTypestringr7g.large.searchInstance type for the data nodes in the provisioned domain (one data node per Availability Zone by default).
app.openSearch.useProvisioned.masterNodeInstanceTypestringr7g.large.searchInstance type for the 3 dedicated master nodes.
app.openSearch.useProvisioned.ebsInstanceNodeSizeGbnumber120Amazon EBS volume size in GB per data node.
app.openSearch.reindexOnCdkDeploybooleanfalseTriggers automatic reindexing of all assets and files during deployment via a CloudFormation custom resource. Important: Enable only for a second deployment after initial deployment or version upgrade, then set back to false. Can be overridden with CDK context reindexOnCdkDeploy=true.
Mutual exclusion

You cannot enable both OpenSearch Serverless and OpenSearch Provisioned simultaneously. Enable at most one option, or disable both to deploy without search functionality.

Scale-to-zero and cold starts

On next-generation Serverless, setting minIndexingOcu and minSearchOcu to 0 lets the collection scale its compute down to zero when idle, which removes the standing OCU cost of an always-on collection. The trade-off is a cold start: after roughly 10 minutes without activity, the first search or indexing request incurs an added latency of about 10–20 seconds while capacity scales back up. Keep the minimums at 1 or greater to avoid cold starts when consistent low latency matters more than cost.

Private Serverless requires a VPC across two Availability Zones

A private collection (allowPublic=false) is reachable only through its VPC endpoint, which is placed across two Availability Zones for high availability. A private Serverless deployment therefore requires app.useGlobalVpc.enabled to be true, and the VPC provides at least two Availability Zones. As with provisioned OpenSearch, only the OpenSearch-facing Lambda functions (search and indexers) are placed in the VPC, so app.useGlobalVpc.useForAllLambdas does not need to be enabled. Configuration validation rejects a private collection when app.useGlobalVpc.enabled is false.

The VPC endpoint type is selected automatically by the collection generation, because the two generations expose different collection endpoint hostnames. A next-generation collection (nextGen=true) serves its endpoint on {collection-id}.aoss.{region}.on.aws and is reached through a standard AWS PrivateLink interface endpoint (service com.amazonaws.{region}.aoss-data) with private DNS enabled. A classic collection (nextGen=false) serves its endpoint on {collection-id}.{region}.aoss.amazonaws.com and is reached through the Amazon OpenSearch Serverless-managed VPC endpoint, which provisions its own Amazon Route 53 private hosted zone. VAMS creates the correct endpoint type for the configured generation; the in-VPC Lambda functions connect over private DNS on port 443 using SigV4 signing with service name aoss.

The next-generation endpoint is a standard Amazon EC2 interface endpoint, so it follows app.useGlobalVpc.addVpcEndpoints like every other interface endpoint: when that is false, VAMS does not create the endpoint or the collection's VPC network access policy, and you must create them manually after deployment (the classic managed endpoint is not governed by this flag and is always created). See OpenSearch — deferred next-gen setup for the manual setup procedure.

OpenSearch engine version by partition

Provisioned domains deploy the OpenSearch engine version pinned in config.ts. Commercial AWS, AWS GovCloud, and other partitions use the standard version (OPENSEARCH_VERSION, currently OpenSearch 3.x). The AWS European Sovereign Cloud (partition aws-eusc, Region eusc-de-east-1) does not yet support OpenSearch 3.x, so VAMS automatically deploys OPENSEARCH_VERSION_EUSOVEREIGN (OpenSearch 2.x) there instead. The selection is partition-based and requires no configuration.

OpenSearch Provisioned service-linked role

A provisioned domain in a VPC requires the AWSServiceRoleForAmazonOpenSearchService service-linked role to exist in the account. AWS normally creates it automatically, but in some accounts it is missing, which fails the deploy with "Before you can proceed, you must enable a service-linked role". VAMS creates this role idempotently during deployment — created if missing, left unchanged if it already exists — so the deployment handles that case without operator action. The role is account-wide and is not removed on stack teardown. See Common deployment errors for additional troubleshooting.

OpenSearch Provisioned is for advanced deployments

Amazon OpenSearch Serverless is the recommended option for most VAMS deployments. The provisioned option is intended for advanced deployments that require dedicated capacity, custom instance sizing, or features unsupported by Serverless, and it introduces several operational considerations that can disrupt AWS CloudFormation stack deployments:

  • VPC requirement -- A VPC spanning availabilityZoneCount Availability Zones (2 by default, optionally 3) must already exist or be created by the same deploy. When importing an existing VPC, it must already provide that many private subnets in separate Availability Zones.
  • Fragile AWS CloudFormation updates -- Domain configuration changes (instance type, EBS size, engine version) trigger blue/green updates that can take 30+ minutes and occasionally exceed the AWS CloudFormation custom-resource timeout. A major engine-version upgrade can fail in place and require redeploying with OpenSearch disabled, then re-enabling, before it succeeds.
  • Service-linked role -- A provisioned domain in a VPC requires the OpenSearch Service service-linked role. VAMS creates it idempotently during deployment (created if missing, left unchanged if present), so the "you must enable a service-linked role" error needs no manual retry.
  • Reindex required after index-name or schema bumps -- Provisioned domains do not auto-populate new indexes; you must run the version-specific data migration script to repopulate them. See Update the solution and the migration READMEs under infra/deploymentDataMigration/.

If you do not have a specific requirement that mandates Provisioned, prefer app.openSearch.useServerless.enabled = true.

Amazon Location Service (app.useLocationService)

Implemented by

Nested stack: infra/lib/nestedStacks/locationService/location-service-nestedStack.ts (LocationServiceNestedStack) — Amazon Location Service map resources (commercial partitions only).

FieldTypeDefaultDescription
app.useLocationService.enabledbooleantrueEnables Amazon Location Service for map visualization of asset metadata with geographic coordinates. Not available in AWS GovCloud. Map views require OpenSearch to be enabled.

Web distribution

Implemented by

Nested stack: infra/lib/nestedStacks/staticWebApp/staticWebBuilder-nestedStack.ts (StaticWebBuilderNestedStack) — an Amazon S3 web bucket fronted by either Amazon CloudFront (useCloudFront) or an Application Load Balancer (useAlb). These two options are mutually exclusive.

Application Load Balancer (app.useAlb)

FieldTypeDefaultDescription
app.useAlb.enabledbooleanfalseEnables ALB-based static website hosting. Required for AWS GovCloud deployments. Cannot be enabled simultaneously with Amazon CloudFront.
app.useAlb.usePublicSubnetbooleanfalsePlaces the ALB in public subnets. Warning: This exposes the web application to the public internet.
app.useAlb.addAlbS3SpecialVpcEndpointbooleantrueCreates the Amazon S3 VPC interface endpoint required by the ALB to serve static web files. Set to false only if this endpoint already exists in your VPC.
app.useAlb.domainHoststring(required when ALB enabled)Domain name for the ALB and static website Amazon S3 bucket (for example, vams.example.com).
app.useAlb.certificateArnstring(required when ALB enabled)ARN of the ACM certificate for HTTPS. Must be in the same Region as the deployment.
app.useAlb.optionalHostedZoneIdstringnullAmazon Route 53 hosted zone ID for automatic DNS alias creation. If not provided, configure DNS manually.

Amazon CloudFront (app.useCloudFront)

FieldTypeDefaultDescription
app.useCloudFront.enabledbooleantrueEnables Amazon CloudFront for static website distribution. Not available in AWS GovCloud. Cannot be enabled simultaneously with ALB.
app.useCloudFront.customDomain.enabledbooleanfalseEnables a custom domain name for the CloudFront distribution. When disabled, CloudFront uses an auto-generated *.cloudfront.net domain.
app.useCloudFront.customDomain.domainHoststring""Custom domain name (for example, vams.example.com). Must match the ACM certificate. Required when custom domain is enabled.
app.useCloudFront.customDomain.certificateArnstring""ACM certificate ARN. Must be in us-east-1 regardless of the VAMS deployment Region. Required when custom domain is enabled.
app.useCloudFront.customDomain.optionalHostedZoneIdstring""Amazon Route 53 hosted zone ID for automatic A-record alias creation. If not provided, configure DNS manually.
CloudFront certificate Region

Amazon CloudFront requires the ACM certificate to be in us-east-1. Using a certificate in any other Region causes a deployment failure.

Authentication (app.authProvider)

Implemented by

Nested stack: infra/lib/nestedStacks/auth/authBuilder-nestedStack.ts (AuthBuilderNestedStack) — Amazon Cognito user and identity pools, SAML federation, and external OAuth IdP wiring. IP-range restrictions (authorizerOptions.allowedIpRanges) are enforced by the custom Lambda authorizer built by infra/lib/lambdaBuilder/authFunctions.ts (buildApiGatewayAuthorizerRestFunction) and attached to the REST API in apiLambda/constructs/rest-api-gateway-construct.ts.

General authentication settings

FieldTypeDefaultDescription
app.authProvider.presignedUrlTimeoutSecondsnumber86400Timeout in seconds for Amazon S3 presigned URLs used for upload and download operations (default: 24 hours).

Authorizer options (app.authProvider.authorizerOptions)

FieldTypeDefaultDescription
app.authProvider.authorizerOptions.allowedIpRangesarray[]Array of IP range pairs for restricting API access. Each range is a 2-element array: ["min_ip", "max_ip"]. Leave empty to allow all IPs.
app.authProvider.authorizerOptions.defaultUserRoleNamestring""Optional role name automatically granted to authenticated users who have no explicitly assigned roles. Enables baseline access for external identity provider logins without manual per-user provisioning. The role must exist in the Roles table. Empty string (default) disables this feature.

IP range example:

"allowedIpRanges": [
["192.168.1.1", "192.168.1.255"],
["10.0.0.1", "10.0.0.255"]
]

Default role example:

"authorizerOptions": {
"allowedIpRanges": [],
"defaultUserRoleName": "basicReadOnly"
}
Default role behavior

The default role is applied only when all of the following hold:

  • The user authenticates successfully (passes custom Lambda authorizer validation).
  • The user has no role assignments in the user roles table at all. A user who holds roles keeps exactly those roles — including a user whose roles are all filtered out of a non-MFA session because they require MFA, who receives no access rather than baseline access.
  • The named role exists in the roles table. If it does not, the role is dropped and an error is logged, leaving the user with no access; the deployment is misconfigured rather than silently permissive.
  • For a non-MFA session, the named role does not itself require MFA.

This is intended for federated identity providers (Amazon Cognito OIDC or SAML federation, or external OAuth) where users authenticate successfully but are not provisioned in VAMS user management. Grant it the narrowest useful permissions — every authenticated identity that reaches the API without an assignment receives it. Leaving the value empty (the default) disables it, so an unprovisioned user has no access.

Amazon Cognito (app.authProvider.useCognito)

FieldTypeDefaultDescription
app.authProvider.useCognito.enabledbooleantrueEnables Amazon Cognito user pools for authentication. At least one authentication provider must be enabled.
app.authProvider.useCognito.useSamlbooleanfalseEnables SAML federation with an external IdP through Amazon Cognito. Cannot be used together with useOidc.
app.authProvider.useCognito.useOidcbooleanfalseEnables OIDC federation with an external IdP through Amazon Cognito. Cannot be used together with useSaml. Configure provider details in infra/config/oidc-config.ts.
app.authProvider.useCognito.useUserPasswordAuthFlowbooleanfalseEnables USER_PASSWORD_AUTH flow for non-SRP authentication. Generates a security warning. Use only when SRP libraries are unavailable for system integrations.
app.authProvider.useCognito.credTokenTimeoutSecondsnumber3600Authentication token timeout in seconds for Amazon Cognito issued tokens (default: 1 hour). Refresh token is fixed at 24 hours.
Advanced: OIDC and SAML federation through Amazon Cognito

Amazon Cognito supports federating with external identity providers using SAML 2.0 or OpenID Connect (OIDC). Provider details are managed through separate TypeScript files, while the enable flag is in config.json:

  • SAML federation: Set useCognito.useSaml to true in config.json and configure provider details in infra/config/saml-config.ts. The displayName field in saml-config.ts controls the login button label. See Security Architecture for details.
  • OIDC federation: Set useCognito.useOidc to true in config.json and configure provider details in infra/config/oidc-config.ts (client ID, issuer URL, scopes, attribute mappings). The displayName field in oidc-config.ts controls the login button label. The client secret must be stored in AWS Secrets Manager.

Only one federation method can be active at a time (useSaml and useOidc cannot both be true), and both require the Amazon Cognito hosted UI, which restricts them to the commercial partition — configuration validation rejects either one in AWS GovCloud (US), the AWS European Sovereign Cloud, and the ISO partitions. Both federation modes let users authenticate through SSO while Amazon Cognito manages the session tokens, and native username/password login remains available for users that exist in the pool. Programmatic access for a federated user uses a VamsCLI token override, since a federated identity has no password in the pool.

External OAuth IdP (app.authProvider.useExternalOAuthIdp)

FieldTypeDefaultDescription
app.authProvider.useExternalOAuthIdp.enabledbooleanfalseEnables an external OAuth 2.0 / OpenID Connect identity provider. Cannot be used simultaneously with Amazon Cognito.
app.authProvider.useExternalOAuthIdp.idpDisplayNamestring""Display name shown on the login button (for example, "Corporate SSO"). Falls back to "SSO" in the UI when empty.
app.authProvider.useExternalOAuthIdp.idpAuthProviderUrlstringnullBase URL of the external OAuth IdP (for example, https://ping-federate.example.com).
app.authProvider.useExternalOAuthIdp.idpAuthClientIdstringnullClient ID registered with the external IdP for this VAMS deployment.
app.authProvider.useExternalOAuthIdp.idpAuthProviderScopestringnullOAuth scope requested by VAMS.
app.authProvider.useExternalOAuthIdp.idpAuthProviderScopeMfastringnullMFA scope attribute appended to the base scope. Set to enable MFA enforcement.
app.authProvider.useExternalOAuthIdp.idpAuthPrincipalDomainstringnullPrincipal domain for the IdP endpoint (for example, ping-federate.example.com).
app.authProvider.useExternalOAuthIdp.idpAuthProviderTokenEndpointstringnullToken endpoint path (for example, /as/token.oauth2).
app.authProvider.useExternalOAuthIdp.idpAuthProviderAuthorizationEndpointstringnullAuthorization endpoint path (for example, /as/authorization.oauth2).
app.authProvider.useExternalOAuthIdp.idpAuthProviderDiscoveryEndpointstringnullDiscovery endpoint path (for example, /.well-known/openid-configuration).
app.authProvider.useExternalOAuthIdp.lambdaAuthorizorJWTIssuerUrlstringnullJWT issuer URL for the custom Lambda authorizer to validate tokens.
app.authProvider.useExternalOAuthIdp.lambdaAuthorizorJWTAudiencestringnullJWT audience claim for token verification.
All fields required

When external OAuth IdP is enabled, all fields in this section are required. Deployment will fail if any field is null or empty.

API configuration (app.api)

Implemented by

Nested stack: infra/lib/nestedStacks/apiLambda/api-nestedStack.ts (ApiNestedStack) — builds the Amazon API Gateway REST API through RestApiGatewayConstruct, including the endpoint type (REGIONAL/PRIVATE) and stage throttling (rate and burst limits).

FieldTypeDefaultDescription
app.api.apiTypestring"APIGATEWAY_REST"Backend API implementation type. Only "APIGATEWAY_REST" (an Amazon API Gateway REST API) is supported; any other value fails configuration validation.
app.api.apiGatewayRest.endpointTypestring"REGIONAL"API Gateway endpoint type. "REGIONAL" creates a public regional REST API (default) that does not route through any VPC endpoint. "PRIVATE" creates a private REST API reachable only through an execute-api VPC interface endpoint; it requires useGlobalVpc.enabled and either useGlobalVpc.addVpcEndpoints = true or optionalExternalPrivateApigVPCEId set, and is incompatible with Amazon CloudFront (requires ALB).
app.api.apiGatewayRest.globalRateLimitnumber50Global rate limit in requests per second for the Amazon API Gateway. Must be a positive number.
app.api.apiGatewayRest.globalBurstLimitnumber100Global burst limit for the Amazon API Gateway. Must be greater than or equal to globalRateLimit.
app.api.apiGatewayRest.optionalExternalPrivateApigVPCEIdstring""Id of a pre-existing execute-api interface VPC endpoint to use for a "PRIVATE" endpoint when VAMS does not create one (useGlobalVpc.addVpcEndpoints = false). Applies only to "PRIVATE"; it is ignored (with a configuration warning) for a "REGIONAL" endpoint.
app.api.apiGatewayRest.apiGatewayTimeoutTimenumber29Integration timeout in seconds — how long Amazon API Gateway waits for a backend Lambda function to respond before returning a 504. Must be a whole number between 29 and 300. Applies to every API route, for both "REGIONAL" and "PRIVATE" endpoint types. Values above 29 require an approved account-level quota increase first (see the warning below).
PRIVATE endpoint requirements

Setting app.api.apiGatewayRest.endpointType to "PRIVATE" requires useGlobalVpc.enabled = true and an execute-api interface VPC endpoint: either set useGlobalVpc.addVpcEndpoints = true so VAMS creates one, or set app.api.apiGatewayRest.optionalExternalPrivateApigVPCEId to an existing endpoint id. A PRIVATE endpoint is incompatible with Amazon CloudFront (which cannot reach a private API); you must front it with the ALB (useCloudFront.enabled = false, useAlb.enabled = true), and that ALB must run in isolated (non-public) subnets (useAlb.usePublicSubnet = false). A public-subnet ALB would expose an internet-facing path to the private API, defeating its isolation. Configuration validation enforces all of these.

Raising the integration timeout requires an AWS quota increase first

app.api.apiGatewayRest.apiGatewayTimeoutTime defaults to 29 seconds, the Amazon API Gateway default integration timeout. Setting it higher requires an approved increase to the account-level Integration timeout quota (L-E5AE38E3) in the deployment Region, requested through the AWS Service Quotas console or AWS Support. Request and receive the increase before deploying with a higher value — Amazon API Gateway rejects an integration timeout above the account's approved quota, which fails the deployment.

The increase applies to both "REGIONAL" and "PRIVATE" endpoint types, which are the two types VAMS supports. Raising this quota may require a compensating reduction in the Region-level request throttle quota for the account, so review both quotas together. A configuration warning is emitted at synthesis time whenever the value exceeds 29 seconds as a reminder.

A longer timeout lets operations on assets with many files or many relationships complete within a single synchronous request instead of returning a 504 while the Lambda function continues working in the background. The AWS Lambda function timeout (15 minutes) remains the outer bound, so a value above the 300-second maximum would not extend the useful window for a synchronous request.

Execute-API VPC endpoint

A REGIONAL endpoint is public and does not route through a VPC endpoint, even when a VPC and its endpoints are enabled. Only a PRIVATE endpoint uses the execute-api interface VPC endpoint: VAMS creates it when useGlobalVpc.addVpcEndpoints = true, otherwise supply an existing one through app.api.apiGatewayRest.optionalExternalPrivateApigVPCEId.

warning
Switching endpointType between PRIVATE and REGIONAL on an existing deployment

Changing app.api.apiGatewayRest.endpointType on a deployment that already exists is fully supported. A PRIVATE endpoint carries an API Gateway resource policy that only allows invocation through the execute-api VPC interface endpoint (an aws:SourceVpce condition); a REGIONAL endpoint uses a public allow-all resource policy. VAMS sets the correct resource policy for each endpoint type on every deployment, so switching in either direction updates the policy — no manual action is required.

Amazon API Gateway itself does not remove a previously-set resource policy when an update simply stops supplying one, which is why VAMS always writes an explicit policy: switching PRIVATEREGIONAL overwrites the aws:SourceVpce-restricted policy with the public allow-all policy, and REGIONALPRIVATE re-applies the VPC-endpoint restriction. If a resource policy left over from an out-of-band change ever remains in place after a switch (for example, a PRIVATE policy on a now-public endpoint), every request — including the CORS preflight — is denied at the resource-policy layer with 403 AccessDeniedException ("no resource-based policy allows the execute-api:Invoke action"). Because that denial precedes the CORS response, a browser reports it as a missing Access-Control-Allow-Origin / failed-preflight error rather than an authorization error. Re-running the VAMS deployment restores the correct policy for the configured endpointType.

REST API TLS security policy

VAMS sets the minimum TLS version and cipher suite on the REST API itself, so it applies to the default execute-api endpoint. The policy is derived from the deployment configuration and is not a separate configuration option.

DeploymentSecurity policyTLS versions accepted
CommercialSecurityPolicy_TLS13_1_2_2021_06TLS 1.3, TLS 1.2
GovCloud and EU Sovereign Cloud (app.govCloud.enabled)Partition and Region default (unchanged)TLS 1.3, TLS 1.2

In the commercial partition, a Regional REST API would otherwise default to the TLS_1_0 policy, which accepts TLS 1.0 and TLS 1.1. VAMS raises the floor to SecurityPolicy_TLS13_1_2_2021_06 and sets the required endpoint access mode to BASIC, so the Amazon CloudFront origin request, the ALB redirect to execute-api, and direct execute-api access all continue to work. A TLS 1.3-only policy is not used because CloudFront negotiates at most TLS 1.2 to a custom origin.

The GovCloud mode, which AWS European Sovereign Cloud deployments also enable, leaves the policy unset so the API keeps its partition and Region default. Those partitions do not offer the TLS_1_0 policy for Regional APIs and their APIs are FIPS-compliant by default, so the minimum version is already TLS 1.2.

A security policy change takes about 15 minutes to propagate, and the API stays invocable while its status is UPDATING. See Security for the full description.

Web UI (app.webUi)

Implemented by

Consumed by the static web hosting stack infra/lib/nestedStacks/staticWebApp/staticWebBuilder-nestedStack.ts (StaticWebBuilderNestedStack). allowUnsafeEvalFeatures feeds Content Security Policy generation in infra/lib/helper/security.ts.

FieldTypeDefaultDescription
app.webUi.optionalBannerHtmlMessagestring""Optional HTML message displayed as a banner in the web interface. Use for system notifications or compliance messages (for example, "AWS Sandbox System. Do not upload sensitive information.").
app.webUi.allowUnsafeEvalFeaturesbooleanfalseAllows unsafe-eval in the Content Security Policy for script execution. Required for certain viewer plugins (Needle USD, SuperSplat Editor, ThatOpen IFC BIM, and the Three.js CAD formats). Consult your security team before enabling.
app.webUi.allowLocalhostAuthCallbacksbooleanfalseRegisters http://localhost:3001 as an Amazon Cognito callback and logout URL, so a web front run locally with npm run start can complete a federated sign-in against the deployed user pool. Read only when Cognito SAML or OIDC federation is enabled — without federation VAMS performs no OAuth redirect. The URLs are registered on the same user pool that serves application users, and the redirect target is on the developer's own machine, so leave this off for a deployment that serves real users and enable it only on a development deployment.

Metadata schema (app.metadataSchema)

Controls auto-loading of default metadata schemas during deployment.

Implemented by

Nested stack: infra/lib/nestedStacks/apiLambda/apiBuilder-nestedStack.ts (ApiBuilderNestedStack) — a default-schema seeding custom resource that writes to the metadata-schema DynamoDB table.

FieldTypeDefaultDescription
app.metadataSchema.autoLoadDefaultAssetLinksSchemabooleantrueCreates a GLOBAL schema named defaultAssetLinks with Translation (XYZ), Rotation (WXYZ), Scale (XYZ), and Matrix (MATRIX4X4) fields for spatial relationship metadata.
app.metadataSchema.autoLoadDefaultDatabaseSchemabooleantrueCreates a GLOBAL schema named defaultDatabase with a Location field (LLA - Latitude/Longitude/Altitude).
app.metadataSchema.autoLoadDefaultAssetSchemabooleantrueCreates a GLOBAL schema named defaultAsset with a Location field (LLA - Latitude/Longitude/Altitude).
app.metadataSchema.autoLoadDefaultAssetFileSchemabooleantrueCreates a GLOBAL schema named defaultAssetFile3dModel with a Polygon_Count field and file type restrictions for common 3D formats (.glb, .usd, .obj, .fbx, .gltf, .stl, .usdz).

Processing pipelines (app.pipelines)

Implemented by

All pipelines are orchestrated by infra/lib/nestedStacks/pipelines/pipelineBuilder-nestedStack.ts (PipelineBuilderNestedStack). Each enabled pipeline below is conditionally instantiated as its own child nested stack (named in each section).

Availability outside the commercial partition

The NVIDIA Cosmos Predict, Cosmos Reason, Cosmos Transfer, Cosmos 3, and Gr00t pipelines run on GPU instance families and download model weights from HuggingFace. Configuration validation checks only that an enabled model variant names a non-empty instanceTypes array -- it does not check that those instance families are offered in the deployment Region, or that the model download path is reachable from the partition. For AWS GovCloud and the AWS European Sovereign Cloud, compare the configured instance types against the GPU instances the target Region offers, adjust them where they differ, and evaluate the pipeline in a non-production deployment before enabling it.

Region availability is not sufficient on its own: an instance type is only a usable fallback when the pipeline's subnets reach an Availability Zone that offers it. VAMS creates two AZs by default (more only when app.openSearch.useProvisioned.availabilityZoneCount raises it), so a type offered in just one AZ of the Region may be unreachable. Measured in us-west-2: p5e.48xlarge is offered only in us-west-2c, while a default deployment's subnets resolved to us-west-2a and us-west-2b — so a list naming it has one fewer real fallback than it appears to, and a job waits for capacity that cannot be placed. Check the offering set for the target Region before relying on a fallback:

aws ec2 describe-instance-type-offerings --location-type availability-zone \
--filters Name=instance-type,Values=p5e.48xlarge \
--query 'InstanceTypeOfferings[].Location'

The Default column in the pipeline tables is the value the shipped config.template.*.json files carry. When a pipeline block is present but omits a field, getConfig() fills in a fallback that may be more conservative than the template: enabled falls back to false (useConversion3dBasic.enabled falls back to true), autoRegisterWithVAMS falls back to true, and autoRegisterAutoTriggerOnFileUpload falls back to false so an omitted key never arms an upload trigger. A pipeline block that is absent entirely is disabled, so its remaining fields have no effect.

3D basic conversion (app.pipelines.useConversion3dBasic)

Reads STL, OBJ, PLY, GLTF, GLB and XYZ files and converts them to STL, OBJ, PLY, GLTF or GLB. XYZ is an input-only format. Does not require a VPC.

Implemented by

Nested stack: infra/lib/nestedStacks/pipelines/conversion/3dBasic/conversion3dBasicBuilder-nestedStack.ts (Conversion3dBasicNestedStack) — a containerized AWS Lambda function.

FieldTypeDefaultDescription
app.pipelines.useConversion3dBasic.enabledbooleantrueEnables the 3D basic conversion pipeline.
app.pipelines.useConversion3dBasic.autoRegisterWithVAMSbooleantrueAutomatically registers the pipeline and workflow in the VAMS database during deployment.

CAD/mesh metadata extraction (app.pipelines.useConversionCadMeshMetadataExtraction)

Extracts metadata from CAD and mesh file formats. Does not require a VPC.

Implemented by

Nested stack: infra/lib/nestedStacks/pipelines/conversion/meshCadMetadataExtraction/conversionMeshCadMetadataExtractionBuilder-nestedStack.ts (ConversionMeshCadMetadataExtractionNestedStack) — a containerized AWS Lambda function.

FieldTypeDefaultDescription
app.pipelines.useConversionCadMeshMetadataExtraction.enabledbooleanfalseEnables the CAD/mesh metadata extraction pipeline.
app.pipelines.useConversionCadMeshMetadataExtraction.autoRegisterWithVAMSbooleantrueAutomatically registers the pipeline during deployment.
app.pipelines.useConversionCadMeshMetadataExtraction.autoRegisterAutoTriggerOnFileUploadbooleantrueAutomatically triggers the pipeline on file uploads matching supported file types.

Point cloud coordinate transform (app.pipelines.useConversionCoordinateTransform)

Reprojects E57, LAS, and LAZ point cloud files between coordinate reference systems using PDAL and pyproj. Runs on AWS Batch with AWS Fargate compute. Requires VPC. See the Coordinate Transform pipeline page for input parameters and per-asset metadata overrides.

Implemented by

Nested stack: infra/lib/nestedStacks/pipelines/conversion/coordinateTransform/coordinateTransformBuilder-nestedStack.ts (CoordinateTransformBuilderNestedStack) — AWS Batch on Fargate.

FieldTypeDefaultDescription
app.pipelines.useConversionCoordinateTransform.enabledbooleanfalseEnables the point cloud coordinate transform pipeline.
app.pipelines.useConversionCoordinateTransform.useCodeBuildbooleanfalseBuilds the container image with AWS CodeBuild and Amazon ECR during deployment instead of a local Docker build. The CodeBuild project runs outside the VPC to pull public base images. CodeBuild builds run asynchronously and outlive the deployment: the stack reports success as soon as the build is STARTED, so a green deploy does not mean the image exists. The pipeline is registered regardless, so a failed build leaves a selectable pipeline whose jobs cannot start — check the CodeBuild project name in the CDK stack outputs before running it.
app.pipelines.useConversionCoordinateTransform.autoRegisterWithVAMSbooleantrueAutomatically registers the pipeline and workflow in the VAMS database during deployment.
app.pipelines.useConversionCoordinateTransform.autoRegisterAutoTriggerOnFileUploadbooleanfalseAutomatically triggers the pipeline when supported point cloud files are uploaded. Requires autoRegisterWithVAMS to be enabled.

Point cloud Potree viewer (app.pipelines.usePreviewPcPotreeViewer)

Processes E57, LAS, and LAZ point cloud files for Potree web viewing. Requires VPC. Uses a GPL-licensed library.

Implemented by

Nested stack: infra/lib/nestedStacks/pipelines/preview/pcPotreeViewer/pcPotreeViewerBuilder-nestedStack.ts (PcPotreeViewerBuilderNestedStack) — AWS Batch on Fargate.

FieldTypeDefaultDescription
app.pipelines.usePreviewPcPotreeViewer.enabledbooleanfalseEnables the point cloud Potree viewer pipeline.
app.pipelines.usePreviewPcPotreeViewer.autoRegisterWithVAMSbooleantrueAutomatically registers the pipeline during deployment.
app.pipelines.usePreviewPcPotreeViewer.autoRegisterAutoTriggerOnFileUploadbooleantrueAutomatically triggers the pipeline on file uploads.

3D preview thumbnail (app.pipelines.usePreview3dThumbnail)

Generates animated GIF and static PNG preview thumbnails from 3D mesh, point cloud, CAD, and USD files. Requires VPC. Uses LGPL-licensed libraries. Supports input files up to 100 GB.

Implemented by

Nested stack: infra/lib/nestedStacks/pipelines/preview/3dThumbnail/preview3dThumbnailBuilder-nestedStack.ts (Preview3dThumbnailBuilderNestedStack) — AWS Batch on Fargate.

FieldTypeDefaultDescription
app.pipelines.usePreview3dThumbnail.enabledbooleanfalseEnables the 3D preview thumbnail pipeline.
app.pipelines.usePreview3dThumbnail.autoRegisterWithVAMSbooleantrueAutomatically registers the pipeline during deployment.
app.pipelines.usePreview3dThumbnail.autoRegisterAutoTriggerOnFileUploadbooleantrueAutomatically triggers the pipeline on file uploads matching supported 3D file types.

GenAI metadata labeling (app.pipelines.useGenAiMetadata3dLabeling)

Uses Amazon Bedrock to generate descriptive metadata labels for GLB, FBX, and OBJ files. Requires VPC.

Implemented by

Nested stack: infra/lib/nestedStacks/pipelines/genAi/metadata3dLabeling/metadata3dLabelingBuilder-nestedStack.ts (Metadata3dLabelingNestedStack) — AWS Batch on Fargate with Amazon Bedrock inference.

FieldTypeDefaultDescription
app.pipelines.useGenAiMetadata3dLabeling.enabledbooleanfalseEnables the GenAI metadata labeling pipeline.
app.pipelines.useGenAiMetadata3dLabeling.bedrockModelIdstring(required when enabled)Amazon Bedrock model ID for inference (for example, global.anthropic.claude-sonnet-4-5-20250929-v1:0). A cross-Region inference-profile prefix is partition-specific: global. and us. exist in the commercial partition, and AWS GovCloud (US) uses us-gov.. Configuration validation rejects a commercial prefix outside the commercial partition, and the GovCloud and EU Sovereign Cloud templates leave the value empty for the operator to set from the models offered in their partition.
app.pipelines.useGenAiMetadata3dLabeling.autoRegisterWithVAMSbooleantrueAutomatically registers the pipeline during deployment.
app.pipelines.useGenAiMetadata3dLabeling.autoRegisterAutoTriggerOnFileUploadbooleanfalseAutomatically triggers the pipeline on file uploads.

Gaussian splatting (app.pipelines.useSplatToolbox)

Generates Gaussian splat reconstructions from media files. Requires VPC.

Implemented by

Nested stack: infra/lib/nestedStacks/pipelines/3dRecon/splatToolbox/splatToolboxBuilder-nestedStack.ts (SplatToolboxBuilderNestedStack) — AWS Batch on GPU instances.

FieldTypeDefaultDescription
app.pipelines.useSplatToolbox.enabledbooleanfalseEnables the Gaussian splatting pipeline.
app.pipelines.useSplatToolbox.useCodeBuildbooleanfalseBuild the container image via AWS CodeBuild + Amazon ECR instead of a local Docker build. Recommended for this pipeline — the image is a large CUDA/PyTorch build. CodeBuild runs in the same private VPC subnets as the pipeline Batch compute environments, with NAT Gateway egress. When false, the image is built locally with a CDK DockerImageAsset (requires local Docker). CodeBuild builds run asynchronously and outlive the deployment: the stack reports success as soon as the build is STARTED, so a green deploy does not mean the image exists. The pipeline is registered regardless, so a failed build leaves a selectable pipeline whose jobs cannot start — check the CodeBuild project name in the CDK stack outputs before running it.
app.pipelines.useSplatToolbox.autoRegisterWithVAMSbooleantrueAutomatically registers the pipeline during deployment.

Mesh to Gaussian Splat (app.pipelines.useMesh2Splat)

Converts GLB mesh files to 3D Gaussian Splat PLY files using GPU-accelerated conversion. Requires VPC.

Implemented by

No useMesh2Splat configuration key or nested stack currently exists in the infrastructure code (infra/config/config.ts, infra/lib/nestedStacks/pipelines/). This section documents a planned pipeline that is not yet implemented.

FieldTypeDefaultDescription
app.pipelines.useMesh2Splat.enabledbooleanfalseEnables the Mesh2Splat pipeline.
app.pipelines.useMesh2Splat.autoRegisterWithVAMSbooleantrueAutomatically registers the pipeline during deployment.
app.pipelines.useMesh2Splat.autoRegisterAutoTriggerOnFileUploadbooleanfalseAutomatically triggers the pipeline when .glb files are uploaded.

RapidPipeline on Amazon ECS (app.pipelines.useRapidPipeline.useEcs)

Third-party spatial data optimization. Requires VPC and an AWS Marketplace subscription.

Implemented by

Nested stack: infra/lib/nestedStacks/pipelines/multi/rapidPipeline/rapidPipeline-nestedStack.ts (RapidPipelineNestedStack) — Amazon ECS on Fargate.

FieldTypeDefaultDescription
app.pipelines.useRapidPipeline.useEcs.enabledbooleanfalseEnables RapidPipeline on Amazon ECS.
app.pipelines.useRapidPipeline.useEcs.ecrContainerImageURIstring(required when enabled)Amazon ECR container image URI for the RapidPipeline container.
app.pipelines.useRapidPipeline.useEcs.autoRegisterWithVAMSbooleantrueAutomatically registers the pipeline during deployment.

RapidPipeline on Amazon EKS (app.pipelines.useRapidPipeline.useEks)

Third-party spatial data optimization on Amazon EKS. Requires VPC with 2+ Availability Zones and an AWS Marketplace subscription.

Implemented by

Nested stack: infra/lib/nestedStacks/pipelines/multi/rapidPipelineEKS/rapidPipelineEKS-nestedStack.ts (RapidPipelineEKSNestedStack) — Amazon EKS.

FieldTypeDefaultDescription
app.pipelines.useRapidPipeline.useEks.enabledbooleanfalseEnables RapidPipeline on Amazon EKS.
app.pipelines.useRapidPipeline.useEks.ecrContainerImageURIstring(required when enabled)Amazon ECR container image URI for the RapidPipeline container.
app.pipelines.useRapidPipeline.useEks.autoRegisterWithVAMSbooleantrueAutomatically registers the pipeline during deployment.
app.pipelines.useRapidPipeline.useEks.eksClusterVersionstring1.36Kubernetes version for the Amazon EKS cluster, as an EKS minor version (1.NN).
app.pipelines.useRapidPipeline.useEks.nodeInstanceTypestringm5.2xlargeAmazon EC2 instance type for EKS worker nodes.
app.pipelines.useRapidPipeline.useEks.minNodesnumber1Minimum worker nodes in the auto-scaling group.
app.pipelines.useRapidPipeline.useEks.maxNodesnumber10Maximum worker nodes in the auto-scaling group.
app.pipelines.useRapidPipeline.useEks.desiredNodesnumber2Desired worker node count under normal operation.
app.pipelines.useRapidPipeline.useEks.jobTimeoutnumber7200Maximum job runtime in seconds (default: 2 hours).
app.pipelines.useRapidPipeline.useEks.jobMemorystring16GiMemory allocation per Kubernetes job pod.
app.pipelines.useRapidPipeline.useEks.jobCpustring2000mCPU allocation per Kubernetes job pod in millicores.
app.pipelines.useRapidPipeline.useEks.jobBackoffLimitnumber2Number of retries before marking a job as failed.
app.pipelines.useRapidPipeline.useEks.jobTTLSecondsAfterFinishednumber600Seconds to retain completed job pods before cleanup.
app.pipelines.useRapidPipeline.useEks.observability.enableControlPlaneLogsbooleanfalseEnables EKS control plane logging to Amazon CloudWatch. Incurs additional costs.
app.pipelines.useRapidPipeline.useEks.observability.enableContainerInsightsbooleanfalseEnables Amazon CloudWatch Container Insights for the cluster. Incurs additional costs.

ModelOps (app.pipelines.useModelOps)

Third-party 3D model optimization by VNTANA. Requires VPC and an AWS Marketplace subscription.

Implemented by

Nested stack: infra/lib/nestedStacks/pipelines/multi/modelOps/modelOps-nestedStack.ts (ModelOpsNestedStack) — Amazon ECS on Fargate.

FieldTypeDefaultDescription
app.pipelines.useModelOps.enabledbooleanfalseEnables the ModelOps pipeline.
app.pipelines.useModelOps.ecrContainerImageURIstring(required when enabled)Amazon ECR container image URI for the ModelOps container.
app.pipelines.useModelOps.autoRegisterWithVAMSbooleantrueAutomatically registers the pipeline during deployment.

Isaac Lab training (app.pipelines.useIsaacLabTraining)

NVIDIA Isaac Lab reinforcement learning training pipeline on GPU instances. Requires VPC.

Implemented by

Nested stack: infra/lib/nestedStacks/pipelines/simulation/isaacLabTraining/isaacLabTrainingBuilder-nestedStack.ts (IsaacLabTrainingBuilderNestedStack) — AWS Batch on GPU instances.

Air-gapped deployments

Isaac Lab features that reach the NVIDIA Omniverse content server need outbound internet access and therefore do not operate in an air-gapped deployment. The pipeline's compute runs in PRIVATE_WITH_EGRESS subnets with a NAT gateway; Amazon VPC endpoints cover the AWS services the pipeline calls but not the NVIDIA content server. Configuration validation does not check for egress, so evaluate the tasks you intend to run before enabling this pipeline on an isolated network.

FieldTypeDefaultDescription
app.pipelines.useIsaacLabTraining.enabledbooleanfalseEnables the Isaac Lab training pipeline.
app.pipelines.useIsaacLabTraining.acceptNvidiaEulabooleanfalseRequired when enabled. Confirms acceptance of the NVIDIA Software License Agreement. Deployment fails if not set to true when the pipeline is enabled.
app.pipelines.useIsaacLabTraining.useCodeBuildbooleanfalseWhen true, the Isaac Lab container is built using AWS CodeBuild in the cloud and pushed to ECR. When false (default), the container is built locally during CDK deployment using DockerImageAsset. CodeBuild runs in the same private VPC subnets as the pipeline Batch compute environments, with NAT Gateway egress for internet access, and forwards the acceptNvidiaEula flag as the ACCEPT_EULA Docker build argument. CodeBuild builds run asynchronously and outlive the deployment: the stack reports success as soon as the build is STARTED, so a green deploy does not mean the image exists. The pipeline is registered regardless, so a failed build leaves a selectable pipeline whose jobs cannot start — check the CodeBuild project name in the CDK stack outputs before running it.
app.pipelines.useIsaacLabTraining.autoRegisterWithVAMSbooleantrueAutomatically registers training and evaluation workflows during deployment.
app.pipelines.useIsaacLabTraining.keepWarmInstancebooleanfalseKeeps a warm AWS Batch compute instance running to reduce cold start times. Warning: Incurs continuous compute costs even when no jobs are running.

NVIDIA Cosmos Predict (app.pipelines.useNvidiaCosmos)

NVIDIA Cosmos world foundation models for generating videos from text prompts (Text2World) and from images/videos (Video2World). Requires VPC and internet access for HuggingFace model downloads.

Implemented by

Nested stack: infra/lib/nestedStacks/pipelines/genAi/nvidia/cosmos/cosmosBuilder-nestedStack.ts (CosmosBuilderNestedStack) — AWS Batch on GPU instances. This single stack implements all NVIDIA Cosmos models: Predict, Reason, Transfer, and Cosmos 3.

FieldTypeDefaultDescription
app.pipelines.useNvidiaCosmos.enabledbooleanfalseEnables the NVIDIA Cosmos Predict pipeline.
app.pipelines.useNvidiaCosmos.huggingFaceTokenstring""HuggingFace Read access token value (e.g., hf_xxxx). CDK stores this in AWS Secrets Manager during deployment. Must have access to all 6 required Cosmos models. Required when enabled.
app.pipelines.useNvidiaCosmos.useCodeBuildbooleanfalseWhen true, Cosmos pipeline containers are built using AWS CodeBuild in the cloud. When false (default), containers are built locally during CDK deployment using DockerImageAsset. CodeBuild runs in the same private VPC subnets as the pipeline Batch compute environments, with NAT Gateway egress for internet access. Consider configuring Docker Hub authentication credentials to avoid rate limiting (429 errors). CodeBuild builds run asynchronously and outlive the deployment: the stack reports success as soon as the build is STARTED, so a green deploy does not mean the image exists. The pipeline is registered regardless, so a failed build leaves a selectable pipeline whose jobs cannot start — check the CodeBuild project name in the CDK stack outputs before running it.
app.pipelines.useNvidiaCosmos.useWarmInstancesbooleanfalseKeeps GPU instances running when idle for instant pipeline starts. When false, scales to zero after job completion (5-10 min cold start). Warning: Warm instances incur continuous compute costs ($5.67/hr per g5.12xlarge).
app.pipelines.useNvidiaCosmos.warmInstanceCountnumber1Number of warm GPU instances to keep running when useWarmInstances is true.
app.pipelines.useNvidiaCosmos.modelsPredict.text2world2B_v2.enabledbooleanfalseEnables Cosmos-Predict2.5-2B-Text2World for generating ~4-second videos from text prompts using the v2.5 flow-matching architecture.
app.pipelines.useNvidiaCosmos.modelsPredict.text2world2B_v2.autoRegisterWithVAMSbooleantrueAutomatically registers the Text2World 2B v2.5 pipeline during deployment.
app.pipelines.useNvidiaCosmos.modelsPredict.text2world2B_v2.instanceTypesarray["g6e.12xlarge", "g5.12xlarge", "g5.48xlarge"]EC2 GPU instance types for AWS Batch compute (BEST_FIT_PROGRESSIVE). Requires 4 GPUs with 24GB+ VRAM. 2B model runs without CPU offloading.
app.pipelines.useNvidiaCosmos.modelsPredict.text2world2B_v2.maxVCpusnumber192Maximum vCPUs for the AWS Batch compute environment.
app.pipelines.useNvidiaCosmos.modelsPredict.text2world14B_v2.enabledbooleanfalseEnables Cosmos-Predict2.5-14B-Text2World for generating ~4-second videos from text prompts using the v2.5 flow-matching architecture. Requires P-series instances.
app.pipelines.useNvidiaCosmos.modelsPredict.text2world14B_v2.autoRegisterWithVAMSbooleantrueAutomatically registers the Text2World 14B v2.5 pipeline during deployment.
app.pipelines.useNvidiaCosmos.modelsPredict.text2world14B_v2.instanceTypesarray["g6e.48xlarge", "p5.48xlarge"]EC2 GPU instance types for AWS Batch compute (BEST_FIT_PROGRESSIVE). 14B models use 8-GPU context parallelism via torchrun. g6e.48xlarge (8x L40S 48GB) recommended; p5.48xlarge (8x H100 80GB) as fallback. Note: p4d instances are not supported due to older CUDA driver incompatibilities.
app.pipelines.useNvidiaCosmos.modelsPredict.text2world14B_v2.maxVCpusnumber192Maximum vCPUs for the AWS Batch compute environment (g6e.48xlarge and p5.48xlarge both have 192 vCPUs).
app.pipelines.useNvidiaCosmos.modelsPredict.video2world2B_v2.enabledbooleanfalseEnables Cosmos-Predict2.5-2B-Video2World for generating ~4-second videos from image/video inputs with optional text guidance using the v2.5 flow-matching architecture.
app.pipelines.useNvidiaCosmos.modelsPredict.video2world2B_v2.autoRegisterWithVAMSbooleantrueAutomatically registers the Video2World 2B v2.5 pipeline during deployment.
app.pipelines.useNvidiaCosmos.modelsPredict.video2world2B_v2.autoTriggerOnFileExtensionsUploadstring""Comma-separated list of file extensions to auto-trigger the pipeline on upload (for example, ".jpg,.png,.mp4"). Leave empty to disable auto-trigger.
app.pipelines.useNvidiaCosmos.modelsPredict.video2world2B_v2.instanceTypesarray["g6e.12xlarge", "g5.12xlarge", "g5.48xlarge"]EC2 GPU instance types for AWS Batch compute (BEST_FIT_PROGRESSIVE). Requires 4 GPUs with 24GB+ VRAM. 2B model runs without CPU offloading.
app.pipelines.useNvidiaCosmos.modelsPredict.video2world2B_v2.maxVCpusnumber192Maximum vCPUs for the AWS Batch compute environment.
app.pipelines.useNvidiaCosmos.modelsPredict.video2world14B_v2.enabledbooleanfalseEnables Cosmos-Predict2.5-14B-Video2World for generating ~4-second videos from image/video inputs with optional text guidance using the v2.5 flow-matching architecture. Requires P-series instances.
app.pipelines.useNvidiaCosmos.modelsPredict.video2world14B_v2.autoRegisterWithVAMSbooleantrueAutomatically registers the Video2World 14B v2.5 pipeline during deployment.
app.pipelines.useNvidiaCosmos.modelsPredict.video2world14B_v2.autoTriggerOnFileExtensionsUploadstring""Comma-separated list of file extensions to auto-trigger the pipeline on upload. Leave empty to disable auto-trigger.
app.pipelines.useNvidiaCosmos.modelsPredict.video2world14B_v2.instanceTypesarray["g6e.48xlarge", "p5.48xlarge"]EC2 GPU instance types for AWS Batch compute (BEST_FIT_PROGRESSIVE). 14B models use 8-GPU context parallelism via torchrun. g6e.48xlarge (8x L40S 48GB) recommended; p5.48xlarge (8x H100 80GB) as fallback. Note: p4d instances are not supported due to older CUDA driver incompatibilities.
app.pipelines.useNvidiaCosmos.modelsPredict.video2world14B_v2.maxVCpusnumber192Maximum vCPUs for the AWS Batch compute environment (g6e.48xlarge and p5.48xlarge both have 192 vCPUs).

NVIDIA Cosmos Reason (app.pipelines.useNvidiaCosmos.modelsReason)

NVIDIA Cosmos Reason Vision Language Models (VLMs) for analyzing video content to generate text-based analysis, captions, descriptions, and reasoning. Still images are not accepted: the upstream model utilities fail when writing an image input back out, so the pipeline restricts its inputs to .mp4 and .mov rather than failing a run after the model has loaded. Requires VPC and internet access for HuggingFace model downloads. Shares the same EFS model cache and HuggingFace token as Cosmos Predict pipelines.

FieldTypeDefaultDescription
app.pipelines.useNvidiaCosmos.modelsReason.reason2B.enabledbooleanfalseEnables Cosmos-Reason2-2B Vision Language Model for video analysis generating text-based output. Model size: ~5GB.
app.pipelines.useNvidiaCosmos.modelsReason.reason2B.autoRegisterWithVAMSbooleantrueAutomatically registers the Reason 2B pipeline during deployment.
app.pipelines.useNvidiaCosmos.modelsReason.reason2B.autoTriggerOnFileExtensionsUploadstring""Comma-separated file extensions to auto-trigger on upload (e.g., ".mp4,.mov"). Leave empty to disable.
app.pipelines.useNvidiaCosmos.modelsReason.reason2B.instanceTypesarray["g6e.12xlarge", "g5.12xlarge"]EC2 GPU instance types for AWS Batch compute (BEST_FIT_PROGRESSIVE). Requires 24GB+ VRAM.
app.pipelines.useNvidiaCosmos.modelsReason.reason2B.maxVCpusnumber192Maximum vCPUs for the AWS Batch compute environment.
app.pipelines.useNvidiaCosmos.modelsReason.reason8B.enabledbooleanfalseEnables Cosmos-Reason2-8B Vision Language Model for improved reasoning quality. Model size: ~16GB. Larger model with better spatial-temporal understanding than 2B.
app.pipelines.useNvidiaCosmos.modelsReason.reason8B.autoRegisterWithVAMSbooleantrueAutomatically registers the Reason 8B pipeline during deployment.
app.pipelines.useNvidiaCosmos.modelsReason.reason8B.autoTriggerOnFileExtensionsUploadstring""Comma-separated file extensions to auto-trigger on upload. Leave empty to disable.
app.pipelines.useNvidiaCosmos.modelsReason.reason8B.instanceTypesarray["g6e.12xlarge", "g6e.24xlarge"]EC2 GPU instance types for AWS Batch compute (BEST_FIT_PROGRESSIVE). Requires 32GB+ VRAM per GPU. g5 instances (A10G, 24GB VRAM) are not supported for the 8B model.
app.pipelines.useNvidiaCosmos.modelsReason.reason8B.maxVCpusnumber192Maximum vCPUs for the AWS Batch compute environment.

NVIDIA Cosmos Transfer (app.pipelines.useNvidiaCosmos.modelsTransfer)

NVIDIA Cosmos Transfer model for video transformation with control signal conditioning. Supports style transfer and content transformation using edge, depth, segmentation, or visual blur control signals. Requires VPC and internet access for HuggingFace model downloads. Shares the same EFS model cache and HuggingFace token as Cosmos Predict and Reason pipelines.

FieldTypeDefaultDescription
app.pipelines.useNvidiaCosmos.modelsTransfer.transfer2B.enabledbooleanfalseEnables Cosmos-Transfer2.5-2B for video transformation with control signal conditioning. Model size: ~20GB. Additional dependencies: VideoDepthAnything (~2GB), SAM2 (~5GB).
app.pipelines.useNvidiaCosmos.modelsTransfer.transfer2B.autoRegisterWithVAMSbooleantrueAutomatically registers the Transfer 2B pipeline during deployment.
app.pipelines.useNvidiaCosmos.modelsTransfer.transfer2B.autoTriggerOnFileExtensionsUploadstring""Comma-separated file extensions to auto-trigger on upload (e.g., ".mp4,.mov"). Leave empty to disable.
app.pipelines.useNvidiaCosmos.modelsTransfer.transfer2B.instanceTypesarray["g6e.48xlarge", "p5.48xlarge"]EC2 GPU instance types for AWS Batch compute (BEST_FIT_PROGRESSIVE). g6e.48xlarge (8x L40S 48GB) is the recommended default. p5.48xlarge (8x H100 80GB) as fallback. Note: p4d.24xlarge is not supported due to older CUDA driver incompatibilities with the Transfer 2.5 runtime.
app.pipelines.useNvidiaCosmos.modelsTransfer.transfer2B.maxVCpusnumber192Maximum vCPUs for the AWS Batch compute environment (g6e.48xlarge and p5.48xlarge both have 192 vCPUs).

NVIDIA Cosmos 3 (app.pipelines.useNvidiaCosmos3)

NVIDIA Cosmos 3 omnimodal world foundation models (Nano 16B, Super 64B) for generating images and videos from text prompts (text2image, text2video) or from images (image2video). Requires VPC and internet access for HuggingFace model downloads. Models are cached on Amazon EFS with Amazon S3 backup.

Implemented by

Construct: infra/lib/nestedStacks/pipelines/genAi/nvidia/cosmos/constructs/cosmos3-construct.ts (Cosmos3Construct), instantiated by the Cosmos nested stack infra/lib/nestedStacks/pipelines/genAi/nvidia/cosmos/cosmosBuilder-nestedStack.ts (CosmosBuilderNestedStack) — AWS Batch on GPU instances.

FieldTypeDefaultDescription
app.pipelines.useNvidiaCosmos3.enabledbooleanfalseEnables the Cosmos 3 pipeline.
app.pipelines.useNvidiaCosmos3.huggingFaceTokenstring""HuggingFace Read access token value (e.g., hf_xxxx). CDK stores this in AWS Secrets Manager during deployment. Must have access to all Cosmos3 models. Required when enabled.
app.pipelines.useNvidiaCosmos3.useCodeBuildbooleanfalseBuild container image via AWS CodeBuild + ECR instead of local Docker. Recommended for large GPU images. When false, uses inline CDK DockerImageAsset (requires local Docker). CodeBuild builds run asynchronously and outlive the deployment: the stack reports success as soon as the build is STARTED, so a green deploy does not mean the image exists. The pipeline is registered regardless, so a failed build leaves a selectable pipeline whose jobs cannot start — check the CodeBuild project name in the CDK stack outputs before running it.
app.pipelines.useNvidiaCosmos3.useWarmInstancesbooleanfalseKeeps GPU instances running when idle for faster pipeline starts. Applies to the Nano tier only, and only when a Nano model is enabled — the Super tier's compute environment always scales to zero. Warm instances incur continuous GPU compute cost.
app.pipelines.useNvidiaCosmos3.warmInstanceCountnumber1Number of warm Nano-tier GPU instances to keep running when useWarmInstances is true. Counted as 48 vCPUs each, which is one g6e.12xlarge; a larger configured instance type yields proportionally fewer instances.
app.pipelines.useNvidiaCosmos3.modelsOmni.nano16B.enabledbooleanfalseEnables Cosmos3-Nano 16B model for text2image, text2video, and image2video. Model size: ~35 GB.
app.pipelines.useNvidiaCosmos3.modelsOmni.nano16B.autoRegisterWithVAMSbooleantrueAutomatically registers the Nano 16B pipeline during deployment.
app.pipelines.useNvidiaCosmos3.modelsOmni.nano16B.autoTriggerOnFileExtensionsUploadstring""Comma-separated file extensions to auto-trigger on upload (e.g., ".jpg,.png"). Leave empty to disable.
app.pipelines.useNvidiaCosmos3.modelsOmni.nano16B.instanceTypesarray["g6e.12xlarge", "g6e.24xlarge", "g6e.48xlarge"]EC2 GPU instance types for AWS Batch compute (BEST_FIT_PROGRESSIVE). Each must carry at least 4 GPUs with 48GB+ VRAM; a type with fewer is rejected at synthesis.
app.pipelines.useNvidiaCosmos3.modelsOmni.nano16B.maxVCpusnumber192Maximum vCPUs for the AWS Batch compute environment.
app.pipelines.useNvidiaCosmos3.modelsOmni.super64B.enabledbooleanfalseEnables Cosmos3-Super 64B omnimodal model for text2image, text2video, and image2video. Model size: ~133 GB.
app.pipelines.useNvidiaCosmos3.modelsOmni.super64B.autoRegisterWithVAMSbooleantrueAutomatically registers the Super 64B pipeline during deployment.
app.pipelines.useNvidiaCosmos3.modelsOmni.super64B.autoTriggerOnFileExtensionsUploadstring""Comma-separated file extensions to auto-trigger on upload (e.g., ".jpg,.png"). Leave empty to disable.
app.pipelines.useNvidiaCosmos3.modelsOmni.super64B.instanceTypesarray["p5.48xlarge", "p5e.48xlarge", "p4de.24xlarge"]EC2 GPU instance types for AWS Batch compute (BEST_FIT_PROGRESSIVE). Requires 8x H100/H200/A100-80GB GPUs. Note: Super models require multi-GPU instances and will not fit on a single 80GB GPU.
app.pipelines.useNvidiaCosmos3.modelsOmni.super64B.maxVCpusnumber192Maximum vCPUs for the AWS Batch compute environment.
app.pipelines.useNvidiaCosmos3.modelsOmni.superText2Image64B.enabledbooleanfalseEnables Cosmos3-Super-Text2Image 64B model for high-quality text-to-image generation. Model size: ~133 GB.
app.pipelines.useNvidiaCosmos3.modelsOmni.superText2Image64B.autoRegisterWithVAMSbooleantrueAutomatically registers the Super-Text2Image 64B pipeline during deployment.
app.pipelines.useNvidiaCosmos3.modelsOmni.superText2Image64B.instanceTypesarray["p5.48xlarge", "p5e.48xlarge"]EC2 GPU instance types for AWS Batch compute (BEST_FIT_PROGRESSIVE). Requires 8x H100/H200 GPUs.
app.pipelines.useNvidiaCosmos3.modelsOmni.superText2Image64B.maxVCpusnumber192Maximum vCPUs for the AWS Batch compute environment.
app.pipelines.useNvidiaCosmos3.modelsOmni.superImage2Video64B.enabledbooleanfalseEnables Cosmos3-Super-Image2Video 64B model for high-quality image-to-video generation. Model size: ~133 GB.
app.pipelines.useNvidiaCosmos3.modelsOmni.superImage2Video64B.autoRegisterWithVAMSbooleantrueAutomatically registers the Super-Image2Video 64B pipeline during deployment.
app.pipelines.useNvidiaCosmos3.modelsOmni.superImage2Video64B.autoTriggerOnFileExtensionsUploadstring""Comma-separated file extensions to auto-trigger on upload (e.g., ".jpg,.png"). Leave empty to disable.
app.pipelines.useNvidiaCosmos3.modelsOmni.superImage2Video64B.instanceTypesarray["p5.48xlarge", "p5e.48xlarge", "p4de.24xlarge"]EC2 GPU instance types for AWS Batch compute (BEST_FIT_PROGRESSIVE). Requires 8x H100/H200/A100-80GB GPUs.
app.pipelines.useNvidiaCosmos3.modelsOmni.superImage2Video64B.maxVCpusnumber192Maximum vCPUs for the AWS Batch compute environment.
The three Super variants share one AWS Batch compute environment

Enabling more than one Super (64B) variant does not create a compute environment per variant. They share one environment and one job queue, and AWS Batch places a job on any instance type in that environment's pool, so the pool is the intersection of the enabled variants' instanceTypes — the types every enabled variant permits. With the defaults for super64B and superText2Image64B both enabled, the pool is ["p5.48xlarge", "p5e.48xlarge"]: p4de.24xlarge is excluded because superText2Image64B requires H100/H200 and does not list it.

Narrowing one variant therefore narrows the shared pool. If the enabled variants' lists have no type in common, deployment is rejected at synthesis — give them at least one type in common, or enable one Super variant per deployment.

maxVCpus behaves differently and is not shared in the same way: the environment takes the largest value among the enabled variants.

NVIDIA Gr00t Fine-Tuning (app.pipelines.useNvidiaGr00t)

NVIDIA Gr00t (GR00T-N1.5-3B) fine-tuning pipeline for embodied AI robot training. Uses LeRobot v2.1 datasets stored as VAMS assets. Operates at the asset level -- downloads the entire asset, looks for training data in a dataset/ subfolder (configurable), and outputs model checkpoints. Requires VPC and internet access for HuggingFace model downloads.

Implemented by

Nested stack: infra/lib/nestedStacks/pipelines/genAi/nvidia/gr00t/gr00tBuilder-nestedStack.ts (Gr00tBuilderNestedStack) — AWS Batch on GPU instances.

SettingTypeDefaultDescription
app.pipelines.useNvidiaGr00t.enabledbooleanfalseEnables the NVIDIA Gr00t fine-tuning pipeline.
app.pipelines.useNvidiaGr00t.huggingFaceTokenstring""HuggingFace Read access token value (e.g., hf_xxxx). CDK stores this in AWS Secrets Manager during deployment. Must have access to nvidia/GR00T-N1.5-3B. Required when enabled.
app.pipelines.useNvidiaGr00t.useCodeBuildbooleanfalseBuild container image via AWS CodeBuild + ECR instead of local Docker. Recommended for large GPU images. When false, uses inline CDK DockerImageAsset (requires local Docker). CodeBuild builds run asynchronously and outlive the deployment: the stack reports success as soon as the build is STARTED, so a green deploy does not mean the image exists. The pipeline is registered regardless, so a failed build leaves a selectable pipeline whose jobs cannot start — check the CodeBuild project name in the CDK stack outputs before running it.
app.pipelines.useNvidiaGr00t.useWarmInstancesbooleanfalseKeeps GPU instances running when idle for faster pipeline starts.
app.pipelines.useNvidiaGr00t.warmInstanceCountnumber1Number of warm GPU instances to keep running when useWarmInstances is true.
app.pipelines.useNvidiaGr00t.modelsFinetune.gr00tN1_5_3B.enabledbooleanfalseEnables GR00T-N1.5-3B fine-tuning.
app.pipelines.useNvidiaGr00t.modelsFinetune.gr00tN1_5_3B.autoRegisterWithVAMSbooleantrueAutomatically registers the fine-tuning pipeline during deployment.
app.pipelines.useNvidiaGr00t.modelsFinetune.gr00tN1_5_3B.instanceTypesarray["g6e.4xlarge", "g6e.12xlarge", "g5.12xlarge"]EC2 GPU instance types for AWS Batch compute (BEST_FIT_PROGRESSIVE). Multiple types listed for regional capacity flexibility. g6e.4xlarge (1 GPU) for LoRA, g6e.12xlarge (4 GPU) for full fine-tuning, g5.12xlarge as fallback.
app.pipelines.useNvidiaGr00t.modelsFinetune.gr00tN1_5_3B.maxVCpusnumber192Maximum vCPUs for the AWS Batch compute environment.

Deadline Cloud Execution Type (app.pipelines.deadlineCloudExecutionTypeEnabled)

Support for the DeadlineCloud pipeline execution type: workflow task states submit OpenJD jobs to an operator-owned AWS Deadline Cloud farm/queue via createJob, and a job-callback Lambda resolves the workflow's task token from Deadline Cloud job status events on the account's default Amazon EventBridge bus. Deadline Cloud pipelines are asynchronous only (callback required). Available only in the commercial AWS partition — configuration validation rejects it in AWS GovCloud, the AWS European Sovereign Cloud, and the AWS China and ISO partitions.

Enabling the type grants the VAMS workflow Lambdas the Deadline Cloud actions they call against the operator's farm, each scoped to the deployment's own account and Region: deadline:CreateJob to submit the job, deadline:GetJob for the job-callback Lambda to read its status, and deadline:UpdateJob to cancel a farm job that an aborted or failed execution would otherwise leave rendering. Both paths that cancel a job — the abort API and the failure reconciliation that stamps an execution's pipeline rows terminal — additionally hold deadline:ListJobs and deadline:GetJob, together with read access to the pipeline definitions the farm and queue are recorded on. That combination is how they reach a job still sitting queued with no worker: no status event has been delivered for such a job, so it is found by walking the queue for its reserved VamsPipelineExecutionId job parameter instead. With the setting false, none of these actions are granted.

VAMS does not create the farm, fleet, or queue. The operator supplies them, and they must satisfy the following:

  • The farm resides in the same account and Region as the VAMS deployment.
  • The queue service role has read access to the execution input locations and write access to the execution output prefixes in the asset bucket.
  • The fleet role grants logs:CreateLogStream and logs:PutLogEvents on arn:aws:logs:*:<account-id>:log-group:/aws/deadline/*, in addition to the worker permissions it already holds.
The AWS managed fleet-worker policy is not sufficient on its own

AWSDeadlineCloud-FleetWorker grants the worker agent's Deadline Cloud API calls but no Amazon CloudWatch Logs access. A fleet role without the two log actions above produces a failure that reports nothing useful: the worker agent passes CreateWorker and AssumeFleetRoleForWorker, then fails the CREATEDSTARTED transition with AccessDeniedException ... does not have sufficient access to perform CreateLogStream, because the service cannot create the worker's log stream.

The visible symptoms are indirect. The farm, fleet, and queue all report ACTIVE, createJob succeeds, and the VAMS execution simply never progresses until it times out. Behind that, the agent restarts every few seconds and the fleet replaces the instance every few minutes, so the account accrues charges and raises the fleet's worker-not-responding alarm — an alarm that describes worker health rather than the IAM permission causing it.

If Deadline Cloud pipeline executions hang and the fleet keeps replacing workers, check this permission before investigating capacity.

Implemented by

Lambda builder: infra/lib/lambdaBuilder/workflowFunctions.ts (buildDeadlineCloudJobCallbackFunction) — deployed in the API builder stack with an EventBridge rule on the default bus.

SettingTypeDefaultDescription
app.pipelines.deadlineCloudExecutionTypeEnabledbooleanfalseDeploys the Deadline Cloud job-callback Lambda + default-bus rule and grants the Deadline Cloud actions listed above.

Addons (app.addons)

Garnet Framework (app.addons.useGarnetFramework)

Integration with the Garnet Framework external knowledge graph for NGSI-LD data synchronization.

Implemented by

Nested stack: infra/lib/nestedStacks/addon/addonBuilder-nestedStack.ts (AddonBuilderNestedStack), which instantiates addon/garnetFramework/garnetFrameworkBuilder-nestedStack.ts (GarnetFrameworkBuilderNestedStack).

FieldTypeDefaultDescription
app.addons.useGarnetFramework.enabledbooleanfalseEnables Garnet Framework integration for automatic NGSI-LD indexing of all VAMS data changes.
app.addons.useGarnetFramework.garnetApiEndpointstring(required when enabled)Garnet Framework API endpoint URL (for example, https://XXX.execute-api.us-east-1.amazonaws.com). Must be a valid URL.
app.addons.useGarnetFramework.garnetApiTokenstring(required when enabled)API authentication token for the Garnet Framework.
app.addons.useGarnetFramework.garnetIngestionQueueSqsUrlstring(required when enabled)Amazon SQS queue URL for Garnet Framework data ingestion. Format: https://sqs.REGION.amazonaws.com/ACCOUNT/QUEUE_NAME.

Physna Sync (app.addons.usePhysnaSync)

One-way synchronization of supported VAMS files and metadata to a Physna tenant for geometric and semantic 3D search.

FieldTypeDefaultDescription
app.addons.usePhysnaSync.enabledbooleanfalseEnables the Physna Sync add-on.
app.addons.usePhysnaSync.tenantIdstring(required when enabled)Physna tenant UUID.
app.addons.usePhysnaSync.apiBaseEndpointstringhttps://app-api.physna.com/v3/Physna REST API base URL. Must end with /.
app.addons.usePhysnaSync.authTokenEndpointstringhttps://physna-app.auth.us-east-2.amazoncognito.com/oauth2/tokenOAuth2 token endpoint for Physna's Cognito user pool.
app.addons.usePhysnaSync.authTypestringcognitoAuthentication mode. Only cognito is supported in phase 1.
app.addons.usePhysnaSync.clientIdstring(required when enabled)Cognito client ID. VAMS creates the credentials secret and populates it at deploy time.
app.addons.usePhysnaSync.clientSecretstring(required when enabled)Cognito client secret. VAMS creates the credentials secret and populates it at deploy time without writing the value into the CloudFormation template.
app.addons.usePhysnaSync.credentialsSecretArnstring""Optional. ARN of an operator-managed AWS Secrets Manager secret holding { "clientId", "clientSecret" }. When set, VAMS imports that secret and clientId/clientSecret are ignored.

Provide the OAuth2 client credentials in one of two ways:

  • Inline clientId + clientSecret (default). Put the credentials directly in the configuration. VAMS creates the Secrets Manager secret during deployment and populates it via a custom resource whose Lambda carries the values in its code asset. Because CDK references code assets by content hash (uploaded to the CDK assets bucket), the credential value does not appear in the synthesized CloudFormation template or its resource properties — and no secret has to be created ahead of deployment.

    What this path does not do is confine the credential to Secrets Manager. It is present in the populate Lambda's deployment package, so a principal holding lambda:GetFunction on that function — part of the AWS managed ReadOnlyAccess policy — can download the package and read it, without the secretsmanager:GetSecretValue and kms:Decrypt the secret itself requires. The same plaintext is uploaded to the CDK assets bucket, and because CDK assets are content-addressed and not garbage collected, a credential stays readable there after it is rotated in configuration. Choose credentialsSecretArn when the credential must be reachable only through Secrets Manager.

  • credentialsSecretArn (operator-managed). Create the secret yourself with a JSON value of { "clientId": "...", "clientSecret": "..." } and reference it by ARN. VAMS imports the secret by ARN and ignores the inline clientId/clientSecret. No credential passes through synthesis on this path, so the populate custom resource is not created at all and the exposures described above do not arise. Use this when secret provisioning is centralized, when it must be managed outside the VAMS deployment, or when lambda:GetFunction is granted more widely than secret read.

    aws secretsmanager create-secret \
    --name my-vams-physna-credentials \
    --secret-string '{"clientId":"...","clientSecret":"..."}'
    # then set app.addons.usePhysnaSync.credentialsSecretArn to the returned ARN

Enabling the Physna Sync add-on also enables the in-app Physna add-on frontend features (currently the Physna Viewer plugin; more Physna-powered UI surfaces are planned). The backend emits a PHYSNA_ADDON feature flag in /api/secure-config whenever app.addons.usePhysnaSync.enabled is true, and the frontend consumes that flag to decide whether to surface Physna add-on features for supported file types. No separate configuration is required.

Physna Viewer tokens grant tenant-wide reach

The Physna Viewer plugin (GET /addon/physna/viewer) enforces VAMS two-tier authorization on the requested asset, then returns a Physna viewer token to the browser. Physna issues this token at tenant scope rather than per-asset (Physna does not currently support asset-scoped viewer tokens), so a user authorized to view one synced asset holds a token whose reach spans the Physna tenant for its lifetime. Treat access to the Physna Viewer feature as granting visibility into the connected Physna tenant, and scope the api and asset permissions for the viewer route accordingly.

Example configurations

For complete configuration examples, see the template files in the repository:

AWS GovCloud deployment

Key differences from the commercial template:

{
"app": {
"useFips": true,
"useWaf": true,
"useKmsCmkEncryption": { "enabled": true },
"govCloud": { "enabled": true, "il6Compliant": false },
"useGlobalVpc": {
"enabled": true,
"useForAllLambdas": false,
"addVpcEndpoints": true,
"vpcCidrRange": "10.1.0.0/16"
},
"openSearch": {
"useServerless": {
"enabled": false,
"nextGen": false,
"allowPublic": false,
"enableStandbyReplicas": false
},
"useProvisioned": { "enabled": true, "availabilityZoneCount": 2 }
},
"useLocationService": { "enabled": false },
"useAlb": {
"enabled": true,
"usePublicSubnet": false,
"domainHost": "vams.example.gov",
"certificateArn": "arn:aws-us-gov:acm:REGION:ACCOUNT:certificate/ID"
},
"useCloudFront": { "enabled": false },
"authProvider": {
"useCognito": { "enabled": true }
}
}
}

The GovCloud template uses a provisioned Amazon OpenSearch Service domain rather than Serverless: next-generation Serverless collections are unavailable in the partition, and configuration validation rejects openSearch.useServerless.nextGen when app.govCloud.enabled is true.

Running all Lambda functions inside the VPC

The GovCloud template sets useGlobalVpc.useForAllLambdas to false, so only the AWS Lambda functions that strictly require the VPC run inside it. Set useGlobalVpc.useForAllLambdas to true to place all VAMS Lambda functions inside the VPC (with the required VPC interface endpoints) when stricter network isolation is needed or the Lambda functions must reach specific VPC network components.

VPC is required for some features

Some features require a VPC and app.useGlobalVpc.enabled must be true when they are enabled. If one is enabled while app.useGlobalVpc.enabled is false, configuration validation fails with an error that lists the offending features; set app.useGlobalVpc.enabled to true (or disable those features). VPC-requiring features are: ALB deployment (useAlb), OpenSearch Provisioned (openSearch.useProvisioned), a private OpenSearch Serverless collection (openSearch.useServerless with allowPublic set to false), and the container-based pipelines (Potree viewer, 3D preview thumbnail, GenAI labeling, Gaussian splatting, coordinate transform, RapidPipeline ECS/EKS, ModelOps, Isaac Lab, NVIDIA Cosmos, NVIDIA Cosmos 3, NVIDIA Gr00t).

AWS European Sovereign Cloud deployment

The AWS European Sovereign Cloud (Region eusc-de-east-1, partition aws-eusc) is a separate, isolated partition. For now, deploy to it using the GovCloud guardrails: set app.govCloud.enabled = true so the same constraints are enforced (VPC required, no Amazon CloudFront, no Amazon Location Service). The European Sovereign Cloud Region currently exposes two Availability Zones, so a provisioned Amazon OpenSearch Service domain must set availabilityZoneCount to 2. Amazon OpenSearch Serverless is not offered in the partition at all, so openSearch.useServerless.enabled must be false and search runs on a provisioned domain.

Key differences from the commercial template (see config.template.eusovereign.json):

{
"env": { "region": "eusc-de-east-1" },
"app": {
"useWaf": true,
"useKmsCmkEncryption": { "enabled": true },
"govCloud": { "enabled": true, "il6Compliant": false },
"useGlobalVpc": {
"enabled": true,
"useForAllLambdas": false,
"addVpcEndpoints": true,
"vpcCidrRange": "10.1.0.0/16"
},
"openSearch": {
"useServerless": {
"enabled": false,
"nextGen": false,
"allowPublic": false,
"enableStandbyReplicas": false
},
"useProvisioned": { "enabled": true, "availabilityZoneCount": 2 }
},
"useLocationService": { "enabled": false },
"useAlb": {
"enabled": true,
"usePublicSubnet": false,
"domainHost": "vams.example.eu",
"certificateArn": "arn:aws-eusc:acm:REGION:ACCOUNT:certificate/ID"
},
"useCloudFront": { "enabled": false }
}
}
Running all Lambda functions inside the VPC

The European Sovereign Cloud template sets useGlobalVpc.useForAllLambdas to false, so only the AWS Lambda functions that strictly require the VPC run inside it. Set useGlobalVpc.useForAllLambdas to true to place all VAMS Lambda functions inside the VPC (with the required VPC interface endpoints) when stricter network isolation is needed or the Lambda functions must reach specific VPC network components.

Additional configuration files

Beyond config.json, VAMS supports several supplementary configuration files:

FilePurpose
infra/config/policy/s3AdditionalBucketPolicyConfig.jsonAdditional IAM policy statements applied to all Amazon S3 buckets. Controls presigned URL and STS credential access restrictions.
infra/config/policy/iamRoleConfig.jsonPre-created IAM role mappings for restricted environments. Read only when app.iamRoleConfig.useCustomBootstrapRoles or app.iamRoleConfig.useCustomVamsStackRoles is true.
infra/config/csp/cspAdditionalConfig.jsonAdditional Content Security Policy (CSP) sources for external APIs, scripts, images, media, fonts, and styles.
infra/config/saml-config.tsSAML identity provider settings for Amazon Cognito federation. Required when authProvider.useCognito.useSaml is true. See Security Architecture.
infra/config/oidc-config.tsOIDC identity provider settings for Amazon Cognito federation. Enable with useCognito.useOidc: true in config.json and configure provider details (client ID, issuer URL, attribute mapping, displayName). Client secret stored in AWS Secrets Manager.
infra/config/docker/Dockerfile-customDependencyBuildConfigCustom Docker build configuration for Lambda layer packaging. Useful for adding custom SSL certificates for HTTPS proxy environments.
infra/cdk.json (environments.common)Key-value pairs applied as tags on all stack resources.
infra/cdk.json (environments.aws)PermissionBoundaryArn and IamRoleNamePrefix for IAM role customization.

CDK environment settings (infra/cdk.json)

The infra/cdk.json file supports two environment configuration sections that apply additional controls to the deployed stack.

Resource tagging (environments.common)

Any non-empty key-value pair added to the environments.common object is applied as a tag on all resources deployed in the VAMS core stack. This is useful for cost allocation, organizational tagging, and compliance tracking.

{
"context": {
"environments": {
"common": {
"SolutionName": "AWSVisualAssetManagementSystem",
"Owner": "your-team",
"CostCenter": "12345",
"BusinessUnit": "Engineering"
}
}
}
}

IAM role customization (environments.aws)

The following settings control IAM role naming and permission boundaries for all roles created by the VAMS core stack:

FieldTypeDefaultDescription
PermissionBoundaryArnstring""ARN of an IAM permission boundary to apply to all roles created by the VAMS core stack. Leave empty to skip permission boundaries.
IamRoleNamePrefixstring""Prefix string applied to all newly created IAM role names.
Role name length limit

The total IAM role name character count limit is 64 characters. Long prefixes may affect role name uniqueness and cause deployment failures. Prefixes of 8 characters or fewer are recommended.

{
"context": {
"environments": {
"aws": {
"PermissionBoundaryArn": "arn:aws:iam::123456789012:policy/MyBoundary",
"IamRoleNamePrefix": "VAMS"
}
}
}
}

Advanced IAM role customization (app.iamRoleConfig)

Some organizations centrally provision IAM roles and do not allow deployment processes to create them. VAMS supports two independent, opt-in mechanisms for these environments. Both are disabled by default; when both are off, VAMS manages all IAM roles itself, which is the recommended approach because grants stay automatically in sync with the resources they protect.

Each mechanism is toggled by a boolean in config.json under app.iamRoleConfig, while the actual mappings (role ARNs, construct-path-to-role-name maps) live in the separate infra/config/policy/iamRoleConfig.json file. This keeps the verbose values out of the main configuration and lets a central IAM team own that file.

app.iamRoleConfig flagMappings source (section in iamRoleConfig.json)Controls
useCustomBootstrapRolesbootstrapThe CDK bootstrap roles assumed during deployment (deploy, CloudFormation execution, lookup, file/image publishing).
useCustomVamsStackRolesvamsStacksThe application roles VAMS constructs create inside the stacks (Lambda execution roles, and so on).
info
How this relates to environments.aws

The environments.aws settings in cdk.json (role name prefix and permission boundary) constrain roles that VAMS creates. app.iamRoleConfig instead lets VAMS avoid creating bootstrap and/or application roles by pointing at pre-created ones. The two are complementary: use environments.aws when VAMS may create roles within guardrails, and app.iamRoleConfig when it may not create them at all.

Bootstrap role customization (bootstrap)

By default, cdk bootstrap creates five roles per account and Region (for example, cdk-hnb659fds-deploy-role-<account>-<region>). When useCustomBootstrapRoles is true, VAMS configures its stack synthesizer from the bootstrap section. This applies to both the VAMS WAF stack and the VAMS core stack; nested stacks inherit the synthesizer from their parent automatically.

Field in bootstrapDescription
useCliCredentialsSynthesizerWhen true, no bootstrap IAM roles are used at all. Deployments run under the caller's own credentials and only require the staging bucket and ECR repo. Does not support cross-account deployments or CDK Pipelines.
qualifierBootstrap qualifier, if you bootstrapped with a non-default qualifier. Leave empty for the CDK default (hnb659fds).
deployRoleArnARN of the pre-created deploy role assumed by the CDK CLI. Empty fields fall back to the CDK default name.
cloudFormationExecutionRoleArnARN of the pre-created role AWS CloudFormation uses to execute the deployment.
lookupRoleArnARN of the pre-created role used for environment context lookups.
fileAssetPublishingRoleArnARN of the pre-created role used to publish file assets to the staging bucket.
imageAssetPublishingRoleArnARN of the pre-created role used to publish Docker image assets to the staging ECR repository.
fileAssetsBucketNameStaging bucket name, only if your customized bootstrap template renamed it.
imageAssetsRepositoryNameStaging ECR repository name, only if your customized bootstrap template renamed it.

Any field left empty keeps the corresponding CDK default. ARNs may use the ${AWS::Partition}, ${AWS::AccountId}, and ${AWS::Region} placeholders, which resolve at deployment time. To discover the required permissions for each role, export the default bootstrap template with cdk bootstrap --show-template > bootstrap-template.yaml and copy the role policies into your role-provisioning process.

Simpler middle ground

If your only concern is that the CloudFormation execution role gets AdministratorAccess by default, you do not need this feature. Instead bootstrap with cdk bootstrap --cloudformation-execution-policies <your-managed-policy-arns> and/or --custom-permissions-boundary <name>.

VAMS stack role customization (vamsStacks)

When useCustomVamsStackRoles is true, VAMS calls iam.Role.customizeRoles at the CDK app level. Because it is applied at the app level, a single IAM policy report covers the VAMS WAF stack, the core stack, and every nested stack.

Field in vamsStacksDescription
generateReportOnlyWhen true (discovery mode), VAMS still creates roles during synthesis but also writes iam-policy-report.txt and iam-policy-report.json to cdk.out. When false, role synthesis is prevented and any role not listed in precreatedRoles causes synthesis to fail.
precreatedRolesJSON object mapping each role's construct path to a pre-created IAM role name ("<construct path>": "<role name>"). The construct paths come from the generated report. See iamRoleConfig.json format below for a complete example.

Recommended workflow:

  1. Set useCustomVamsStackRoles to true and generateReportOnly to true in the vamsStacks section.
  2. Run cd infra && npx cdk synth. VAMS writes cdk.out/iam-policy-report.txt (and .json) listing every role it would create, each with its trust policy and required permissions.
  3. Hand the report to whoever pre-creates IAM roles in your organization. They create the roles outside of VAMS.
  4. Populate precreatedRoles with a "<construct path>": "<pre-created role name>" entry for every role in the report, then set generateReportOnly to false.
  5. Synthesize and deploy. Once every role is mapped, the synthesized templates reference the existing roles and contain no AWS::IAM::Role resources.
Map every role

With generateReportOnly set to false, synthesis fails if any role the constructs need is not present in precreatedRoles. Re-run the report whenever you enable a new VAMS feature or pipeline, since new features introduce new roles.

iamRoleConfig.json format

The precreatedRoles field is a JSON object (a map), not an array. Each key is the construct path of a role exactly as it appears in the generated iam-policy-report.txt (the value shown in parentheses after <missing role>), and each value is the name of the IAM role you pre-created in your account. The key is a path string, not an ARN; the value is a plain role name, not an ARN.

The report lists each role like this:

<missing role> (vams-core-prod-us-east-1/StorageResourcesBuilder/BucketNotificationsHandler050a0587b7544547bf325f094a3db834/Role)

You take the text in parentheses as the key and map it to your pre-created role name. A complete infra/config/policy/iamRoleConfig.json with mock values looks like this:

{
"bootstrap": {
"useCliCredentialsSynthesizer": false,
"qualifier": "",
"deployRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/my-org-cdk-deploy-role",
"cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/my-org-cdk-cfn-exec-role",
"lookupRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/my-org-cdk-lookup-role",
"fileAssetPublishingRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/my-org-cdk-file-publishing-role",
"imageAssetPublishingRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/my-org-cdk-image-publishing-role",
"fileAssetsBucketName": "",
"imageAssetsRepositoryName": ""
},
"vamsStacks": {
"generateReportOnly": false,
"precreatedRoles": {
"vams-core-prod-us-east-1/StorageResourcesBuilder/BucketNotificationsHandler050a0587b7544547bf325f094a3db834/Role": "my-org-vams-storage-bucketnotify-role",
"vams-core-prod-us-east-1/ApiBuilder/VAMSWorkflowIAMRole/Resource": "my-org-vams-workflow-role",
"vams-core-prod-us-east-1/AuthBuilder/Cognito/.../ServiceRole": "my-org-vams-auth-service-role",
"vams-waf-prod-us-east-1/Wafv2CF/.../ServiceRole": "my-org-vams-waf-service-role"
}
}
}
Keys are deployment-specific

The construct path keys begin with your full stack name (for example, vams-core-prod-us-east-1), which is derived from name, app.baseStackName, and the Region. If you change any of those values, the keys change and the report must be regenerated. Always copy the exact paths from your own iam-policy-report.txt rather than from this example. The values (my-org-vams-* above) are placeholders for whatever role names your IAM team assigns.

Amazon S3 additional bucket policy (infra/config/policy/s3AdditionalBucketPolicyConfig.json)

This file allows you to add an additional JSON-formatted IAM policy statement that is applied to all Amazon S3 buckets created by VAMS. The Resource field in the policy statement is automatically overridden at deployment time to reference each respective bucket and its objects. An empty file means no additional policy statement is added beyond the default TLS enforcement.

This configuration also controls the ability to allow or deny access to presigned Amazon S3 URLs and AWS STS credentials that VAMS generates for asset upload and download operations.

ViaAWSService condition

When restricting access, add an aws:ViaAWSService condition set to false to restrict only direct user calls, since AWS services also need to access these buckets internally.

The following examples demonstrate common bucket policy patterns. See the AWS Knowledge Center article on restricting S3 traffic for additional guidance.

Restrict access outside of a VPC interface endpoint:

{
"Sid": "VPCe",
"Action": "s3:*",
"Effect": "Deny",
"Resource": ["*"],
"Condition": {
"StringNotEquals": {
"aws:SourceVpce": ["vpce-XXXXXXXX", "vpce-YYYYYYYY"]
},
"BoolIfExists": { "aws:ViaAWSService": "false" }
},
"Principal": "*"
}

Restrict access outside of a VPC private IP range:

{
"Sid": "VpcSourceIp",
"Action": "s3:*",
"Effect": "Deny",
"Resource": ["*"],
"Condition": {
"NotIpAddressIfExists": {
"aws:VpcSourceIp": ["10.1.1.1/32", "172.1.1.1/32"]
},
"BoolIfExists": { "aws:ViaAWSService": "false" }
},
"Principal": "*"
}

Restrict access outside of a source IP range:

{
"Sid": "SourceIP",
"Action": "s3:*",
"Effect": "Deny",
"Resource": ["*"],
"Condition": {
"NotIpAddressIfExists": {
"aws:SourceIp": ["11.11.11.11/32", "22.22.22.22/32"]
},
"BoolIfExists": { "aws:ViaAWSService": "false" }
},
"Principal": "*"
}

Content Security Policy (infra/config/csp/cspAdditionalConfig.json)

VAMS supports configurable Content Security Policy (CSP) settings through this JSON file. This allows organizations to add their specific external API endpoints and resources without modifying core code.

The file supports the following categories:

CategoryDescription
connectSrcExternal APIs and services the application can connect to via XMLHttpRequest, WebSocket, EventSource
scriptSrcExternal JavaScript libraries or CDNs that can be executed
workerSrcWeb Worker and Service Worker sources
imgSrcExternal image sources that can be loaded
mediaSrcExternal media sources (audio/video) that can be loaded
fontSrcExternal font sources (for example, Google Fonts)
styleSrcExternal stylesheet sources that can be loaded

Behavior:

  • File not found -- VAMS uses default CSP settings without failing the build.
  • Invalid JSON -- Logs a warning and uses default CSP settings.
  • Empty arrays -- Ignored; only default CSP sources are used for those categories.
  • Duplicate prevention -- Additional sources are merged with existing ones, avoiding duplicates.
CSP security

Only add trusted domains to your CSP configuration. Avoid using wildcards (*) as they compromise security. Regularly audit your CSP configuration and test changes in a development environment before deploying to production.