package
1.13.1
Repository: https://github.com/spiffe/spire.git
Documentation: pkg.go.dev

# README

SPIRE OIDC Discovery Provider

The SPIRE OIDC Discovery Provider is a small helper that provides a minimal implementation of a subset of the OIDC discovery document as related to exposing a JSON Web Key Set (JWKS) for JSON Web Token (JWT) validation.

It provides the following endpoints:

VerbPathDescription
GET/.well-known/openid-configurationReturns the OIDC discovery document
GET/keysReturns the JWKS for JWT validation
GET/readyReturns http.OK (200) as soon as requests can be served. (disabled by default)
GET/liveReturns http.OK (200) as soon as a keyset is available, otherwise http.InternalServerError (500). (disabled by default)

The endpoints can be moved to a different prefix by way of the server_path_prefix option. For example, setting server_path_prefix to /instance/1 will make the OIDC discovery document served at /instance/1/.well-known/openid-configuration and keys at /instance/1/keys

The provider by default relies on ACME to obtain TLS certificates that it uses to serve the documents securely.

Configuration

Command Line Configuration

The provider has the following command line flags:

FlagDescriptionDefault
-configPath on disk to the HCL Configuration fileoidc-discovery-provider.conf

HCL Configuration

The configuration file is required by the provider. It contains HCL encoded configurables.

KeyTypeRequired?DescriptionDefault
acmesectionrequired[1]Provides the ACME configuration.
serving_cert_filesectionrequired[1][4]Provides the serving certificate configuration.
allow_insecure_schemebooloptional[3]Serves OIDC configuration response with HTTP url.false
domainsstringsrequiredOne or more domains the provider is being served from.
experimentalsectionoptionalThe experimental options that are subject to change or removal.
insecure_addrstringoptional[3]Exposes the service on http.
set_key_usebooloptionalIf true, the use parameter on JWKs will be set to sig.false
listen_socket_pathstringrequired[1][3]Path on disk to listen with a Unix Domain Socket. Unix platforms only.
log_formatstringoptionalFormat of the logs (either "TEXT" or "JSON")""
log_levelstringrequiredLog level (one of "error","warn","info","debug")"info"
log_pathstringoptionalPath on disk to write the log.
log_requestsbooloptionalIf true, all HTTP requests are logged at the debug levelfalse
server_apisectionrequired[2]Provides SPIRE Server API details.
workload_apisectionrequired[2]Provides Workload API details.
filesectionrequired[2]Provides File details.
health_checkssectionoptionalEnable and configure health check endpoints
jwt_issuerstringoptionalSpecifies the issuer for the OIDC provider configuration request
jwks_uristringoptionalSpecifies the JWKS URI returned in the discovery document
server_path_prefixstringoptionalIf specified, all endpoints listened to will be prefixed by this value"/"
experimentalTypeRequired?DescriptionDefault
listen_named_pipe_namestringrequired[1][3]Pipe name to listen with a named pipe. Windows only.

Considerations for Unix platforms

[1]: One of acme, serving_cert_file or listen_socket_path must be defined.

[3]: The allow_insecure_scheme should only be used in a local development environment for testing purposes. It only works in conjunction with insecure_addr or listen_socket_path.

Considerations for Windows platforms

[1]: One of acme, serving_cert_file or listen_named_pipe_name must be defined.

[3]: The allow_insecure_scheme should only be used in a local development environment for testing purposes. It only works in conjunction with insecure_addr or listen_named_pipe_name.

Considerations for all platforms

[2]: One of server_api, workload_api, or file must be defined. The provider relies on one of these APIs to obtain the public key material used to construct the JWKS document.

The domains configurable contains the list of domains the provider is expected to be served from. If a request is received from a domain other than one in the list (as determined by the Host or X-Forwarded-Host header), it will be rejected. Likewise, when ACME is used, the domains list contains the allowed domains for which certificates will be obtained. The TLS handshake will terminate if another domain is requested.

[4]: SPIRE OIDC Discovery provider monitors and reloads the files provided in the serving_cert_file configuration at runtime.

ACME Section

KeyTypeRequired?DescriptionDefault
cache_dirstringoptionalThe directory used to cache the ACME-obtained credentials. Disabled if explicitly set to the empty string"./.acme-cache"
directory_urlstringoptionalThe ACME directory URL to use. Uses Let's Encrypt if unset."https://acme-v01.api.letsencrypt.org/directory"
emailstringrequiredThe email address used to register with the ACME service
tos_acceptedboolrequiredIndicates explicit acceptance of the ACME service Terms of Service. Must be true.

Serving Certificate Section

KeyTypeRequired?DescriptionDefault
cert_file_pathstringrequiredThe certificate file path, the file must contain PEM encoded data.
key_file_pathstringrequiredThe private key file path, the file must contain PEM encoded data.
file_sync_intervaldurationoptionalControls how frequently the service polls the files for changes.1 minute
addrstringoptionalExposes the service on the given address.:443

Server API Section

KeyTypeRequired?DescriptionDefault
addressstringrequiredSPIRE Server API gRPC target address. Only the unix name system is supported. See https://github.com/grpc/grpc/blob/master/doc/naming.md. Unix platforms only.
experimentalsectionoptionalThe experimental options that are subject to change or removal.
poll_intervaldurationoptionalHow often to poll for changes to the public key material."10s"
experimentalTypeRequired?DescriptionDefault
named_pipe_namestringrequiredPipe name of the SPIRE Server API named pipe. Windows only.

Workload API Section

KeyTypeRequired?DescriptionDefault
experimentalsectionoptionalThe experimental options that are subject to change or removal.
socket_pathstringrequiredPath on disk to the Workload API Unix Domain socket. Unix platforms only.
poll_intervaldurationoptionalHow often to poll for changes to the public key material."10s"
trust_domainstringrequiredTrust domain of the workload. This is used to pick the bundle out of the Workload API response.
experimentalDescriptionDefault
named_pipe_namePipe name of the Workload API named pipe. Windows only.

File Section

KeyTypeRequired?DescriptionDefault
pathstringrequiredPath on disk to the spiffe formatted trust bundle to use.
poll_intervaldurationoptionalHow often to poll for changes to the public key material."10s"

Health Checks Section

Health checks are enabled by adding health_checks {} to the configuration. The health checks endpoints are hosted on a dedicated listener on localhost.

  • The "ready" state is determined by the availability of keys fetched via the workload/server API. If the keys where fetched successfully but can't be fetched anymore (e.g. workload or server API can't be reached), the server is still determined ready for the threshold interval.
  • The "live" state is either determined by the availability of keys fetched via the workload/server API or the threshold interval after the server started serving requests. If the keys where fetched successfully but can't be fetched anymore (e.g. workload/server API can't be reached), the server is still determined live for the threshold interval.

The threshold interval is currently set to 5 times the workload/server APIs poll interval, but at least 3 minutes. Both states respond with a 200 OK status code for success or 500 Internal Server Error for failure.

KeyTypeRequired?DescriptionDefault
bind_portstringoptionaloverride default listener bind port"8008"
ready_pathstringoptionaloverride default ready path"/ready"
live_pathstringoptionaloverride default live path"/live"

Examples (Unix platforms)

Server API and ACME

log_level = "debug"
domains = ["mypublicdomain.test"]
acme {
    cache_dir = "/some/path/on/disk/to/cache/creds"
    email = "[email protected]"
    tos_accepted = true
}
server_api {
    address = "unix:///tmp/spire-server/private/api.sock"
}

Workload API and ACME

log_level = "debug"
domains = ["mypublicdomain.test"]
acme {
    cache_dir = "/some/path/on/disk/to/cache/creds"
    email = "[email protected]"
    tos_accepted = true
}
workload_api {
    socket_path = "/tmp/spire-agent/public/api.sock"
    trust_domain = "domain.test"
}

Server API and Serving Certificate

log_level = "debug"
domains = ["mypublicdomain.test"]
serving_cert_file {
 cert_file_path = "/some/path/on/disk/to/cert.pem"
 key_file_path = "/some/path/on/disk/to/key.pem"
}
server_api {
    address = "unix:///tmp/spire-server/private/api.sock"
}

Workload API and Serving Certificate

log_level = "debug"
domains = ["mypublicdomain.test"]
serving_cert_file {
 cert_file_path = "/some/path/on/disk/to/cert.pem"
 key_file_path = "/some/path/on/disk/to/key.pem"
}
workload_api {
    socket_path = "/tmp/spire-agent/public/api.sock"
    trust_domain = "domain.test"
}

Listening on a Unix Socket

The following configuration has the OIDC Discovery Provider listen for requests on the given socket. This can be used in conjunction with a webserver like Nginx, Apache, or Envoy which supports reverse proxying to a unix socket.

log_level = "debug"
domains = ["mypublicdomain.test"]
listen_socket_path = "/run/oidc-discovery-provider/server.sock"

workload_api {
    socket_path = "/tmp/spire-agent/private/api.sock"
    trust_domain = "domain.test"
}

A minimal Nginx configuration that proxies all traffic to the OIDC Discovery Provider's socket might look like this.

daemon off;
 events {}
 http {
   access_log /dev/stdout;
   upstream oidc {
     server unix:/run/oidc-discovery-provider/server.sock;
   }
   server {
     # ... Any TLS and listening config you may need
     location / {
       proxy_pass http://oidc;
     }
   }
 }

Examples (Windows)

Server API and ACME

log_level = "debug"
domains = ["mypublicdomain.test"]
acme {
    cache_dir = "c:\\some\\path\\on\\disk\\to\\cache\\creds"
    email = "[email protected]"
    tos_accepted = true
}
server_api {
    experimental {
        named_pipe_name = "\\spire-server\\private\\api"
    }
}

Workload API and ACME

log_level = "debug"
domains = ["mypublicdomain.test"]
acme {
    cache_dir = "c:\\some\\path\\on\\disk\\to\\cache\\creds"
    email = "[email protected]"
    tos_accepted = true
}
workload_api {
    experimental {
        named_pipe_name = "\\spire-agent\\public\\api"
    }
    trust_domain = "domain.test"
}

Server API and Serving Certificate

log_level = "debug"
domains = ["mypublicdomain.test"]
serving_cert_file {
    cert_file_path = "c:\\some\\path\\on\\disk\\to\\cert.pem"
    key_file_path = "c:\\some\\path\\on\\disk\\to\\key.pem"
}
server_api {
    experimental {
        named_pipe_name = "\\spire-server\\private\\api"
    }
}

Workload API and Serving Certificate

log_level = "debug"
domains = ["mypublicdomain.test"]
serving_cert_file {
 cert_file_path = "c:\\some\\path\\on\\disk\\to\\cert.pem"
 key_file_path = "c:\\some\\path\\on\\disk\\to\\key.pem"
}
workload_api {
    experimental {
        named_pipe_name = "\\spire-agent\\public\\api"
    }
    trust_domain = "domain.test"
}

Listening on a Named Pipe

The following configuration has the OIDC Discovery Provider listen for requests on the given named pipe. This can be used in conjunction with a webserver that supports reverse proxying to a named pipe.

log_level = "debug"
domains = ["mypublicdomain.test"]
experimental {
    listen_named_pipe_name = "oidc-discovery-provider"
}

workload_api {
    experimental {
        named_pipe_name = "\\spire-agent\\public\\api"
    }
    trust_domain = "domain.test"
}