teleport/rfd/0124-plugin-secrets.md
Michael Wilson f511de6630
Plugin static credentials RFD. (#26599)
* Plugin static credentials RFD.

The RFD for supporting plugin static credentials has been created. This RFD
describes how static credentials such as API tokens and username/passwords
should be stored within Teleport.

* Incorporating feedback. Removed the CLI, clarified security/access control considerations, improved details on implementation plan.

* Use labels instead of name matching, adjust names and respond to other feedback.

* Noted that Teleport Assist's API token must be interpreted as a file location.

* Revert Assist API token must be interpreted as a file.

* Use true label matching, clarify security related concerns, add in some clarity to the plugin label fields.

* Remove explicit references to the plugin-label and have it become an auto-generated internal label within the metadata.

* Label and naming updates.

* Note that we won't use existing credentials objects.
2023-05-30 15:04:20 +00:00

6.3 KiB

authors state
Michael Wilson (michael.wilson@goteleport.com) draft

RFD 124 - Plugin static credentials

Required Approvers

  • Engineering @r0mant, @justinas
  • Security @reed
  • Product: @klizhentas

What

Allow storage of plugin static credentials within Teleport in a safe and secure way.

Why

As we grow our plugin support, we have discovered that the various services we hope to integrate do not offer a uniform mechanism for configuration. For instance, Slack uses oauth2, but Okta requires an API token, and Jamf requires a username and password.

Today, the plugin houses a credentials object that allows for this sort of storage. However, unlike an oauth authorization code, static credentials pose a much greater risk of exposure, and rotating credentials can be a time consuming process. To reduce the risks associated with storing static credentials within Teleport and to allow for easier credentials rotation, we would like to create a new resource within Teleport that is handled in an explicitly secure way.

Details

The PluginStaticCredentials object

A new object will be needed to house static credentials. At present it will support:

  • API tokens
  • Usernames and passwords
  • OAuth client ID and secret

This object has very strict access control requirements that will be explained in detail in the Access Control section. On creation, the plugin and static credentials will receive a UUID called the plugin-label. The static credentials will have an internal label that receives this value. Additionally, one plugin may have many credentials for the purposes of credentials rotation.

kind: plugin_static_credentials
version: v1
metadata:
  name: credentials-name
  labels:
    # This is a unique plugin label generated randomly at plugin creation.
    # It cannot be modified by the user.
    teleport.internal/plugin: 48398071-9860-4be6-9f29-ca6ca5bc7155
    # additional labels to uniquely identify the credentials.
    label1: value1
    type: slack
spec:
  credentials:
    # Only one of these credential types must be defined at a time. All values in this
    # are string literals and not file locations. None of the existing credentials objects
    # will be used for this, and all new objects will be created.
    api_token: example-token
    basic_auth:
      username: example-user
      password: example-password
    oauth_client_secret:
      client_id: example-client-id
      client_secret: example-client-secret

If a Plugin is using the oauth authorization code flow, however, it will not need any PluginStaticCredentials objects.

Changes to the Plugin object

The Plugin object's Credentials field will have a new type of credential called CredentialsRef that contains a reference to a static plugin label. More than one static credential may match this label, in which case when starting the plugin, the most recently created credential will be used.

credentials_ref:
  labels:
    # This label is the same label generated at plugin creation. This field will be
    # injected by Teleport at creation.
    teleport.internal/plugin: 48398071-9860-4be6-9f29-ca6ca5bc7155
    env: prod
    type: slack

Access control

PluginStaticCredentials can be written to and deleted by RoleProxy. At introduction, creating credentials is a flow that will only happen through the web UI, so only RoleProxy is needed. Future work may determine that we want to open up writing through the CLI.

The object will be only readable by the RoleAdmin role (with one exception). This is because plugins run on the auth server, so it's the only role that needs to be able to actually read the static credentials.

One Plugin object can refer to multiple static credentials and a Plugin can't refer to existing static credentials. Static credentials must be associated with one and only one plugin.

The one exception here is Teleport Assist, which runs in the proxy. The proxy will be able to read plugin credentials with the name of openai-default, which is the name of the Assist plugin.

Lifecycle of the PluginStaticCredentials object

Creation

A PluginStaticCredentials object must be created at the same time that the Plugin is created.

Deletion

On deletion, the associated Plugin will be stopped and related PluginStaticCredentials objects will be deleted when deleting its associated plugin.

UX

Web UI

The web UI will remain largely the same with respect to entering credentials for specific plugins. This will largely depend on the specific application.

Audit events

A number of new audit events will be created as part of this effort:

Event Name Description
plugin.credentials.create Emitted when plugin credentials have been created.
plugin.credentials.delete Emitted when plugin credentials have been deleted.

Security

  • Only the auth server is able to read plugin credentials. The proxy will be able to create them, and admins will be able to delete them.
  • The credentials will be stored in DynamoDB, which is encrypted at rest. This will provide a layer of protection for the stored credentials.
  • The credentials will not be cached, so they won't be sitting in an in-memory cache to be exfiltrated.

Implementation plan

PluginStaticCredentials object and backend service

  • The PluginStaticCredentials object
  • The local service to manage the PluginStaticCredentials objects in the backend.

Modifications to the Plugin object

  • A new PluginStaticCredentialsRefs type.
  • PluginStaticCredentials objects are created during Plugin creation.
  • PluginStaticCredentials objects are deleted during Plugin deletion.

Implement PluginStaticCredentials permissions

  • gRPC methods in the auth service to support reading the PluginStaticCredentials, ensuring that reading can only be done by RoleAdmin and, for the specific case of Teleport Assist, RoleProxy.
  • Any updates to RBAC to support the creation/deletion of the PluginStaticCredentials object.

Integrate PluginStaticCredentials with enterprise plugin manager

  • Look up PluginStaticCredentials objects when starting plugins that require them in the plugin manager.

Add audit events

  • Add audit events for the creation and deletion of PluginStaticCredentials.