Skip to main content
Version: 1.x

Policy Service

wasmCloud hosts will always enforce a certain level of security by default that cannot be loosened. For example, hosts will always validate runtime links. Additionally, the wasmCloud policy service API can be used to extend and customize policy evaluation, such as by restricting untrusted application components and providers on particular hosts.

Policy evaluation flow

The policy service API provides a simple mechanism for communicating with an external policy server. External servers can be created using standard engines such as Open Policy Agent.

Once the wasmCloud policy service is enabled, the host will send policy requests on a dedicated NATS subject (for example, wasmcloud.policy) to the external server. The policy server, in turn, returns responses on the same NATS subject, determining whether the host is allowed to start an application component, start a capability provider, or let a component invoke a capability provider.

Diagram of policy evaluation flow

The policy service is disabled by default. When enabled, the policy service will be called by a host when:

  • a particular component or provider is started for the first time
  • an invocation is received between two entities for the first time

The policy service evaluates the provided action and returns a response indicating whether it is permitted. This response is cached by the host, so subsequent requests for the same action will not incur any overhead.

Policy Requests and Responses

Policy requests are made on a NATS subject, which is specified by the --policy-topic host config option. (The argument uses the general messaging term "topic" rather than the NATS-specific "subject," but you will simply specify a NATS subject here.)

Policy request schemas

Request schemes vary according to whether the request is to start an application component, start a provider component, or perform an invocation.

Schema for component start:

json
{
  "requestId": "... unique ID used for correlation ...",
  "kind": "startComponent",
  "version": "v1",
  "request": {
    "componentId": "componentId",
    "imageRef": "... OCI or file reference ...",
    "maxInstances": 1,
    "annotations": {
      "key": "value"
    },
    "claims": {
      "publicKey": "Mxxx",
      "issuer": "Axxx",
      "issuedAt": "1711993586",
      "expiresAt": 1711993587,
      "expired": true
    }
  },
  "host": {
    "publicKey": "Nxxxx",
    "lattice": "default",
    "labels": {
      "key": "value"
    }
  }
}

Schema for provider start:

json
{
  "requestId": "... unique ID used for correlation ...",
  "kind": "startProvider",
  "version": "v1",
  "request": {
    "providerId": "component ID",
    "imageRef": "... OCI or file reference ...",
    "annotations": {
      "key": "value"
    },
    "claims": {
      "publicKey": "Vxxx",
      "issuer": "Axxx",
      "issuedAt": "1711993586",
      "expiresAt": 1711993587,
      "expired": true
    }
  },
  "host": {
    "publicKey": "Nxxxx",
    "lattice": "default",
    "labels": {
      "key": "value"
    }
  }
}

Schema for invocation:

For example, invoking a component on the WASI HTTP standard handler wasi:http/incoming-handler.handle:

json
{
  "requestId": "... unique ID used for correlation ...",
  "kind": "performInvocation",
  "version": "v1",
  "request": {
    "interface": "wasi:http/incoming-handler",
    "function": "handle",
    "target": {
      "componentId": "componentId",
      "imageRef": "... OCI or file reference ...",
      "maxInstances": 1,
      "annotations": {
        "key": "value"
      }
    },
    "claims": {
      "publicKey": "Mxxx",
      "issuer": "Axxx",
      "issuedAt": "1711993586",
      "expiresAt": 1711993587,
      "expired": true
    }
  },
  "host": {
    "publicKey": "Nxxxx",
    "lattice": "default",
    "labels": {
      "key": "value"
    }
  }
}

Note that in all requests claims are optional and may be omitted if the component is not signed. This is a useful check for a policy server to determine whether a component is signed by a trusted issuer.

Policy response schema
json
{
  "requestId": "... unique ID used for correlation ...",
  "permitted": true|false,
  "message": "... optional detailed message ..."
}

Revoking Policy Decisions

Past policy decisions can be revoked/overridden by the policy service by publishing on the --policy-changes-topic NATS subject.

Example: Open Policy Agent

Since the policy service API is over NATS, it can be implemented by anything that can subscribe and publish responses to the configured policy topic (including a wasmCloud component!).

An example policy service implementing Open Policy Agent is available in the wasmCloud GitHub repository.