Secrets Service

Related ticket(s):

Problem statement

Many system and user applications need to store secrets such as passwords or service keys and have no good way to properly deal with them. The simple approach is to embed these secrets into configuration files potentially ending up exposing sensitive key material to backups, config management system and in general making it harder to secure data.

The custodia project was born to deal with this problem in cloud like environments, but we found the idea compelling even at a single system level. As a security service sssd is ideal to host this capability while offering the same API via a UNIX Socket. This will make it possible to use local calls and have them transparently routed to a local or a remote key management store like IPA Vault or HashiCorp’s Vault for storage, escrow and recovery.

Use cases

This feature can be used to keep secrets safe in an encrypted database and yet make it easy for application to have access to the clear text form, at the same time protecting access to the secrets by using targeted system policies. Also when remote providers are implemented it will become possible to synchronize application secrets across multiple machines either for system applications like clusters or for user’s passwords by providing a simple network keyring that can be shared by multiple clients.

Overview of the solution

This feature will be implemented by creating a new responder process that handles the REST API over a UNIX Socket, and will route requests either to a local database separate from the generic ldb caches or to a provider that can implement remote backends like IPA Vault to store some or all the secrets of a user or a system application.

The new responder daemon will be called sssd-secrets and will be socket activated in the default configuration on systemd based environments.

Additionally a client library will be provided with a very simple basic API for simple application needs. The full Custodia API will be provided over the socket and will be accessible via curl or a similar tool.

Implementation details

TBD

Request flow: application -> libsss-secrets.so —unix socket—> sssd-secrets -> local store

Or alternatively, for an application that can speak REST itself: application —unix socket—> sssd-secrets -> local store

The latter would be probably used by applications written in higher level languages such as Java or Python, the former would be better suited for C/C++ applications without requiring additional dependencies.

unix socket in /var/run/secrets.socket local store in /var/lib/sss/secrets/secrets.ldb encrypted using master secret (potentially uses TPM where available ?)

Helper libraries

The Custodia REST API uses JSON to encode requests and replies, {provisionally} the ​Jansson library will be used behind a talloc base wrapper and insulated to allow easy replacement, and encoding/decoding into specific API objects.

The REST API uses HTTP 1.1 as transport so we’ll need to parse HTTP Requests in the server, {provisionally} the ​http-parser library will be used in a tevent wrapper to handle these requests. The library seem to be particularly suitable for use in callback based systems like tevent, and does not handle memory on it’s own allowing use to use fully talloc backed objects natively.

Client Library

A simple client library is build to provide easy access to secrets from C applications (or other languages via bindings) by concealing all the communication into a simple API.

The API should be as follow:

struct secrets_context;

struct secrets_data {
    uint8_t *data;
    size_t *length;
};

struct secrets_list {
    struct secret_data *elements;
    int count;
}

int secrets_init(const char *appname,
                 struct secrets_context **ctx);
int secrets_get(struct secrets_context *ctx, const char *name,
                struct secrets_data *data);
int secrets_put(struct secrets_context *ctx, const char *name,
                struct secrets_data *data);
int secrets_list(struct secrets_context *ctx, const char *path,
                 struct secrets_list *list);

void secrets_context_free(struct secrets_context **ctx);
void secrets_list_contents_free(struct secrets_list *list);
void secrets_data_contents_free(struct secrets_data *data);

The API uses exclusively the “simple” secret type.

Resource Considerations

TBD user quotas

Security Considerations

Access Control SO_PEERCRED and SELinux.

Configuration changes

A new type of configuration section called “secrets” will be introduced. Like the “domain” sections, secrets session names include a secret name in the section name.

A typical section name to override where an application like the Apache web server will have its secrets stored looks like this:

[secrets/system/httpd]
provider = xyz

The global secrets configuration will be held in the `` [secrets] `` (no path components) section. Providers may deliver overrides in configuration snippets, use of additional, dynamic configuration snippets will be the primary method to configure overrides and remote backends.

How To Test

A test/example binary that implement the functions of the client library will be provided, additional the curl binary should be used to test the wider API, especially once we have a proxy backend to talk to a real custodia server on the network.

Authors

Simo Sorce <simo@redhat.com>