Mutually authenticated TLS (mTLS) reference

Environment variables

NameDescription
VESPA_TLS_CONFIG_FILE Absolute path JSON configuration file with TLS configuration.
VESPA_TLS_INSECURE_MIXED_MODE Enables TLS mixed mode. See TLS Mixed mode for possible values.

TLS mixed mode

Possible TLS mixed mode settings for VESPA_TLS_INSECURE_MIXED_MODE:

NameDescription
plaintext_client_mixed_server Clients do not use TLS, servers accept both TLS and plaintext clients.
tls_client_mixed_server Clients use TLS, servers accept both TLS and plaintext clients.
tls_client_tls_server All clients and servers use TLS only.

Configuration file

The TLS configuration file contains a single top-level JSON object.

Top-level elements

NameRequiredDescription
files Yes JSON object containing file system paths crypto material.
authorized-peers No JSON array of authorized-peer objects. Authorization engine is disabled if not specified. See dedicated section on how to create peer authorization rules.
accepted-ciphers No JSON array of accepted TLS cipher suites. See here for cipher suites enabled by default. You can only specify a subset of the default cipher suites. This is an expert option—use the default unless you have good reasons not to.
accepted-protocols No JSON array of accepted TLS protocol versions. See here for TLS versions enabled by default. You can only specify a subset of the default protocol versions. This is an expert option—use the default unless you have good reasons not to.
disable-hostname-validation No Disables TLS/HTTPS hostname validation. Enabled by default (default value false).

The files element

NameRequiredDescription
private-key Yes Absolute path to file containing the private key in PKCS#8 PEM format.
certificate Yes Absolute path to file containing X.509 certificate chain (including any intermediate certificates). Certificates must be encoded in PEM format separated by newlines.
ca-certificates Yes Absolute path to file containing all trusted X.509 Certificate Authorities. Certificates must be encoded in PEM format separated by newlines.

The authorized-peer element

NameRequiredDescription
required-credentials Yes A JSON array specifying each credential requirement for this particular rule.
name Yes Name of the rule.
description No Description of the rule.

The required-credential element

NameRequiredDescription
field Yes Certificate field. Possible values: CN, SAN_DNS, SAN_URI.
must-match Yes String containing a "glob"-style pattern.

Peer authorization rules

The authorized-peers member is an array of credential rule-set objects. For a peer to be considered authorized its certificate MUST match at least one rule set completely.

Each rule set must contain a required-credentials array of credential matchers. For a certificate to match a rule set it MUST match all its credential matchers.

A credential is matched by checking a pattern given in must-match against a specified certificate field. The following fields are currently supported:

  • CN - the Common Name part of the certificate's Distinguished Name information. If multiple CN entries are present, the last one will be considered.
  • SAN_DNS - a Subject Alternate Name with type DNS. A certificate may contain many SAN entries. If so, all entries are checked and the credential is considered a match if at least one entry matches.
  • SAN_URI - a Subject Alternate Name with type URI. It is similar to SAN_DNS but with slightly different pattern matching semantics.

For CN and SAN_DNS fields, the must-match pattern is a "glob"-style pattern with the following semantics:

  • * matches 0-n non-dot characters within a single dot-separated hostname part. This is similar to the wildcards used by certificates for HTTPS hostname validation. Examples
    • *.baz matches bar.baz but not foo.bar.baz or foo.baz.bar.
    • *.*.baz matches foo.bar.baz but not bar.baz.
    • *-myservice matches foo-myservice but not bar.foo-myservice.
  • ? matches exactly 1 non-dot character within a single dot-separated hostname part. Examples:
    • ?.bar matches x.bar but not bar, .bar or yx.bar.
    • ?.?.baz matches x.y.baz but not x.baz or xx.yy.baz.

For SAN_URI fields, must-match is also a "glob"-style pattern, with some deviation compared to CN/SAN_DNS:

  • The * wildcard matches 0-n non-slash characters. A / is used as separator between the host and path components, as well as separator between path segments. Examples:
    • vespa://myapp/content/* matches vespa://myapp/content/node1 but not vespa://myapp/container/node1 or vespa://myapp/content/node1/myservice.
    • vespa://*/*/* matches vespa://myapp/content/node1 but not vespa://myapp/content or vespa://myapp/content/node1/myservice.
  • ? in a pattern has no special behaviour - it only matches the ? literal. URIs use ? as separator between the path and query components.

The description field is optional and is useful for e.g. documenting why a particular ruleset is present. It has no semantic meaning to the authorization engine.

Not providing the authorized-peers field means only certificate validity is used for authorization. If the authorized-peers field is provided, it must contain at least one entry.

Example

{
    "files": {
        "ca-certificates": "/absolute/path/to/ca-certs.pem",
        "certificates": "/absolute/path/to/host-certs.pem",
        "private-key": "/absolute/path/to/private-key.pem",
        "disable-hostname-validation": false
    },
    "authorized-peers": [
        {
            "required-credentials": [
                { "field": "CN", "must-match": "vespa-monitoring.example.com" },
                { "field": "SAN_DNS", "must-match": "*.us-east-*.monitor.example.com" }
            ],
            "description": "Backend monitoring service access",
            "name": "monitoring"
        }, 
        {
            "required-credentials": [
                { "field": "SAN_DNS", "must-match": "*.mycluster.vespa.example.com" }
            ],
            "description": "Cluster-internal node P2P access",
            "name": "cluster"
        }
    ]
}

TLS features supported by Vespa

Vespa is built with modern, high-performance cryptography libraries. For security reasons, the Vespa TLS stack has some additional constraints that are always present:

  • TLSv1.2 is the oldest TLS version that can be negotiated.
  • Only cipher suites supporting forward secrecy can be negotiated (i.e. cipher suites using ECDHE as part of their key exchange).
  • Only modern, symmetric ciphers with AEAD properties are supported. In practice this means AES-GCM or ChaCha20-Poly1305. Supported cipher suites are listed here.
  • TLS compression is explicitly disabled to mitigate CRIME/BREACH-style compression oracle attacks.
  • TLS renegotiation is explicitly disabled.
  • TLS session resumption is explicitly disabled, as this opens up some potential vulnerabilities related to replay attacks. Note that the Vespa application container edge does support session resumption, due to needing to support many frequent, short-lived connections from proxies and clients.

Default TLS protocol settings

Vespa will by default use the following TLS configuration (unless overridden by accepted-ciphers / accepted-protocols).

Protocol versions

  • TLSv1.3 - note: due to certain limitations in the current Java runtime, TLSv1.3 is only supported by the C++ backends for now. We will revisit this in the near future to ensure Java defaults to TLSv1.3 as well.
  • TLSv1.2

Cipher suites

  • TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
  • TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
  • TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 (JDK 12+)
  • TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
  • TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
  • TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
  • TLS_AES_128_GCM_SHA256 (TLSv1.3)
  • TLS_AES_256_GCM_SHA384 (TLSv1.3)
  • TLS_CHACHA20_POLY1305_SHA256 (TLSv1.3, JDK 12+)