Skip to main content

Authorization API

The Authorization API provides endpoints for managing permission constraints, roles, user-role assignments, Cognito user management, and API keys. These resources control access to all VAMS functionality through a two-tier Casbin ABAC/RBAC authorization model.

Two-tier authorization

VAMS enforces authorization at two levels:

  • Tier 1 (API-level): Controls which API routes a role can access.
  • Tier 2 (Object-level): Controls which data entities (databases, assets, pipelines, etc.) a role can access.

Both tiers must allow access for a request to succeed.

Free-text whitespace

Surrounding whitespace is removed from a submitted description before the length constraint is applied and before the value is stored, so a subsequent read returns the trimmed value. A padded value whose trimmed length falls below the documented minimum is rejected with 400. Interior whitespace is preserved.


Constraints

Constraints define the authorization policies that determine what actions users and groups can perform on specific resource types.

List constraints

Retrieves all permission constraints.

GET /auth/constraints

Query parameters

ParameterTypeRequiredDefaultDescription
maxItemsnumberNo30000Ceiling on the constraints returned in one response (1-30000).
pageSizenumberNo3000Constraints per page (1-10000). A value above 3000 is served in 3000-item pages.
startingTokenstringNonullPagination token from a previous response's NextToken.

The page served is the smallest of pageSize, maxItems, and 3,000 — the bound that keeps a page of whole constraints, each carrying its criteria and permission lists, within the AWS Lambda response limit.

Response

NextToken is present only when more constraints remain; page until it is absent. It is an opaque string: pass it back on startingToken unmodified.

{
"message": {
"Items": [
{
"constraintId": "admin-full-access",
"name": "Admin Full Access",
"description": "Full access to all resources",
"objectType": "asset",
"criteriaAnd": [{ "field": "databaseId", "value": ".*", "operator": "contains" }],
"criteriaOr": [],
"groupPermissions": [
{ "groupId": "admin-role", "permission": "GET", "permissionType": "allow" }
],
"userPermissions": []
}
],
"NextToken": "eyJ..."
}
}

Error responses

StatusDescription
400startingToken is not a token this listing emitted
403Not authorized
500Internal server error

Get a constraint

Retrieves a specific constraint by ID.

GET /auth/constraints/{constraintId}

Path parameters

ParameterTypeRequiredDescription
constraintIdstringYesConstraint identifier

Create a constraint

Creates a new permission constraint.

POST /auth/constraints/{constraintId}

Path parameters

ParameterTypeRequiredDescription
constraintIdstringYesUnique constraint identifier

Request body

FieldTypeRequiredDescription
namestringYesHuman-readable name for the constraint
descriptionstringYesDescription of the constraint's purpose
objectTypestringYesResource type this constraint applies to (e.g., asset, database, pipeline, workflow, api, web, tag, tagType, role, userRole, metadataSchema)
criteriaAndarrayNoAND criteria for matching resources (all must match)
criteriaOrarrayNoOR criteria for matching resources (at least one must match)
groupPermissionsarrayYesPermissions granted to roles/groups
userPermissionsarrayNoPermissions granted to specific users

Each entry in groupPermissions:

FieldTypeRequiredDescription
groupIdstringYesRole/group name
permissionstringYesHTTP action (GET, PUT, POST, DELETE)
permissionTypestringYesallow or deny

Each entry in criteriaAnd or criteriaOr:

FieldTypeRequiredDescription
fieldstringYesField to match (e.g., databaseId, assetType)
valuestringYesValue to match against (supports * wildcard)
operatorstringYesComparison operator (equals, contains, etc.)
Combining AND and OR criteria

A constraint may define both criteriaAnd and criteriaOr. When both are present, access is granted only if all criteriaAnd entries match and at least one criteriaOr entry matches.

Request body example

{
"name": "Database Reader",
"description": "Read-only access to assets in the production database",
"objectType": "asset",
"criteriaAnd": [
{
"field": "databaseId",
"value": "production-db",
"operator": "equals"
}
],
"criteriaOr": [],
"groupPermissions": [
{
"groupId": "viewer-role",
"permission": "GET",
"permissionType": "allow"
}
],
"userPermissions": []
}

Response

{
"success": true,
"message": "Constraint database-reader created/updated successfully",
"constraintId": "database-reader",
"operation": "create",
"timestamp": "2026-03-15T10:30:00.000000",
"constraint": "{\"identifier\": \"database-reader\", \"name\": \"Database Reader\", \"description\": \"Read-only access to assets in the production database\", \"objectType\": \"asset\", \"criteriaAnd\": [{\"field\": \"databaseId\", \"value\": \"production-db\", \"operator\": \"equals\"}], \"groupPermissions\": [{\"groupId\": \"viewer-role\", \"permission\": \"GET\", \"permissionType\": \"allow\"}]}"
}

Update a constraint

Updates an existing constraint.

PUT /auth/constraints/{constraintId}

Path parameters

ParameterTypeRequiredDescription
constraintIdstringYesConstraint identifier

Request body

Same structure as Create a constraint.


Delete a constraint

Deletes a permission constraint.

DELETE /auth/constraints/{constraintId}

Path parameters

ParameterTypeRequiredDescription
constraintIdstringYesConstraint identifier

Response

{
"success": true,
"message": "Constraint database-reader deleted successfully",
"constraintId": "database-reader",
"operation": "delete",
"timestamp": "2026-03-15T10:30:00.000000"
}

Import constraint template

Imports a constraint configuration from a JSON template file. This is useful for bulk-provisioning permissions.

POST /auth/constraintsTemplateImport

Request body

The request body should contain the full constraint template JSON. See the permission templates in documentation/permissionsTemplates/ for examples.

Response

{
"message": "Template imported successfully"
}

List constraint permission objects

Retrieves the master mapping used when authoring constraints: the object types (with the fields valid on each), the criteria operators, the permissions (HTTP actions), and the permission types. The constraints editor and CLI use this as the authoritative source for objectType, criteria field, operator, permission, and permissionType values.

GET /auth/constraints/permissionObjects

Response

{
"message": {
"objectTypes": [
{
"label": "Asset",
"value": "asset",
"fields": [
{ "label": "Database ID", "value": "databaseId" },
{ "label": "Asset Name", "value": "assetName" },
{ "label": "Asset Type", "value": "assetType" },
{ "label": "Tags", "value": "tags" }
]
}
],
"operators": [{ "label": "Equals", "value": "equals" }],
"permissions": [{ "label": "View/GET", "value": "GET" }],
"permissionTypes": [{ "label": "Allow", "value": "allow" }]
}
}
Authoritative field matrix

A constraint criterion whose field is not valid for its objectType is rejected at create/update and template import, and out-of-matrix or deprecated fields are ignored during authorization evaluation.

Error responses

StatusDescription
403Not authorized
500Internal server error

API route listing

These endpoints expose the deployment's API route surface from the master route definitions. They are useful when authoring API authorization constraints (route__path values) and for discovering which endpoints a user can call.

List all API routes

Retrieves the full list of VAMS API endpoint routes with their HTTP methods and categories.

GET /auth/routes/api

Response

{
"routes": [
{
"path": "/database/{databaseId}/assets",
"methods": ["GET"],
"category": "assets",
"unauthenticated": false
}
]
}

Error responses

StatusDescription
403Not authorized
500Internal server error

List allowed API routes

Retrieves the API routes (and the HTTP methods on each) that the requesting user is authorized to call, evaluated against the user's authorization constraints. Routes with no allowed methods are omitted.

GET /auth/routes/api/allowed

Response

{
"routes": [
{
"path": "/database/{databaseId}/assets",
"methods": ["GET"],
"category": "assets"
}
],
"userId": "user@example.com"
}

Error responses

StatusDescription
403Not authorized
500Internal server error

Roles

Roles are named groups that can be assigned to users. Constraints reference roles via groupPermissions to grant or deny access.

List roles

Retrieves all roles.

GET /roles

Response

{
"message": {
"Items": [
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"roleName": "admin",
"description": "Full administrative access",
"createdOn": "2026-03-15T10:30:00",
"source": null,
"sourceIdentifier": null,
"mfaRequired": false
}
]
}
}

Create a role

Creates a new role.

POST /roles

Request body

FieldTypeRequiredDescription
roleNamestringYesUnique role name
descriptionstringYesRole description
sourcestringNoRole source (e.g. INTERNAL_SYSTEM)
sourceIdentifierstringNoIdentifier associated with the source
mfaRequiredbooleanNoWhen true, the role's constraints apply only to MFA sessions

Request body example

{
"roleName": "viewer",
"description": "Read-only access to assets and databases"
}

Response

{
"success": true,
"message": "Role viewer created successfully",
"roleName": "viewer",
"operation": "create",
"timestamp": "2026-03-15T10:30:00.000000"
}

Update a role

Updates an existing role.

PUT /roles

Request body

Same fields as Create a role, with roleName the only required one. It identifies the role and cannot be changed.

Only the fields present in the body are written. A field the body omits keeps its stored value, so clearing one requires sending it explicitly — "mfaRequired": false to remove an MFA requirement, or "source": null to remove the source linkage. description is the exception: it is always present on a role, so null is rejected and omitting the field is how it is left alone.

A body naming only roleName is rejected with 400, since it asks for no change.


Delete a role

Deletes a role.

DELETE /roles/{roleId}

Path parameters

ParameterTypeRequiredDescription
roleIdstringYesRole name to delete
warning

Deleting a role does not automatically remove user-role assignments referencing this role. Clean up user-role assignments before or after deleting the role.

Response

{
"message": "success"
}

User-role assignments

User-role assignments link users to roles. A user can have multiple roles, and each role's constraints combine to determine the user's effective permissions.

List user-role assignments

Retrieves all user-role assignments.

GET /user-roles

Response

{
"message": {
"Items": [
{
"userId": "user@example.com",
"roleName": ["admin", "viewer"],
"createdOn": "2026-03-15T10:30:00"
}
]
}
}

Assign a role to a user

Creates a new user-role assignment.

POST /user-roles

Request body

FieldTypeRequiredDescription
userIdstringYesUser identifier
roleNamearrayYesOne or more role names to assign

Request body example

{
"userId": "user@example.com",
"roleName": ["viewer"]
}

Response

{
"success": true,
"message": "User roles created successfully",
"userId": "user@example.com",
"operation": "create",
"timestamp": "2026-03-15T10:30:00.000000"
}

Update a user-role assignment

Updates an existing user-role assignment.

PUT /user-roles

Request body

Same structure as Assign a role to a user.


Remove all roles from a user

Removes every role assignment for a user.

DELETE /user-roles

Request body

FieldTypeRequiredDescription
userIdstringYesUser identifier
Removes all roles

This endpoint deletes all role assignments for the given userId. It does not accept a roleName, so there is no way to remove a single role through it. To leave the user with a subset of their roles, use PUT /user-roles with the desired role list instead.

Request body example

{
"userId": "user@example.com"
}

Response

{
"success": true,
"message": "User roles deleted successfully",
"userId": "user@example.com",
"operation": "delete",
"timestamp": "2026-03-15T10:30:00.000000"
}

Cognito user management

These endpoints manage users in the Amazon Cognito user pool. They are only available when Cognito authentication is enabled in the deployment.

Cognito required

These endpoints return 400 with the message Cognito user management is not available when Cognito is not enabled in the deployment configuration (app.authProvider.useCognito.enabled).

List Cognito users

GET /user/cognito

Query parameters

ParameterTypeRequiredDefaultDescription
maxItemsnumberNo60Maximum number of users to return (1-60).
pageSizenumberNo60Number of users per page (1-60). Takes precedence over maxItems.
startingTokenstringNonullPagination token from a previous response's NextToken.

Response

NextToken is present only when more users remain; page until it is absent.

{
"users": [
{
"userId": "user@example.com",
"email": "user@example.com",
"phone": "+12345678900",
"userStatus": "CONFIRMED",
"enabled": true,
"userCreateDate": "2026-03-15T10:30:00",
"userLastModifiedDate": "2026-03-15T10:30:00",
"mfaEnabled": false
}
],
"NextToken": "eyJ..."
}

Create a Cognito user

POST /user/cognito

Request body

FieldTypeRequiredDescription
userIdstringYesUsername for the new user
emailstringYesEmail address
phonestringNoPhone number in E.164 format (e.g. +12345678900)

Request body example

{
"userId": "newuser@example.com",
"email": "newuser@example.com",
"phone": "+12345678900"
}

Update a Cognito user

PUT /user/cognito/{userId}

Path parameters

ParameterTypeRequiredDescription
userIdstringYesUser identifier

Request body

FieldTypeRequiredDescription
emailstringNoUpdated email address
phonestringNoPhone number in E.164 format (e.g. +12345678900)
clearPhonebooleanNoSet to true to remove the stored phone number

At least one of email, phone, or clearPhone must be provided.

The update is partial: an attribute the request does not mention keeps its stored value, so an email-only request leaves the phone number as it is. Removing the number takes clearPhone set to true, which is accepted on its own or alongside an email change. A request that sends both phone and clearPhone is rejected with 400.


Delete a Cognito user

DELETE /user/cognito/{userId}

Path parameters

ParameterTypeRequiredDescription
userIdstringYesUser identifier to delete

Reset a user's password

Sends a password reset to the specified Cognito user.

POST /user/cognito/{userId}/resetPassword

Path parameters

ParameterTypeRequiredDescription
userIdstringYesUser identifier

Request body

The request body is required and must set confirmReset to true. A request that omits the body, sends an empty one, or sends the field as false or null is rejected with 400 and does not reach Amazon Cognito.

FieldTypeRequiredDescription
confirmResetbooleanYesMust be true

Response

{
"success": true,
"message": "Password reset successfully for user user@example.com. A new temporary password has been sent to their email.",
"userId": "user@example.com",
"operation": "resetPassword",
"timestamp": "2026-03-15T10:30:00.000000"
}

API keys

API keys provide programmatic access to VAMS without requiring interactive authentication. A request that presents an API key acts as the VAMS user the key is bound to and carries the roles assigned to that user.

The /auth/api-keys routes are the administrative variant of these endpoints. They operate across every user's keys, and POST /auth/api-keys binds the new key to the userId supplied in the request body. Of the default roles, only admin reaches them; basicReadOnly is granted the self-service /auth/user/api-keys routes instead.

Administrative routes

Because POST /auth/api-keys accepts any userId, including an administrator's, a role that can call it can issue a credential that acts as any user in the deployment. Access to the /auth/api-keys routes is therefore equivalent to full administrative access. Grant them only to administrator roles, and give other users the self-service /auth/user/api-keys routes for managing their own keys.

List API keys

GET /auth/api-keys

Query parameters

ParameterTypeRequiredDefaultDescription
maxItemsnumberNo3000Maximum number of keys in one response (1-3000). Values above 3000 are clamped.
pageSizenumberNo1000Number of keys read per page. Clamped to maxItems.
startingTokenstringNonullPagination token from a previous response's NextToken.

Response

NextToken and truncated are present only when more keys remain; page until they are absent. A malformed or foreign startingToken returns 400 with Invalid pagination token.

{
"Items": [
{
"apiKeyId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"apiKeyName": "CI/CD Pipeline Key",
"description": "Automation key for the deployment pipeline",
"userId": "service-account@example.com",
"createdBy": "admin@example.com",
"createdAt": "2026-03-15T10:30:00+00:00",
"updatedAt": "2026-03-15T10:30:00+00:00",
"expiresAt": "2027-03-15T10:30:00Z",
"isActive": "true"
}
],
"NextToken": "eyJ...",
"truncated": true
}
note

The API key secret value is only returned once during creation and cannot be retrieved afterwards.

A bounded page can be empty

DynamoDB reports a continuation key whenever a read stops at its limit, so a listing whose size is an exact multiple of the page bound ends with a NextToken and an empty Items array. Treat an absent NextToken, not an empty page, as the end of the listing.


Get a specific API key

GET /auth/api-keys/{apiKeyId}

Path parameters

ParameterTypeRequiredDescription
apiKeyIdstringYesAPI key identifier

Create an API key

Creates an API key bound to the userId in the request body. The key acts as that user and carries that user's roles, which makes this an administrative route.

POST /auth/api-keys

Request body

FieldTypeRequiredDescription
apiKeyNamestringYesDisplay name for the API key
userIdstringYesUser the key acts as; any user with a role assignment
descriptionstringYesDescription of the API key
expiresAtstringNoExpiration date (ISO 8601)

Request body example

{
"apiKeyName": "CI/CD Pipeline Key",
"userId": "service-account@example.com",
"description": "Automation key for the deployment pipeline",
"expiresAt": "2027-03-15T10:30:00Z"
}

Response

{
"apiKeyId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"apiKeyName": "CI/CD Pipeline Key",
"description": "Automation key for the deployment pipeline",
"userId": "service-account@example.com",
"createdBy": "admin@example.com",
"createdAt": "2026-03-15T10:30:00+00:00",
"updatedAt": "2026-03-15T10:30:00+00:00",
"expiresAt": "2027-03-15T10:30:00Z",
"isActive": "true",
"apiKey": "vams_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
Store the secret securely

The plaintext apiKey value is only returned during creation. Store it securely -- it cannot be retrieved again.


Update an API key

PUT /auth/api-keys/{apiKeyId}

Path parameters

ParameterTypeRequiredDescription
apiKeyIdstringYesAPI key identifier

Request body

FieldTypeRequiredDescription
descriptionstringNoUpdated description
expiresAtstringNoUpdated expiration date (ISO 8601)
isActivestringNo"true" or "false" to enable/disable

At least one of description, expiresAt, or isActive must be provided. The API key name is immutable after creation.


Delete an API key

DELETE /auth/api-keys/{apiKeyId}

Path parameters

ParameterTypeRequiredDescription
apiKeyIdstringYesAPI key identifier

Response

{
"message": "API key deleted successfully"
}

User (self-service) API keys

The /auth/user/api-keys routes are the self-service variant of the API key endpoints. They allow users to manage their own keys without administrative access:

  • All operations are scoped to keys owned by the requesting user. Other users' keys are never listed, and direct access to them returns not-found.
  • Created keys are always tied to the authenticated caller -- there is no userId field.
  • An expiration date is required on creation and may be at most 365 days from creation.
  • Updates cannot clear the expiration and cannot set it beyond 365 days from the key's original creation date. After the window elapses, the user must create a new key (rotation).

The administrative routes (/auth/api-keys) cover every user's keys, accept a userId on creation, and treat the expiration date as optional. They are reserved for administrator roles.

List your API keys

GET /auth/user/api-keys

Returns the same response shape as the admin list, filtered to the requesting user's keys.

Query parameters

ParameterTypeRequiredDefaultDescription
maxItemsnumberNo3000Maximum number of keys in one response (1-3000). Values above 3000 are clamped.
pageSizenumberNo1000Number of keys read per page. Clamped to maxItems.
startingTokenstringNonullPagination token from a previous response's NextToken.

NextToken and truncated behave exactly as they do on GET /auth/api-keys, including the empty-final-page case.


Get one of your API keys

GET /auth/user/api-keys/{apiKeyId}

Path parameters

ParameterTypeRequiredDescription
apiKeyIdstringYesAPI key identifier

Create a self-service API key

POST /auth/user/api-keys

Request body

FieldTypeRequiredDescription
apiKeyNamestringYesDisplay name for the API key (immutable after creation)
descriptionstringYesDescription of the API key
expiresAtstringYesExpiration date (ISO 8601), at most 365 days from creation

Request body example

{
"apiKeyName": "My Automation Key",
"description": "Personal automation scripts",
"expiresAt": "2027-03-15T10:30:00Z"
}

The response matches the admin create response; the plaintext key is returned exactly once.


Update one of your API keys

PUT /auth/user/api-keys/{apiKeyId}

Request body

FieldTypeRequiredDescription
descriptionstringNoUpdated description
expiresAtstringNoUpdated expiration (within 365 days of key creation; cannot be cleared)
isActivestringNotrue or false to enable/disable the key

Delete one of your API keys

DELETE /auth/user/api-keys/{apiKeyId}

Deletes the key when it is owned by the requesting user; other users' keys return not-found.


  • Assets API -- Resources protected by these authorization policies
  • Pipelines API -- Pipeline access controlled by constraints
  • Workflows API -- Workflow access controlled by constraints