crypto: deprecate native Hashicorp Vault support (#11352)

This commit deprecates the native Hashicorp Vault
support and removes the legacy Vault documentation.

The native Hashicorp Vault documentation is marked as
outdated and deprecated for over a year now. We give
another 6 months before we start removing Hashicorp Vault
support and show a deprecation warning when a MinIO server
starts with a native Vault configuration.
master
Andreas Auernhammer 3 years ago committed by GitHub
parent 451d9057f3
commit 33554651e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 35
      cmd/admin-handlers.go
  2. 10
      cmd/config-current.go
  3. 18
      docs/kms/vault-config.json
  4. 269
      docs/kms/vault-legacy.md
  5. 6
      pkg/madmin/info-commands.go

@ -1544,7 +1544,7 @@ func (a adminAPIHandlers) ServerInfoHandler(w http.ResponseWriter, r *http.Reque
return
}
vault := fetchVaultStatus()
kmsStat := fetchKMSStatus()
ldap := madmin.LDAP{}
if globalLDAPConfig.Enabled {
@ -1613,7 +1613,7 @@ func (a adminAPIHandlers) ServerInfoHandler(w http.ResponseWriter, r *http.Reque
domain := globalDomainNames
services := madmin.Services{
Vault: vault,
KMS: kmsStat,
LDAP: ldap,
Logger: log,
Audit: audit,
@ -1689,47 +1689,46 @@ func fetchLambdaInfo() []map[string][]madmin.TargetIDStatus {
return notify
}
// fetchVaultStatus fetches Vault Info
func fetchVaultStatus() madmin.Vault {
vault := madmin.Vault{}
// fetchKMSStatus fetches KMS-related status information.
func fetchKMSStatus() madmin.KMS {
kmsStat := madmin.KMS{}
if GlobalKMS == nil {
vault.Status = "disabled"
return vault
kmsStat.Status = "disabled"
return kmsStat
}
keyID := GlobalKMS.DefaultKeyID()
kmsInfo := GlobalKMS.Info()
if len(kmsInfo.Endpoints) == 0 {
vault.Status = "KMS configured using master key"
return vault
kmsStat.Status = "KMS configured using master key"
return kmsStat
}
if err := checkConnection(kmsInfo.Endpoints[0], 15*time.Second); err != nil {
vault.Status = "offline"
kmsStat.Status = "offline"
} else {
vault.Status = "online"
kmsStat.Status = "online"
kmsContext := crypto.Context{"MinIO admin API": "ServerInfoHandler"} // Context for a test key operation
// 1. Generate a new key using the KMS.
key, sealedKey, err := GlobalKMS.GenerateKey(keyID, kmsContext)
if err != nil {
vault.Encrypt = fmt.Sprintf("Encryption failed: %v", err)
kmsStat.Encrypt = fmt.Sprintf("Encryption failed: %v", err)
} else {
vault.Encrypt = "Ok"
kmsStat.Encrypt = "Ok"
}
// 2. Verify that we can indeed decrypt the (encrypted) key
decryptedKey, err := GlobalKMS.UnsealKey(keyID, sealedKey, kmsContext)
switch {
case err != nil:
vault.Decrypt = fmt.Sprintf("Decryption failed: %v", err)
kmsStat.Decrypt = fmt.Sprintf("Decryption failed: %v", err)
case subtle.ConstantTimeCompare(key[:], decryptedKey[:]) != 1:
vault.Decrypt = "Decryption failed: decrypted key does not match generated key"
kmsStat.Decrypt = "Decryption failed: decrypted key does not match generated key"
default:
vault.Decrypt = "Ok"
kmsStat.Decrypt = "Ok"
}
}
return vault
return kmsStat
}
// fetchLoggerDetails return log info

@ -480,11 +480,13 @@ func lookupConfigs(s config.Config, setDriveCounts []int) {
if err != nil {
logger.LogIf(ctx, fmt.Errorf("Unable to setup KMS with current KMS config: %w", err))
}
globalAutoEncryption = kmsCfg.AutoEncryption // Enable auto-encryption if enabled
// Enable auto-encryption if enabled
globalAutoEncryption = kmsCfg.AutoEncryption
if globalAutoEncryption && !globalIsGateway {
logger.LogIf(ctx, fmt.Errorf("%s env is deprecated please migrate to using `mc encrypt` at bucket level", crypto.EnvKMSAutoEncryption))
if kmsCfg.Vault.Enabled {
const deprecationWarning = `Native Hashicorp Vault support is deprecated and will be removed on 2021-10-01. Please migrate to KES + Hashicorp Vault: https://github.com/minio/kes/wiki/Hashicorp-Vault-Keystore
Note that native Hashicorp Vault and KES + Hashicorp Vault are not compatible.
If you need help to migrate smoothly visit: https://min.io/pricing`
logger.LogIf(ctx, fmt.Errorf(deprecationWarning))
}
globalOpenIDConfig, err = openid.LookupConfig(s[config.IdentityOpenIDSubSys][config.Default],

@ -1,18 +0,0 @@
{
"api_addr": "https://127.0.0.1:8200",
"backend": {
"file": {
"path": "vault/file"
}
},
"default_lease_ttl": "168h",
"max_lease_ttl": "720h",
"listener": {
"tcp": {
"address": "0.0.0.0:8200",
"tls_cert_file": "vault-tls.crt",
"tls_key_file": "vault-tls.key",
"tls_min_version": "tls12"
}
}
}

@ -1,269 +0,0 @@
# KMS Quickstart Guide [![Slack](https://slack.min.io/slack?type=svg)](https://slack.min.io)
MinIO uses a key-management-system (KMS) to support SSE-S3. If a client requests SSE-S3, or auto-encryption
is enabled, the MinIO server encrypts each object with an unique object key which is protected by a master key
managed by the KMS. Usually all object keys are protected by a single master key.
MinIO supports two different KMS concepts:
- External KMS:
MinIO can be configured to use an external KMS i.e. [Hashicorp Vault](https://www.vaultproject.io/).
An external KMS decouples MinIO as storage system from key-management. An external KMS can
be managed by a dedicated security team and allows you to grant/deny access to (certain) objects
by enabling or disabling the corresponding master keys on demand.
- Direct KMS master keys:
MinIO can also be configured to directly use a master key specified by the environment variable `MINIO_KMS_MASTER_KEY` or with a docker secret key.
Direct master keys are useful if the storage backend is not on the same machine as the MinIO server, e.g.,
if network drives or MinIO gateway is used and an external KMS would cause too much management overhead.
Note: KMS master keys are mainly for testing purposes. It's not recommended to use them for production deployments.
Further if the MinIO server machine is ever compromised, then the master key must also be treated as compromised.
**Important:**
If multiple MinIO servers are configured as [gateways](https://github.com/minio/minio/blob/master/docs/gateway/README.md) pointing to the *same* backend - for example the same NAS storage - then the KMS configuration **must** be the same for all gateways. Otherwise one gateway may not be able to decrypt objects created by another gateway. It is the operator responsibility to ensure consistency.
## Get started
### 1. Prerequisites
Install MinIO - [MinIO Quickstart Guide](https://docs.min.io/docs/minio-quickstart-guide).
### 2. Setup a KMS
Either use Hashicorp Vault as external KMS or specify a master key directly depending on your use case.
#### 2.1 Setup Hashicorp Vault
Here is a sample quick start for configuring vault with a transit backend and Approle with correct policy
MinIO requires the following Vault setup:
- The [transit backend](https://www.vaultproject.io/api/secret/transit/index.html) configured with a named encryption key-ring
- [AppRole](https://www.vaultproject.io/docs/auth/approle.html) based authentication with read/update policy for transit backend. In particular, read and update policy are required for the [Generate Data Key](https://www.vaultproject.io/api/secret/transit/index.html#generate-data-key) endpoint and [Decrypt Data](https://www.vaultproject.io/api/secret/transit/index.html#decrypt-data) endpoint.
**2.1.1 Start Vault server**
Vault requires access to `mlock` syscall by default. Use `setcap` to give the Vault executable the ability to use the `mlock` syscall without running the process as root. To do so run:
```
sudo setcap cap_ipc_lock=+ep $(readlink -f $(which vault))
```
Create `vault-config.json` to use file backend and start the server.
```
cat > vault-config.json <<EOF
{
"api_addr": "http://127.0.0.1:8200",
"backend": {
"file": {
"path": "vault/file"
}
},
"default_lease_ttl": "168h",
"max_lease_ttl": "720h",
"listener": {
"tcp": {
"address": "0.0.0.0:8200",
"tls_disable": true
}
},
"ui": true
}
EOF
vault server -config vault-config.json
```
> NOTE: In this example we use `"tls_disable": true` for demonstration purposes only,
> in production setup you should generate proper TLS certificates by specifying
> - [`tls_cert_file`](https://www.vaultproject.io/docs/configuration/listener/tcp.html#tls_cert_file)
> - [`tls_key_file`](https://www.vaultproject.io/docs/configuration/listener/tcp.html#tls_key_file)
**2.1.2 Initialize vault and unseal it**
```
export VAULT_ADDR='http://127.0.0.1:8200'
vault operator init
Unseal Key 1: eyW/+8ZtsgT81Cb0e8OVxzJAQP5lY7Dcamnze+JnWEDT
Unseal Key 2: 0tZn+7QQCxphpHwTm6/dC3LpP5JGIbYl6PK8Sy79R+P2
Unseal Key 3: cmhs+AUMXUuB6Lzsvgcbp3bRT6VDGQjgCBwB2xm0ANeF
Unseal Key 4: /fTPpec5fWpGqWHK+uhnnTNMQyAbl5alUi4iq2yNgyqj
Unseal Key 5: UPdDVPto+H6ko+20NKmagK40MOskqOBw4y/S51WpgVy/
Initial Root Token: s.zaU4Gbcu0Wh46uj2V3VuUde0
Vault is initialized with 5 key shares and a key threshold of 3. Please securely
distribute the key shares printed above. When the Vault is re-sealed,
restarted, or stopped, you must supply at least 3 of these keys to unseal it
before it can start servicing requests.
Vault does not store the generated master key. Without at least 3 key to
reconstruct the master key, Vault will remain permanently sealed!
It is possible to generate new unseal keys, provided you have a quorum of
existing unseal keys shares. See "vault operator rekey" for more information.
```
Use any of the previously generated keys to unseal the vault
```
vault operator unseal eyW/+8ZtsgT81Cb0e8OVxzJAQP5lY7Dcamnze+JnWEDT
vault operator unseal 0tZn+7QQCxphpHwTm6/dC3LpP5JGIbYl6PK8Sy79R+P2
vault operator unseal cmhs+AUMXUuB6Lzsvgcbp3bRT6VDGQjgCBwB2xm0ANeF
Key Value
--- -----
Seal Type shamir
Initialized true
Sealed false ---> NOTE: vault is unsealed
Total Shares 5
Threshold 3
Version 1.1.3
Cluster Name vault-cluster-3f084948
Cluster ID 8c92e999-7062-4da6-4434-0fc05f34824d
HA Enabled false
```
Obtain root token from the `vault operator init` output above. It is displayed as `Initial Root Token: s.zaU4Gbcu0Wh46uj2V3VuUde0`
**2.1.3 Set up vault transit backend and create an app role**
```
export VAULT_TOKEN=s.zaU4Gbcu0Wh46uj2V3VuUde0
vault auth enable approle # enable approle style auth
vault secrets enable transit # enable transit secrets engine
# define an encryption key-ring for the transit path
vault write -f transit/keys/my-minio-key
cat > vaultpolicy.hcl <<EOF
path "transit/datakey/plaintext/my-minio-key" {
capabilities = [ "read", "update"]
}
path "transit/decrypt/my-minio-key" {
capabilities = [ "read", "update"]
}
path "transit/rewrap/my-minio-key" {
capabilities = ["update"]
}
EOF
# define a policy for AppRole to access transit path
vault policy write minio-policy ./vaultpolicy.hcl
# period indicates it is renewable if token is renewed before the period is over
vault write auth/approle/role/my-role token_num_uses=0 secret_id_num_uses=0 period=5m
# define an AppRole
vault write auth/approle/role/my-role policies=minio-policy # apply policy to role
vault read auth/approle/role/my-role/role-id # get Approle ID
Key Value
--- -----
role_id 8c03926c-6c51-7a1d-cf7d-62e48ab8d6d7
vault write -f auth/approle/role/my-role/secret-id
Key Value
--- -----
secret_id edd8738c-6efe-c226-74f9-ef5b66e119d7
secret_id_accessor 57d1db64-6350-c321-4a3e-fc6aeb7d00b6
```
The AppRole ID, AppRole Secret Id, Vault endpoint and Vault key name can now be used to start minio server with Vault as KMS.
**2.1.3 Vault Environment variables**
You'll need the Vault endpoint, AppRole ID, AppRole SecretID and encryption key-ring name defined in step 2.1.2
```
export MINIO_KMS_VAULT_APPROLE_ID=8c03926c-6c51-7a1d-cf7d-62e48ab8d6d7
export MINIO_KMS_VAULT_APPROLE_SECRET=edd8738c-6efe-c226-74f9-ef5b66e119d7
export MINIO_KMS_VAULT_ENDPOINT=http://vault-endpoint-ip:8200
export MINIO_KMS_VAULT_KEY_NAME=my-minio-key
export MINIO_KMS_VAULT_AUTH_TYPE=approle
minio server ~/export
```
Optionally, set `MINIO_KMS_VAULT_CAPATH` to a directory of PEM-encoded CA cert files to use mTLS for client-server authentication.
```
export MINIO_KMS_VAULT_CAPATH=/home/user/custom-certs
```
An additional option is to set `MINIO_KMS_VAULT_NAMESPACE` if AppRole and Transit Secrets engine have been scoped to Vault Namespace
```
export MINIO_KMS_VAULT_NAMESPACE=ns1
```
Note: If [Vault Namespaces](https://learn.hashicorp.com/vault/operations/namespaces) are in use, MINIO_KMS_VAULT_VAULT_NAMESPACE variable needs to be set before setting approle and transit secrets engine.
#### 2.2 Specify a master key
**2.2.1 KMS master key from environment variables**
A KMS master key consists of a master-key ID (CMK) and the 256 bit master key encoded as HEX value separated by a `:`.
A KMS master key can be specified directly using:
```
export MINIO_KMS_MASTER_KEY=my-minio-key:6368616e676520746869732070617373776f726420746f206120736563726574
```
Please use your own master key. A random master key can be generated using e.g. this command on Linux/Mac/BSD* systems:
```
head -c 32 /dev/urandom | xxd -c 32 -ps
```
**2.2.2 KMS master key from docker secret**
Alternatively, you may pass a master key as a [Docker secret](https://docs.docker.com/engine/swarm/secrets/).
```bash
echo "my-minio-key:6368616e676520746869732070617373776f726420746f206120736563726574" | docker secret create kms_master_key
```
Obviously, do not use this demo key for anything real!
To use another secret name, follow the instructions above and replace kms_master_key with your custom names (e.g. my_kms_master_key). Then, set the MINIO_KMS_MASTER_KEY_FILE environment variable to your secret name:
```bash
export MINIO_KMS_MASTER_KEY_FILE=my_kms_master_key
```
### 3. Test your setup
To test this setup, start minio server with environment variables set in Step 3, and server is ready to handle SSE-S3 requests.
### Auto-Encryption
MinIO can also enable auto-encryption **if** a valid KMS configuration is specified and the storage backend supports
encrypted objects. Auto-Encryption, if enabled, ensures that all uploaded objects are encrypted using the specified
KMS configuration.
Auto-Encryption is useful especially if the MinIO operator wants to ensure that objects are **never** stored in
plaintext - for example if sensitive data is stored on public cloud storage.
To enable auto-encryption set the environment variable to `on`:
```
export MINIO_KMS_AUTO_ENCRYPTION=on
```
To verify auto-encryption, use the `mc` command:
```
mc cp test.file myminio/crypt/
test.file: 5 B / 5 B ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ 100.00% 337 B/s 0s
mc stat myminio/crypt/test.file
Name : test.file
...
Encrypted :
X-Amz-Server-Side-Encryption: AES256
```
Note: Auto-Encryption only affects non-SSE-C requests since objects uploaded using SSE-C are already encrypted
and S3 only allows either SSE-S3 or SSE-C but not both for the same object.
# Explore Further
- [Use `mc` with MinIO Server](https://docs.min.io/docs/minio-client-quickstart-guide)
- [Use `aws-cli` with MinIO Server](https://docs.min.io/docs/aws-cli-with-minio)
- [Use `s3cmd` with MinIO Server](https://docs.min.io/docs/s3cmd-with-minio)
- [Use `minio-go` SDK with MinIO Server](https://docs.min.io/docs/golang-client-quickstart-guide)
- [The MinIO documentation website](https://docs.min.io)

@ -188,7 +188,7 @@ type InfoMessage struct {
// Services contains different services information
type Services struct {
Vault Vault `json:"vault,omitempty"`
KMS KMS `json:"kms,omitempty"`
LDAP LDAP `json:"ldap,omitempty"`
Logger []Logger `json:"logger,omitempty"`
Audit []Audit `json:"audit,omitempty"`
@ -210,8 +210,8 @@ type Usage struct {
Size uint64 `json:"size,omitempty"`
}
// Vault - Fetches the Vault status
type Vault struct {
// KMS contains KMS status information
type KMS struct {
Status string `json:"status,omitempty"`
Encrypt string `json:"encrypt,omitempty"`
Decrypt string `json:"decrypt,omitempty"`

Loading…
Cancel
Save