Search
Varnish Enterprise

cwt

Experimental Api

Note that the API of this VMOD is considered experimental at this time and may change in subsequent releases. Such changes will be highlighted in the release notes.

Cbor Web Tokens

The cwt VMOD enables verification and validation of CBOR Web Tokens (CWTs) from VCL. CWT is derived from JSON Web Token (JWT) but uses CBOR (Concise Binary Object Representation) rather than JSON.

A CWT is a set of claims encapsulated inside a COSE object (CBOR Object Signature and Encryption) cryptographically verifiable. An application can use these claims to enforce access control over privileged resources.

Please note however that it is up to the application to know the resources that should be guarded. This VMOD can validate claims that can be evaluated automatically, and it can give access to claims that can be represented in VCL, but it cannot expose claims using more complex types.

The following claims are supported:

  • iss: Issuer
  • sub: Subject
  • aud: Audience
  • exp: Expiration Time
  • nbf: Not Before
  • iat: Issued At
  • cti: CWT ID

Common Access Tokens

A Common Access Token (CAT) is a CWT that may contain CAT-specific claims. When working with a CAT, tokens follow acceptance rules stricter than CWT validation. For example, unknown claims must be ignored for CWT validation but they must be rejected for CAT acceptance.

Moreover, there are several locations from where Common Access Tokens may be imported, in which case accepting one token is enough to accept the client request.

The following claims are supported:

  • catv: CAT Version
  • catnip: Network IP
  • catu: URI
  • catm: Method
  • cath: Header

For catu and cath claims, regular expression, SHA-256 and SHA-512/256 matching is not implemented.

Example

This implements basic handling with verification and validation of CWT claims from the client. The COSE keys registered here are lifted from the RFC 8392, and should not be used on any production server.

vcl 4.1;

import cwt;

sub vcl_init {
	# RFC 8392 Appendix A.2.2
	cwt.import_cose_key(hex={"
	a4205820403697de87af64611c1d32a05dab0fe1fcb715a86ab435f1ec99192d
	795693880104024c53796d6d65747269633235360304
	"});

	# RFC 8392 Appendix A.2.3
	cwt.import_cose_key(hex={"
	a72358206c1382765aec5358f117733d281c1c7bdc39884d04a45a1e6c67c858
	bc206c1922582060f7f1a780d8a783bfb7a2dd6b2796e8128dbbcef9d3d168db
	9529971a36e7b9215820143329cce7868e416927599cf65a34f3ce2ffda55a7e
	ca69ed8919a394d42f0f2001010202524173796d6d6574726963454344534132
	35360326
	"});
	}
}

sub vcl_recv {
	if (!cwt.import_cat()) {
		return (synth(400, cwt.get_error()));
	}

	if (!cwt.accept()) {
		return (synth(403, cwt.get_error()));
	}
}

Key Management

The cryptographic verification of a CWT requires its public key. Keys can be loaded from vcl_init and they will be used for the entire life time of the VCL. Loading new keys requires a VCL reload.

Keys have identifiers (kid). More than one key can be loaded with the same identifier, but that is generally discouraged. This can be used for example during a key rotation, where two different keys may share the same kid. It can also be the same kid used for different key types, for different cryptographic algorithms.

For this reason, keys loaded last take precedence over keys loaded first.

It should be noted that keys may describe incomplete algorithms, also known as polymorphic algorithms. For example the EdDSA algorithm could lack a curve parameter specifying the underlying Edwards curve. Another example is the ECDSA algorithm where the number of bits does not match between the curve and the digest, which is not recommended.

This VMOD only accepts fully-specified algorithms, but it will accept a polymorphic algorithm identifier when all parameters are specified, and when applicable, only if it follows recommendation.

Keys can be loaded in the COSE format, and other formats will be supported.

import_cose_key

VOID import_cose_key([STRING base64url], [STRING hex], [BLOB cbor])

Import the given COSE_Key object and add it to the key ring.

Exactly one of base64url, hex, or cbor must be specified. Failing to import a key fails the VCL load.

The cryptographic signature verification and decryption algorithms currently supported are:

  • ES256/ESP256 (ECDSA with curve P-256 and SHA-256)
  • RS256 (RSA-PSS with SHA-256, public keys only, at least 2048 bits)
  • HS256 (HMAC with SHA-256, optionally truncated to 64 bits)
  • EdDSA (with curves Ed25519 or Ed448)

Arguments:

  • base64url accepts type STRING

  • hex accepts type STRING

  • cbor accepts type BLOB

Type: Function

Returns: None

Restricted to: vcl_init

import_cose_keyset

VOID import_cose_keyset([STRING base64url], [STRING hex], [BLOB cbor])

Import the given COSE_KeySet object and add all of its keys to the key ring.

Exactly one of base64url, hex, or cbor must be specified. Failing to import a key fails the VCL load.

The order of keys is maintained once imported. For example if a key with a kid “previous” was imported before a key set, and that key set contains keys with kid “first” and “last”, the new lookup order in the key ring becomes “first”, “last” and “previous”.

Token Management

Tokens can be imported in the current client task from vcl_recv. Multiple tokens can be imported in the same task, but a token provenance MUST be specified in order to load more than one at a time. All functions operating on tokens may take a from argument. The syntax for provenance is the same as VCL variables:

  • it must start with a letter
  • it can then contain letters, digits and the minus sign (-)

Provenance must be unique within a client task.

Arguments:

  • base64url accepts type STRING

  • hex accepts type STRING

  • cbor accepts type BLOB

Type: Function

Returns: None

Restricted to: vcl_init

import_cwt

BOOL import_cwt([STRING base64url], [STRING hex], [BLOB cbor], [STRING from])

Import a CWT into the current client task.

Exactly one of base64url, hex, or cbor must be specified.

Returns true on success and false otherwise.

Arguments:

  • base64url accepts type STRING

  • hex accepts type STRING

  • cbor accepts type BLOB

  • from accepts type STRING

Type: Function

Returns: Bool

Restricted to: vcl_recv

import_cat

BOOL import_cat()

Automatically import Common Access Tokens from standard locations with a provenance identifying that location.

For now, only one location is scanned:

  • cat-hdr: the req.http.CTA-Common-Access-Token variable

It is however possible to import tokens from other locations with the help of other VMODs.

Returns true if all tokens were successfully imported and false otherwise.

Arguments: None

Type: Function

Returns: Bool

Restricted to: vcl_recv

verify

BOOL verify([STRING from])

Verify the cryptographic signature of all imported CWTs, or the token specified by the from argument.

Returns true if all tokens were successfully verified and false otherwise.

Arguments:

  • from accepts type STRING

Type: Function

Returns: Bool

Restricted to: vcl_recv

validate

BOOL validate([DURATION clock_skew], [INT asn], [STRING from])

Validate known claims of all imported CWTs, or the token specified by the from argument. If a claim cannot semantically be validated, for example the indented audience (aud), claim validation is limited to ensuring a well-formed value.

The following arguments can influence token validation:

  • clock_skew: the time window tolerated for time-based checks
  • asn: the ASN of the client, see VMOD asn

Returns true if all tokens were successfully validated and false otherwise.

Arguments:

  • clock_skew accepts type DURATION

  • asn accepts type INT

  • from accepts type STRING

Type: Function

Returns: Bool

Restricted to: vcl_recv

accept

BOOL accept([DURATION clock_skew], [INT asn])

Checks whether all claims can be accepted for at least one imported CWT, or the token specified by the from argument. If a claim cannot semantically be validated, for example the token issuer (iss), the check is limited to ensuring a well-formed claim value.

Unknown claims are rejected.

Before checking the claims, the token signature is also verified.

This matches the acceptance criteria for Common Access Tokens.

The following arguments can influence token validation:

  • clock_skew: the time window tolerated for time-based checks
  • asn: the ASN of the client, see VMOD asn

Returns true if at least one token can be accepted and false otherwise.

Arguments:

  • clock_skew accepts type DURATION

  • asn accepts type INT

Type: Function

Returns: Bool

Restricted to: vcl_recv

get_tokens

STRING get_tokens()

Returns a comma-separated list of token provenances, for example:

  "cat-query,cat-cookie"

Arguments: None

Type: Function

Returns: String

Restricted to: client

get_error

STRING get_error([STRING from])

Get the last error message for a specific token after an operation, or the first error found at the task or token level when from is not specified.

An operation is a call to any function in the token management section. An operation clears all errors before executing.

Token Access

The following functions access information about a token, when possible.

Known claims can be accessed by name with the name argument, and any claim can be accessed by its numeric identifier with the key argument. Only one of name or key must be used at a time.

When provenance is not specified, the first imported token is searched.

When well-known claims are not found, they return the same value as the get_claim_<type>() function matching their return type.

Arguments:

  • from accepts type STRING

Type: Function

Returns: String

Restricted to: client

get_claim_blob

BLOB get_claim_blob([STRING name], [INT key], [STRING from])

Search a claim with a binary string value.

Returns a BLOB on success or null on failure.

Arguments:

  • name accepts type STRING

  • key accepts type INT

  • from accepts type STRING

Type: Function

Returns: Blob

Restricted to: client

get_claim_int

INT get_claim_int([STRING name], [INT key], [STRING from])

Search a claim with an integer value.

Returns an INT on success or 0 on failure.

Arguments:

  • name accepts type STRING

  • key accepts type INT

  • from accepts type STRING

Type: Function

Returns: Int

Restricted to: client

get_claim_string

STRING get_claim_string([STRING name], [INT key], [STRING from])

Search a claim with an string value. The result must be allocated in the workspace.

Returns a STRING on success or null on failure.

Arguments:

  • name accepts type STRING

  • key accepts type INT

  • from accepts type STRING

Type: Function

Returns: String

Restricted to: client

get_claim_time

TIME get_claim_time([STRING name], [INT key], [STRING from])

Search a claim with a value that can be converted to TIME.

Returns the TIME value on success or 0.0 on failure.

Arguments:

  • name accepts type STRING

  • key accepts type INT

  • from accepts type STRING

Type: Function

Returns: Time

Restricted to: client

get_iss

STRING get_iss([STRING from])

Get the well-known issuer claim from a CWT.

Arguments:

  • from accepts type STRING

Type: Function

Returns: String

Restricted to: client

get_sub

STRING get_sub([STRING from])

Get the well-known subject claim from a CWT.

Arguments:

  • from accepts type STRING

Type: Function

Returns: String

Restricted to: client

get_exp

TIME get_exp([STRING from])

Get the well-known expiry claim from a CWT.

Arguments:

  • from accepts type STRING

Type: Function

Returns: Time

Restricted to: client

get_nbf

TIME get_nbf([STRING from])

Get the well-known not-before claim from a CWT.

Arguments:

  • from accepts type STRING

Type: Function

Returns: Time

Restricted to: client

get_iat

TIME get_iat([STRING from])

Get the well-known issued-at claim from a CWT.

Arguments:

  • from accepts type STRING

Type: Function

Returns: Time

Restricted to: client

get_cti

BLOB get_cti([STRING from])

Get the well-known CWT ID claim from a CWT.

Arguments:

  • from accepts type STRING

Type: Function

Returns: Blob

Restricted to: client

get_catv

INT get_catv([STRING from])

Get the well-known CAT version claim from a CWT.

Arguments:

  • from accepts type STRING

Type: Function

Returns: Int

Restricted to: client


®Varnish Software, Wallingatan 12, 111 60 Stockholm, Organization nr. 556805-6203