secrets/db: documents credential types and snowflake key pair auth (#15892)

This commit is contained in:
Austin Gebauer 2022-06-09 15:56:50 -07:00 committed by GitHub
parent 8f115a9904
commit 1bd49383cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 229 additions and 71 deletions

View File

@ -315,6 +315,8 @@ This endpoint creates or updates a role definition.
functionality. See the plugin's API page for more information on support and
formatting for this parameter.
@include 'db-secrets-credential-types.mdx'
### Sample Payload
```json
@ -369,6 +371,7 @@ $ curl \
"CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}';",
"GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";"
],
"credential_type": "password",
"db_name": "mysql",
"default_ttl": 3600,
"max_ttl": 86400,
@ -501,6 +504,8 @@ this in order to know the password.
plugin type will support this functionality. See the plugin's API page for
more information on support and formatting for this parameter.
@include 'db-secrets-credential-types.mdx'
### Sample Payload
```json
@ -550,6 +555,7 @@ $ curl \
```json
{
"data": {
"credential_type": "password",
"db_name": "mysql",
"username": "static-user",
"rotation_statements": [

View File

@ -90,9 +90,13 @@ list the plugin does not support that statement type.
statements executed to create and configure a user. Must be a
semicolon-separated string, a base64-encoded semicolon-separated string, a
serialized JSON string array, or a base64-encoded serialized JSON string
array. The `{{name}}`, `{{password}}` and `{{expiration}}` values will be
substituted. The generated password will be a random alphanumeric 20 character
string.
array. The `{{name}}` and `{{expiration}}` values will be substituted.
The following values will be substituted depending on the
[credential_type](/api-docs/secret/databases#credential_type) of the role:
- `{{password}}` is substituted for the `password` credential type
- `{{public_key}}` is substituted for the `rsa_private_key` credential type
- `revocation_statements` `(list: [])` Specifies the database statements to
be executed to revoke a user. Must be a semicolon-separated string, a
@ -118,5 +122,10 @@ list the plugin does not support that statement type.
executed to rotate the password for a given username. Must be a
semicolon-separated string, a base64-encoded semicolon-separated string, a
serialized JSON string array, or a base64-encoded serialized JSON string
array. The `{{name}}` and `{{password}}` values will be substituted. The
generated password will be a random alphanumeric 20 character string.
array. The `{{name}}` value will be substituted.
The following values will be substituted depending on the
[credential_type](/api-docs/secret/databases#credential_type) of the role:
- `{{password}}` is substituted for the `password` credential type
- `{{public_key}}` is substituted for the `rsa_private_key` credential type

View File

@ -36,10 +36,9 @@ When credentials are requested for the Role, Vault returns the current
password for the configured database user, allowing anyone with the proper
Vault policies to have access to the user account in the database.
~> Not all database types support static roles at this time. Please consult the
specific database documentation on the left navigation or the table below under
[Database Capabilities](#database-capabilities) to see if a given database
backend supports static roles.
-> Please consult the specific database documentation on the left navigation or
the table below under [Database Capabilities](#database-capabilities) to see if
a given database backend supports static roles.
## Setup
@ -134,21 +133,21 @@ As of Vault 1.6, all databases support dynamic roles and static roles. All plugi
the root user's credentials. MongoDB Atlas cannot support rotating the root user's credentials because it uses a public
and private key pair to authenticate.
| Database | Root Credential Rotation | Dynamic Roles | Static Roles | Username Customization |
| ----------------------------------------------------- | ------------------------ | ------------- | ------------ | ---------------------- |
| [Cassandra](/docs/secrets/databases/cassandra) | Yes | Yes | Yes (1.6+) | Yes (1.7+) |
| [Couchbase](/docs/secrets/databases/couchbase) | Yes | Yes | Yes | Yes (1.7+) |
| [Elasticsearch](/docs/secrets/databases/elasticdb) | Yes | Yes | Yes (1.6+) | Yes (1.8+) |
| [HanaDB](/docs/secrets/databases/hanadb) | Yes (1.6+) | Yes | Yes (1.6+) | No |
| [InfluxDB](/docs/secrets/databases/influxdb) | Yes | Yes | Yes (1.6+) | Yes (1.8+) |
| [MongoDB](/docs/secrets/databases/mongodb) | Yes | Yes | Yes | Yes (1.7+) |
| [MongoDB Atlas](/docs/secrets/databases/mongodbatlas) | No | Yes | Yes | Yes (1.8+) |
| [MSSQL](/docs/secrets/databases/mssql) | Yes | Yes | Yes | Yes (1.7+) |
| [MySQL/MariaDB](/docs/secrets/databases/mysql-maria) | Yes | Yes | Yes | Yes (1.7+) |
| [Oracle](/docs/secrets/databases/oracle) | Yes | Yes | Yes | Yes (1.7+) |
| [PostgreSQL](/docs/secrets/databases/postgresql) | Yes | Yes | Yes | Yes (1.7+) |
| [Redshift](/docs/secrets/databases/redshift) | Yes | Yes | Yes | Yes (1.8+) |
| [Snowflake](/docs/secrets/databases/snowflake) | Yes | Yes | Yes | Yes (1.8+) |
| Database | Root Credential Rotation | Dynamic Roles | Static Roles | Username Customization | Credential Types |
| ----------------------------------------------------- | ------------------------ | ------------- | ------------ | ---------------------- |---------------------------|
| [Cassandra](/docs/secrets/databases/cassandra) | Yes | Yes | Yes (1.6+) | Yes (1.7+) | password |
| [Couchbase](/docs/secrets/databases/couchbase) | Yes | Yes | Yes | Yes (1.7+) | password |
| [Elasticsearch](/docs/secrets/databases/elasticdb) | Yes | Yes | Yes (1.6+) | Yes (1.8+) | password |
| [HanaDB](/docs/secrets/databases/hanadb) | Yes (1.6+) | Yes | Yes (1.6+) | No | password |
| [InfluxDB](/docs/secrets/databases/influxdb) | Yes | Yes | Yes (1.6+) | Yes (1.8+) | password |
| [MongoDB](/docs/secrets/databases/mongodb) | Yes | Yes | Yes | Yes (1.7+) | password |
| [MongoDB Atlas](/docs/secrets/databases/mongodbatlas) | No | Yes | Yes | Yes (1.8+) | password |
| [MSSQL](/docs/secrets/databases/mssql) | Yes | Yes | Yes | Yes (1.7+) | password |
| [MySQL/MariaDB](/docs/secrets/databases/mysql-maria) | Yes | Yes | Yes | Yes (1.7+) | password |
| [Oracle](/docs/secrets/databases/oracle) | Yes | Yes | Yes | Yes (1.7+) | password |
| [PostgreSQL](/docs/secrets/databases/postgresql) | Yes | Yes | Yes | Yes (1.7+) | password |
| [Redshift](/docs/secrets/databases/redshift) | Yes | Yes | Yes | Yes (1.8+) | password |
| [Snowflake](/docs/secrets/databases/snowflake) | Yes | Yes | Yes | Yes (1.8+) | password, rsa_private_key |
## Custom Plugins
@ -156,6 +155,16 @@ This secrets engine allows custom database types to be run through the exposed
plugin interface. Please see the [custom database plugin](/docs/secrets/databases/custom)
for more information.
## Credential Types
Database systems support a variety of authentication methods and credential types.
The database secrets engine supports management of credentials alternative to usernames
and passwords. The [credential_type](/api-docs/secret/databases#credential_type)
and [credential_config](/api-docs/secret/databases#credential_config) parameters
of dynamic and static roles configure the credential that Vault will generate and
make available to database plugins. See the documentation of individual database
plugins for the credential types they support and usage examples.
## Password Generation
Passwords are generated via [Password Policies](/docs/concepts/password-policies).

View File

@ -9,49 +9,27 @@ description: |-
# Snowflake Database Secrets Engine
Snowflake is one of the supported plugins for the database secrets engine. This
plugin generates database credentials dynamically based on configured roles for
Snowflake hosted databases, and also supports [Static
Roles](/docs/secrets/databases#static-roles).
Snowflake is one of the supported plugins for the database secrets engine. This plugin
generates database credentials dynamically based on configured roles for Snowflake-hosted
databases and supports [Static Roles](/docs/secrets/databases#static-roles).
See the [database secrets engine](/docs/secrets/databases) docs for
more information about setting up the database secrets engine.
The Snowflake secrets engine uses
The Snowflake database secrets engine uses
[gosnowflake](https://pkg.go.dev/github.com/snowflakedb/gosnowflake).
A properly formatted data source name (DSN) needs to be provided during configuration of the
database. This DSN is typically formatted with the following options:
```text
{{username}}:{{password}}@account/db_name
```
`{{username}}` and `{{password}}` will typically be used as is during configuration. The
special formatting is replaced by the username and password options passed to the configuration
for initial connection.
`account` is your Snowflake account identifier. You can find out more about this value by reading
the `server` section of
[this document](https://docs.snowflake.com/en/user-guide/odbc-parameters.html#connection-parameters).
`db_name` is the name of a database in your snowflake instance.
Please note: the user being utilized should have `ACCOUNT_ADMIN` privileges, and should be different
from the root user you were provided when making your Snowflake account. This allows you to rotate
the root credentials and still be able to access your account should something go awry.
## Capabilities
| Plugin Name | Root Credential Rotation | Dynamic Roles | Static Roles | Username Customization |
| --------------------------- | ------------------------ | ------------- | ------------ | ---------------------- |
| `snowflake-database-plugin` | Yes | Yes | Yes | Yes (1.8+) |
| Plugin Name | Root Credential Rotation | Dynamic Roles | Static Roles | Username Customization | Credential Types |
| --------------------------- | ------------------------ | ------------- | ------------ | ---------------------- |---------------------------|
| `snowflake-database-plugin` | Yes | Yes | Yes | Yes (1.8+) | password, rsa_private_key |
## Setup
1. Enable the database secrets engine if it is not already enabled:
```text
```shell-session
$ vault secrets enable database
Success! Enabled the database secrets engine at: database/
```
@ -61,7 +39,7 @@ the root credentials and still be able to access your account should something g
1. Configure Vault with the proper plugin and connection information:
```text
```shell-session
$ vault write database/config/my-snowflake-database \
plugin_name=snowflake-database-plugin \
allowed_roles="my-role" \
@ -70,38 +48,174 @@ the root credentials and still be able to access your account should something g
password="vaultpass"
```
1. Configure a role that maps a name in Vault to an SQL statement to execute to
create the database credential:
A properly formatted data source name (DSN) needs to be provided during configuration of the
database. This DSN is typically formatted with the following options:
```text
$ vault write database/roles/my-role \
db_name=my-snowflake-database \
creation_statements="CREATE USER {{name}} PASSWORD = '{{password}}' DAYS_TO_EXPIRY = {{expiration}} DEFAULT_ROLE=myrole;
GRANT ROLE myrole TO USER {{name}};" \
default_ttl="1h" \
max_ttl="24h"
Success! Data written to: database/roles/my-role
```shell-session
{{username}}:{{password}}@account/db_name
```
`{{username}}` and `{{password}}` will typically be used as is during configuration. The
special formatting is replaced by the username and password options passed to the configuration
for initial connection.
`account` is your Snowflake account identifier. You can find out more about this value by reading
the `server` section of
[this document](https://docs.snowflake.com/en/user-guide/odbc-parameters.html#connection-parameters).
`db_name` is the name of a database in your Snowflake instance.
~> **Note:** The user being utilized should have `ACCOUNT_ADMIN` privileges, and should be different
from the root user you were provided when making your Snowflake account. This allows you to rotate
the root credentials and still be able to access your account.
## Usage
After the secrets engine is configured and a user/machine has a Vault token with
the proper permission, it can generate credentials.
After the secrets engine is configured, configure dynamic and static roles to
enable generating credentials.
### Dynamic Roles
#### Password Credentials
1. Configure a role that creates new Snowflake users with password credentials:
```shell-session
$ vault write database/roles/my-password-role \
db_name=my-snowflake-database \
creation_statements="CREATE USER {{name}} PASSWORD = '{{password}}'
DAYS_TO_EXPIRY = {{expiration}} DEFAULT_ROLE=myrole;
GRANT ROLE myrole TO USER {{name}};" \
default_ttl="1h" \
max_ttl="24h"
Success! Data written to: database/roles/my-password-role
```
1. Generate a new credential by reading from the `/creds` endpoint with the name
of the role:
```text
$ vault read database/creds/my-role
```shell-session
$ vault read database/creds/my-password-role
Key Value
--- -----
lease_id database/creds/my-role/2f6a614c-4aa2-7b19-24b9-ad944a8d4de6
lease_id database/creds/my-password-role/2f6a614c-4aa2-7b19-24b9-ad944a8d4de6
lease_duration 1h
lease_renewable true
password SsnoaA-8Tv4t34f41baD
username v_root_my_role_fU0jqEy4wMNoAY2h60yd_1610561532
username v_root_my_password_role_fU0jqEy4wMNoAY2h60yd_1610561532
```
#### Key Pair Credentials
1. Configure a role that creates new Snowflake users with key pair credentials:
```shell-session
$ vault write database/roles/my-keypair-role \
db_name=my-snowflake-database \
creation_statements="CREATE USER {{name}} RSA_PUBLIC_KEY='{{public_key}}'
DAYS_TO_EXPIRY = {{expiration}} DEFAULT_ROLE=myrole;
GRANT ROLE myrole TO USER {{name}};" \
credential_type="rsa_private_key" \
credential_config=key_bits=2048 \
default_ttl="1h" \
max_ttl="24h"
Success! Data written to: database/roles/my-keypair-role
```
1. Generate a new credential by reading from the `/creds` endpoint with the name
of the role:
```shell-session
$ vault read database/creds/my-keypair-role
Key Value
--- -----
lease_id database/creds/my-keypair-role/2f6a614c-4aa2-7b19-24b9-ad944a8d4de6
lease_duration 1h
lease_renewable true
rsa_private_key -----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----
username v_token_my_keypair_role_n20WjS9U3LWTlBWn4Wbh_1654718170
```
You can directly use the PEM-encoded `rsa_private_key` value to establish a connection
to Snowflake. See [connection options](https://docs.snowflake.com/en/user-guide/key-pair-auth.html#step-6-configure-the-snowflake-client-to-use-key-pair-authentication)
for a list of clients and instructions for establishing a connection using key pair
authentication.
### Static Roles
#### Password Credentials
1. Configure a static role that rotates the password credential for an existing Snowflake user.
```shell-session
$ vault write database/static-roles/my-password-role \
db_name=my-snowflake-database \
username="snowflake_existing_user" \
rotation_period="24h" \
rotation_statements="ALTER USER {{name}} SET PASSWORD = '{{password}}'"
Success! Data written to: database/static-roles/my-password-role
```
1. Retrieve the current password credential from the `/static-creds` endpoint:
```shell-session
$ vault read database/static-creds/my-password-role
Key Value
--- -----
last_vault_rotation 2020-08-07T16:50:48.393354+01:00
password Z4-KH8F-VK5VJc0hSkXQ
rotation_period 24h
ttl 23h59m39s
username my-existing-couchbase-user
```
#### Key Pair Credentials
1. Configure a static role that rotates the key pair credential for an existing Snowflake user:
```shell-session
$ vault write database/static-roles/my-keypair-role \
db_name=my-snowflake-database \
username="snowflake_existing_user" \
rotation_period="24h" \
rotation_statements="ALTER USER {{name}} SET RSA_PUBLIC_KEY='{{public_key}}'" \
credential_type="rsa_private_key" \
credential_config=key_bits=2048
Success! Data written to: database/static-roles/my-keypair-role
```
1. Retrieve the current key pair credential from the `/static-creds` endpoint:
```shell-session
$ vault read database/static-creds/my-keypair-role
Key Value
--- -----
last_vault_rotation 2022-06-08T13:13:02.355928-07:00
rotation_period 24h
rsa_private_key -----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----
ttl 23h59m55s
username snowflake_existing_user
```
You can directly use the PEM-encoded `rsa_private_key` value to establish a connection
to Snowflake. See [connection options](https://docs.snowflake.com/en/user-guide/key-pair-auth.html#step-6-configure-the-snowflake-client-to-use-key-pair-authentication)
for a list of clients and instructions for establishing a connection using key pair
authentication.
## Key Pair Authentication
Snowflake supports using [key pair authentication](https://docs.snowflake.com/en/user-guide/key-pair-auth.html)
for enhanced authentication security as an alternative to username and password authentication.
The Snowflake database plugin can be used to manage key pair credentials for Snowflake users
by using the `rsa_private_key` [credential_type](/api-docs/secret/databases#credential_type).
See the [usage](/docs/secrets/databases/snowflake#usage) section for examples using both
dynamic and static roles.
## API
The full list of configurable options can be seen in the [Snowflake database

View File

@ -0,0 +1,20 @@
- `credential_type` `(string: "password")` Specifies the type of credential that
will be generated for the role. Options include: `password`, `rsa_private_key`.
See the plugin's API page for credential types supported by individual databases.
- `credential_config` `(map<string|string>: <optional>)` Specifies the configuration
for the given `credential_type`.
The following options are available for each `credential_type` value:
- `password`
- `password_policy` `(string: <optional>)` - The [policy](/docs/concepts/password-policies)
used for password generation. If not provided, defaults to the password policy of the
database [configuration](/api-docs/secret/databases#password_policy).
- `rsa_private_key`
- `key_bits` `(int: 2048)` - The bit size of the RSA key to generate. Options include:
`2048`, `3072`, `4096`.
- `format` `(string: "pkcs8")` - The output format of the generated private key
credential. The private key will be returned from the API in PEM encoding. Options
include: `pkcs8`.