Policy Engine API

Authentication

Currently a customer can authenticate their requests using the same API access token as the customer uses when interacting with Vesper's /decision endpoint.

The Policy Engine API only authenticates the access token present in the Authorization request header.

Limits

  • A customer can have up to 10 policies.
  • A policy's text size is limited to 10KB.
  • A customer can have up to 10 external sets.
    • An external set can be 100KB where each:
    • Unsigned integer item is 4B,
    • IP address (IPv4 or IPv6) is 16B, or
    • String is variable length.
  • An inline set is limited to 250 items.

POST, PUT, and DELETE Responses

Unless otherwise noted, the service will respond to user requests with the following.

Successful Request Response (Status Code: 2xx)

{
    "ok": true
}

Bad Request Response (Status Code: 400)

{
    "ok": false,
    "errors": [
        {
            "message": "failed to unmarshal request body",
            "see_also": "this is optional if we can provide more specific reasons for the bad request"
        }
    ]
}

Not Found Response (Status Code: 404)

{
    "ok": false
}

Server Error Response (Status Code: 500)

{
    "ok": false
}

Policy Resource

A policy represents a named resource that contains the customer specified logic for determining Vesper's action response, such as allow, block, or something customer defined.

GET /v1/policies

Successful Response (Status Code: 200)

{
    "policies": [
        {
            "id": "MyFirstPolicy",

            "version": 104,

            // Time in nanoseconds since UNIX epoch
            "last_modified": 12345678890,

            // Policy length in bytes
            "size": 123,

            // Is the policy enabled?
            "enabled": true
        },
        ...
    ]
}

Server Error Response (Status Code: 500)

The service does not respond with a body.

POST /v1/policies

Request

The service will validate the given policy and persists the policy under the id. policy should be written according the grammar defined in the DSL.

{
    // A string that corresponds to the optional policy_name property in the Vesper decision request
    "id": "MyPolicyName",

    // Should the policy be enabled at creation?  If "enabled" is undefined, it's assumed to be true.
    "enabled": false,

    // A string that is valid DSL syntax
    "policy": "version 1\nMyPolicyLabel: if request.ip in BadIPAddresses then block\ndefault allow"
}

Bad Request Response (Status Code: 400)

If the customer provides an invalid policy, the service will respond with a 400 and a list of line/column specific errors.

// policy: "hello world"
{
    "ok": false,
    "errors": [
        {
            "line": 1,
            "column": 6,
            "message": "mismatched input 'world' expecting ':'"
        }
    ]
}

If the customer attempts to a create a policy with the name of an existing policy, the service will response with a 400.

{
    "ok": false,
    "errors": [
        {
            "message": "policy already exists"
        }
    ]
}

Successful Response (Status Code: 201)

{
    "ok": true
}

POST /v1/policies?dryrun

The query parameter, ?dryrun, will only perform validation. If successful, the service will return status code 200.

GET /v1/policies/{policyName}

Successful Response (Status Code: 200)

{
    "id": "MyPolicyName",
    "policy": "version 1\nMyPolicyLabel: if request.ip in BadIPAddresses then block\ndefault allow",
    "last_modified": 12345678890,
    "size": 80
}

Not Found Response (Status Code: 404)

The service does not respond with a body.

Server Error Response (Status Code: 500)

The service does not respond with a body.

PUT /v1/policies/{policyName}

Request

enabled is not required, and policy can either be null, an empty string, or can be entirely excluded if only enabling/disabled the policy.

{
    // If "enabled" is undefined, the policy's enabled state will remain unchanged.
    "enabled": true,
    "version": 104,
    "policy": "version 1\ndefault allow"
}

Bad Request Response (Status Code: 400)

The service has the same response as POST /v1/policies?dryrun.

Successful Response (Status Code: 202)

{
    "ok": true
}

DELETE /v1/policies/{policyName}

Successful Response (Status Code: 204)

{
    "ok": true
}

Sets

A policy can reference externally defined sets of entities like IP addresses, ASNs, or arbitrary strings which are generally preferable over including them in the policy directly.

GET /v1/sets

Successful Response (Status Code: 200)

{
    "sets": [
        {
            // Set identifier is generally equivalent to https://developer.mozilla.org/en-US/docs/Glossary/Identifier (minus '$')
            "id": "MyFirstSet",

            // Set version
            "version": 104,

            // Entity type can be "ip", "string", or "uint" (unsigned integer)
            "entity_type": "ip",

            // Time in nanoseconds since UNIX epoch
            "last_modified": 12345678890,

            // Number of (unique) items in set
            "count": 3
        },
        ...
    ]
}

Server Error Response (Status Code: 500)

The service does not respond with a body.

POST /v1/sets

Request

{
    // A string that corresponds to the BadIPAddresses in a policy
    "id": "MyFirstSet",

    // Entity type can be "ip", "string", or "uint" (unsigned integer) and is immutable
    "entity_type": "ip",

    // Items is a deduplicated list of values
    "items": [
        "1.2.3.4",
        "5.6.7.8",
        "9.10.11.12"
    ]
}

Bad Request Response (Status Code: 400)

If the customer provided an invalid customer set, the service will respond with a 400 and a list of line/column specific errors.

{
    "ok": false,
    "errors": [
        // bad set name
        {
            "message": "invalid customer set name",
            "see_also": "https://developer.mozilla.org/en-US/docs/Glossary/Identifier (minus '$')"
        },
        // empty items: items: [] or items: null or no items property
        {
            "message": "null or empty set items specified",
        }
    ]
}

If the customer attempts to a create a set with the name of an existing set, the service will response with a 400.

{
    "ok": false,
    "errors": [
        {
            "message": "customer set already exists"
        }
    ]
}

Successful Response (Status Code: 201)

{
    "ok": true
}

GET /v1/sets/{setName}

Successful Response (Status Code: 200)

{
    "id": "MyFirstSet",
    "entity_type": "ip",
    "version": 104,
    "last_modified": 12345678890,
    "count": 3,
    "items": [
        "1.2.3.4",
        "5.6.7.8",
        "9.10.11.12"
    ]
}

Not Found Response (Status Code: 404)

The service does not respond with a body.

Server Error Response (Status Code: 500)

The service does not respond with a body.

PUT /v1/sets/{setName}

The customer can replace the items of an existing set with the specified items in the given set.

Request

entity_type and items are both required.

  • entity_type is "string", "ip", or "uint". entity_type must match the existing type.
    • To change the set's entity_type, the existing set must be deleted and then recreated with the new entity_type.
  • items is a non-empty array.
{
    "entity_type": "ip",
    "items": [
        "1.2.3.4",
        "13.14.15.16"
    ]
}

Bad Request Response (Status Code: 400)

The service has the same response as POST /v1/sets.

Successful Response (Status Code: 202)

{
    "ok": true
}

DELETE /v1/sets/{setName}

Successful Response (Status Code: 204)

{
    "ok": true
}