keystore

package module
v0.0.0-...-63f23c4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 1, 2023 License: GPL-3.0 Imports: 0 Imported by: 0

README

keystore

KeyStore holds unencrypted secrets on behalf of users in memory for a short time (of the order of a SSO session lifespan). User secrets can be opened with a password (used to decrypt the key, which is stored encrypted in a database), queried by presenting a suitable authentication token, and closed (wiped and forgotten).

The database can provide multiple versions of the encrypted key (to support multiple decryption passwords), in which case we'll try them all sequentially until one of them decrypts successfully with the provided password.

In order to query the KeyStore, you need to present a valid SSO token for the user whose secrets you would like to obtain.

API

The server exports an API over HTTP/HTTPS. All requests should be made using the POST method and a Content-Type of application/json. The request body should contain a JSON-encoded object. Responses will be similarly JSON-encoded.

/api/open (OpenRequest)

Retrieve the encrypted key for a user, decrypt it with the provided password, and store it in memory.

OpenRequest is an object with the following attributes:

  • username
  • password to decrypt the user's key with
  • ttl (seconds) time after which the credentials are automatically forgotten

If the user has no encrypted keys in the database, the request will still return successfully: no action will be performed, and no errors will be returned.

/api/get (GetRequest) -> GetResponse

Retrieve the key for a user. GetRequest must contain the following attributes:

  • username whose key you wish to retrieve
  • sso_ticket with a valid SSO ticket for the keystore service

If the request is successfully authenticated, GetResponse will contain a single attribute key.

/api/close (CloseRequest)

Forget the key for a given user.

Dovecot integration

The final consumer for user encryption keys is the Dovecot service. The dovecot-keylookupd daemon can read the user public and private keys from the database, and serve the unencrypted keys to Dovecot using its dict proxy protocol.

NOTE that passdb lookups using dovecot-keylookupd contain the cleartext password as part of the key, which may be logged in case of error! This is currently a huge limitation of this solution, but there seems to be no workaround that does not involve switching to a fork()-based solution (like the checkpassword script). That might be a better solution long-term.

TODO: explain the lookup protocol.

Configuration

The keystored daemon loads its configuration from a YAML-encoded file, /etc/keystore/config.yml by default. It can contain the following attributes:

  • sso_public_key_file: path to the SSO Ed25519 public key
  • sso_service: SSO service for this application
  • sso_domain: SSO domain
  • backend: backend configuration
    • type: backend type, one of ldap or sql
    • params: backend parameters, type-specific (see Backend configuration, below)
  • http_server: HTTP server configuration
    • tls: contains the server-side TLS configuration:
      • cert: path to the server certificate
      • key: path to the server's private key
      • ca: path to the CA used to validate clients
      • acl: specifies TLS-based access controls, a list of entries with the following attributes:
        • path: regular expression to match the request URL path
        • cn: regular expression that must match the CommonName part of the subject of the client certificate
    • max_inflight_requests: maximum number of in-flight requests to allow before server-side throttling kicks in

The dovecot-keylookupd daemon uses a similar configuration, read by default from /etc/keystore/dovecot.yml:

  • backend: backend configuration
    • type: backend type, one of ldap or sql
    • params: backend parameters, type-specific (see Backend configuration, below)
  • keystore: configures the connection to the keystore service
    • url: URL for the keystore service
    • sharded: if true, requests to the keystore service will be partitioned according to the user's shard attribute
    • tls: client TLS configuration
      • cert: path to the client certificate
      • key: path to the private key
      • ca: path to the CA used to validate the server
  • shard: shard identifier for the local host. Must be set if keystore.sharded is true.

Backend configuration

The keystore servers can talk to a LDAP or a SQL database. In both cases it is possible to adapt to the database schema by defining the exact queries to use. All we need to do is to retrieve the public and private parts of the user encryption key.

The ldap database backend understands the following configuration parameters:

  • uri: LDAP server URI
  • bind_dn: bind DN (for simple bind, SASL is not supported)
  • bind_pw: bind password
  • bind_pw_file: bind password (load from this file), in alternative to bind_pw
  • query: Parameters for the LDAP search query
    • search_base: base DN for the search
    • search_filter: search filter. The filter string may contain a literal %s token somewhere, that will be replaced with the (escaped) username.
    • scope: search scope, one of sub (default), one or base
    • public_key_attr: attribute that contains the user's public key
    • private_key_attr: attribute that contains the user's encrypted key(s)

The sql database backend requires the following parameters:

  • driver: SQL driver, one of sqlite3, mysql or postgres
  • db_uri: database URI (a.k.a. DSN), whose exact syntax will depend on the chosen driver. Check out the documentation for the database/sql sqlite, mysql and postgres drivers.
  • queries: map with the known queries. All SQL queries take one parameter (the user name), and return one or more rows with a single column. Use the ? placeholder for the parameter. Known queries:
    • get_user_public_key: must return a single row with the public key
    • get_user_private_keys: must return one or more rows with the user's private keys (copies of the same key encrypted with different passwords).

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type CloseRequest

type CloseRequest struct {
	Username  string `json:"username"`
	SessionID string `json:"session_id"`
}

type CloseResponse

type CloseResponse struct{}

type GetRequest

type GetRequest struct {
	Username  string `json:"username"`
	SSOTicket string `json:"sso_ticket"`
}

type GetResponse

type GetResponse struct {
	HasKey bool   `json:"has_key"`
	Key    []byte `json:"key"`
}

type OpenRequest

type OpenRequest struct {
	Username  string `json:"username"`
	Password  string `json:"password"`
	TTL       int    `json:"ttl"`
	SessionID string `json:"session_id"`
}

type OpenResponse

type OpenResponse struct{}

Directories

Path Synopsis
sql
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL