Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bucket replication with KMS is broken in 7.0.0 #2390

Open
dhess opened this issue Feb 2, 2025 · 7 comments
Open

Bucket replication with KMS is broken in 7.0.0 #2390

dhess opened this issue Feb 2, 2025 · 7 comments

Comments

@dhess
Copy link

dhess commented Feb 2, 2025

Hi!

We believe that version 7.0.0 of the operator has broken bucket replication, specifically something related to kes and KMS.

Our setup:

  • Site A cluster-a runs the MinIO operator and 2 tenants, lake-0 and nvme-0.

  • Site C cluster-c runs the MinIO operator and 1 tenant, lake-1.

All 3 tenants are encrypted using kes, and share a common Vault service for KMS.

Site A tenants lake-0 and nvme-0 each have multiple buckets that are configured to replicate (via bucket replication) to Site C tenant lake-1. This has been working very well for about 8 months.

On Jan 30, we upgraded the MinIO operators and tenants in both cluster-a and cluster-c from version 6.0.4 to to version 7.0.0, via the operator and tenant Helm charts.

Since then, we noticed that new objects in replicated buckets in Site A tenants lake-0 and nvme-0 were no longer replicating to Site C tenant lake-1. All of the objects in question are marked as FAILED, and attempts to retry them via mc ls, mc stat, etc., do not resolve the issue, nor does restarting the tenants and/or operators, as we've sometimes needed to do in the past to restart the replication process.

After some investigation and spelunking through logs, it appears that shortly after we upgraded the operators and tenants to version 7.0.0, lake-1's kes started requesting non-existent keys from the Vault KMS. These bogus requests appear to be caused by replication attempts from the lake-0 and nvme-0 tenants.

Here's an example of a bad request from the logs of lake-1's kes, sampled from shortly after the upgrade:

{
  "time": "2025-01-30T23:43:03.415228411Z",
  "request": {
    "ip": "10.70.1.176",
    "path": "/v1/key/generate/nvme-0-key",
    "identity": "624268fb0afa9a64b0ae8047c54e37024d5808aa3d7110bcca9ccf8c997401cf"
  },
  "response": {
    "code": 404,
    "time": 1975831000
  }
}

Here's an example of what Vault sees, taken from the logs of the shared Vault KMS and sampled around the same time as the previous request. (This may not be the precise response to that request, as there are a lot of them, but they all have the same path.)

{
  "auth": {
    "accessor": "hmac-sha256:e0d4beb86b3546cd6d0b9615160631d83864cdfebaca238444b1543087849455",
    "client_token": "hmac-sha256:4b348f3f093987f1be08ebc0c963e5cdf271426cc5f9f109e59dc1c7e8ee7a07",
    "display_name": "cluster-c-minio-lake-1-kes-sa",
    "entity_id": "9bfde683-4e64-0faa-1ad8-2b1aaa105020",
    "metadata": {
      "role": "minio-lake-1-kes",
      "service_account_name": "kes-sa",
      "service_account_namespace": "minio-lake-1",
      "service_account_secret_name": "",
      "service_account_uid": "f365f367-a347-440a-9508-b51406b58e62"
    },
    "policies": [
      "default",
      "minio-lake-1-kes"
    ],
    "policy_results": {
      "allowed": true,
      "granting_policies": [
        {
          "type": ""
        },
        {
          "name": "minio-lake-1-kes",
          "namespace_id": "root",
          "type": "acl"
        }
      ]
    },
    "token_policies": [
      "default",
      "minio-lake-1-kes"
    ],
    "token_issue_time": "2025-01-26T18:23:40Z",
    "token_ttl": 86400,
    "token_type": "service"
  },
  "request": {
    "client_id": "9bfde683-4e64-0faa-1ad8-2b1aaa105020",
    "client_token": "hmac-sha256:b579ca85e3df6c5c406587569210cecd46a959690afbb701595844aad2f5d290",
    "client_token_accessor": "hmac-sha256:e0d4beb86b3546cd6d0b9615160631d83864cdfebaca238444b1543087849455",
    "id": "2a873ef9-7f49-9f07-3ea3-a655f1a3b75f",
    "mount_class": "secret",
    "mount_point": "minio-lake-1/",
    "mount_running_version": "v0.20.0+builtin",
    "mount_type": "kv",
    "namespace": {
      "id": "root"
    },
    "operation": "read",
    "path": "minio-lake-1/data/minio-lake-1/nvme-0-key",
    "remote_address": "10.70.1.135",
    "remote_port": 60642
  },
  "time": "2025-01-30T23:43:03.288757958Z",
  "type": "request"
}

Indeed, no such key minio-lake-1/data/minio-lake-1/nvme-0-key exists in the Vault KMS's key-value store; only minio-lake-1/data/minio-lake-1/lake-1-key exists there.

Here's an example of how this problem manifests in mc admin trace lake-1:

lake-1-pool-0-0.lake-1-hl.minio-lake-1.svc.cluster.local:9000 [REQUEST s3.PutObject] [2025-02-02T14:49:18.325] [Client IP: 10.20.7.123]
lake-1-pool-0-0.lake-1-hl.minio-lake-1.svc.cluster.local:9000 PUT /media-barman/pg-cluster-media/wals/00000046000001F8/00000046000001F8000000B3.bz2?versionId=ccf86c6c-9041-4d92-8969-6071778d4506
lake-1-pool-0-0.lake-1-hl.minio-lake-1.svc.cluster.local:9000 Proto: HTTP/1.1
lake-1-pool-0-0.lake-1-hl.minio-lake-1.svc.cluster.local:9000 Host: lake-1.minio.[redacted]
lake-1-pool-0-0.lake-1-hl.minio-lake-1.svc.cluster.local:9000 X-Amz-Content-Sha256: UNSIGNED-PAYLOAD
lake-1-pool-0-0.lake-1-hl.minio-lake-1.svc.cluster.local:9000 X-Minio-Source-Replication-Request: true
lake-1-pool-0-0.lake-1-hl.minio-lake-1.svc.cluster.local:9000 X-Amz-Object-Lock-Mode: GOVERNANCE
lake-1-pool-0-0.lake-1-hl.minio-lake-1.svc.cluster.local:9000 Content-Length: 95867
lake-1-pool-0-0.lake-1-hl.minio-lake-1.svc.cluster.local:9000 Content-Type: binary/octet-stream
lake-1-pool-0-0.lake-1-hl.minio-lake-1.svc.cluster.local:9000 X-Minio-Source-Etag: 1bcccab66c48338351b390c082c5d0ea
lake-1-pool-0-0.lake-1-hl.minio-lake-1.svc.cluster.local:9000 X-Minio-Source-Mtime: 2025-02-01T04:48:39.871375438Z
lake-1-pool-0-0.lake-1-hl.minio-lake-1.svc.cluster.local:9000 X-Amz-Date: 20250202T144918Z
lake-1-pool-0-0.lake-1-hl.minio-lake-1.svc.cluster.local:9000 X-Amz-Replication-Status: REPLICA
lake-1-pool-0-0.lake-1-hl.minio-lake-1.svc.cluster.local:9000 X-Amz-Storage-Class: STANDARD
lake-1-pool-0-0.lake-1-hl.minio-lake-1.svc.cluster.local:9000 X-Amz-Server-Side-Encryption: aws:kms
lake-1-pool-0-0.lake-1-hl.minio-lake-1.svc.cluster.local:9000 X-Amz-Server-Side-Encryption-Aws-Kms-Key-Id: arn:aws:kms:nvme-0-key
lake-1-pool-0-0.lake-1-hl.minio-lake-1.svc.cluster.local:9000 X-Minio-Source-Replication-Retention-Timestamp: 2025-02-01T04:48:39.871375438Z
lake-1-pool-0-0.lake-1-hl.minio-lake-1.svc.cluster.local:9000 Authorization: AWS4-HMAC-SHA256 Credential=[redacted]/20250202/us-east-1/s3/aws4_request, SignedHeaders=content-type;host;x-amz-content-sha256;x-amz-date;x-amz-object-lock-mode;x-amz-object-lock-retain-until-date;x-amz-replication-status;x-amz-server-side-encryption;x-amz-server-side-encryption-aws-kms-key-id;x-amz-storage-class;x-minio-source-etag;x-minio-source-mtime;x-minio-source-replication-request;x-minio-source-replication-retention-timestamp, Signature=c0563b93e042cb7dbdbcffadafed49796dcc24fac05d39e2f587334086ba8f0f
lake-1-pool-0-0.lake-1-hl.minio-lake-1.svc.cluster.local:9000 User-Agent: MinIO (linux; amd64) minio-go/v7.0.77 minio-replication-target/RELEASE.2024-11-07T00-52-20Z arn:minio:replication::6adef648-e12e-4c7b-a2bf-c2718e649707:media-barman
lake-1-pool-0-0.lake-1-hl.minio-lake-1.svc.cluster.local:9000 X-Amz-Object-Lock-Retain-Until-Date: 2025-03-05T04:48:39Z
lake-1-pool-0-0.lake-1-hl.minio-lake-1.svc.cluster.local:9000 <BLOB>
lake-1-pool-0-0.lake-1-hl.minio-lake-1.svc.cluster.local:9000 [RESPONSE] [2025-02-02T14:51:12.247] [ Duration 1m53.9216s TTFB 1m53.921574209s ↑ 390 B  ↓ 510 B ]
lake-1-pool-0-0.lake-1-hl.minio-lake-1.svc.cluster.local:9000 500 Internal Server Error
lake-1-pool-0-0.lake-1-hl.minio-lake-1.svc.cluster.local:9000 X-Xss-Protection: 1; mode=block
lake-1-pool-0-0.lake-1-hl.minio-lake-1.svc.cluster.local:9000 Content-Type: application/xml
lake-1-pool-0-0.lake-1-hl.minio-lake-1.svc.cluster.local:9000 Server: MinIO
lake-1-pool-0-0.lake-1-hl.minio-lake-1.svc.cluster.local:9000 Strict-Transport-Security: max-age=31536000; includeSubDomains
lake-1-pool-0-0.lake-1-hl.minio-lake-1.svc.cluster.local:9000 Vary: Origin,Accept-Encoding
lake-1-pool-0-0.lake-1-hl.minio-lake-1.svc.cluster.local:9000 X-Content-Type-Options: nosniff
lake-1-pool-0-0.lake-1-hl.minio-lake-1.svc.cluster.local:9000 X-Ratelimit-Limit: 4120
lake-1-pool-0-0.lake-1-hl.minio-lake-1.svc.cluster.local:9000 Accept-Ranges: bytes
lake-1-pool-0-0.lake-1-hl.minio-lake-1.svc.cluster.local:9000 Content-Length: 510
lake-1-pool-0-0.lake-1-hl.minio-lake-1.svc.cluster.local:9000 X-Amz-Id-2: fe353d29ca0c4d7c9fa25206451adb7190a12401e5f659b127f0c3540ebe3609
lake-1-pool-0-0.lake-1-hl.minio-lake-1.svc.cluster.local:9000 X-Amz-Request-Id: 18206B985E46F778
lake-1-pool-0-0.lake-1-hl.minio-lake-1.svc.cluster.local:9000 X-Ratelimit-Remaining: 3804
lake-1-pool-0-0.lake-1-hl.minio-lake-1.svc.cluster.local:9000 <?xml version="1.0" encoding="UTF-8"?>
<Error><Code>kms:KeyGenerationFailed</Code><Message>failed to generate data key with KMS key</Message><Key>pg-cluster-media/wals/00000046000001F8/00000046000001F8000000B3.bz2</Key><BucketName>media-barman</BucketName><Resource>/media-barman/pg-cluster-media/wals/00000046000001F8/00000046000001F8000000B3.bz2</Resource><RequestId>18206B985E46F778</RequestId><HostId>fe353d29ca0c4d7c9fa25206451adb7190a12401e5f659b127f0c3540ebe3609</HostId></Error>
lake-1-pool-0-0.lake-1-hl.minio-lake-1.svc.cluster.local:9000

The examples shown above are for nvme-0 bucket replication, but we see similar errors in the logs for the lake-0 tenant, the key difference being that, for this tenant, lake-1's kes is requesting /v1/key/generate/lake-0-key rather than /v1/key/generate/nvme-0-key.

According to our logs, prior to the upgrade to 7.0.0, lake-1's kes previous only requested the KMS path /v1/key/generate/lake-1-key, and never /v1/key/generate/lake-0-key nor /v1/key/generate/nvme-0-key.

Expected Behavior

Bucket replication between 2 tenants, each using KMS, should work.

Current Behavior

kes in the replication destination tenant appears to look up the KMS key for the source bucket, which it does not know or have access to, instead of its own key.

Steps to Reproduce (for bugs)

  1. Using MinIO operator and tenant 6.0.4, set up bucket replication between 2 tenants each using Vault for KMS.
  2. Successfully replicate some objects.
  3. Upgrade the MinIO operator and tenant to 7.0.0.
  4. Look at the kes logs and see that kes is requesting an invalid key from the KMS.

Context

Our bucket replication is no longer replicating new objects.

Regression

Yes, as of 7.0.0.

Your Environment

  • Version used (minio-operator): 7.0.0
  • Environment name and version (e.g. kubernetes v1.17.2): Kubernetes v1.32.0
  • Operating System and version (uname -a): Talos v1.9.2.
@dhess
Copy link
Author

dhess commented Feb 2, 2025

Just wanted to confirm that after downgrading all operators and tenants to version 6.0.4, and having made no other changes, replication is working again, and kes is no longer generating the invalid key paths.

@aead
Copy link
Member

aead commented Feb 7, 2025

@dhess This behavior has been introduced in minio/minio with commit 883cd5c17 which has been considered a bug fix. Before, MinIO did not replicate the KMS key ID when replicating objects. Objects would not be encrypted with the specified key ID. Instead, the dest. site's bucket config got applied. In particular, without a bucket encryption config, such objects would have been stored unencrypted.

However, a side effect of this bug fix is that now all sites would be required to have access to all cryptographic keys used on any site. We understand that this is not always desirable. We can provide an option to disable the replication of SSE-KMS key IDs. This means, MinIO still replicates an SSE-KMS header indicating to the target site that the object should be encrypted using SSE-KMS but without specifying the KMS key ID. Then the site will apply either the site-level default KMS key or a key specified in a bucket config, if any.

@aead
Copy link
Member

aead commented Feb 7, 2025

minio/minio#20909

@dhess
Copy link
Author

dhess commented Feb 7, 2025

@aead Thanks for the reply.

We do indeed have site-level default KMS enabled for all buckets at both Site A and Site B. Each site uses a different default key, and neither site has access to the other's key. We would like to keep it that way.

Let me make sure I understand MinIO's behavior prior to minio/minio#20542, and the proposed fix's behavior:

  1. As we have been running a version of MinIO that pre-dates set kms keyid in replication opts minio#20542 — and have now reverted to that earlier version, after upgrading to version 7.0.0 of this operator and encountering the problem described in this issue — objects replicated via bucket replication from Site A to Site B have been encrypted at Site B with Site B's default KMS key, correct? (In other words, our replicated objects at Site B are being encrypted, correct?)
  2. Assuming that kms: add MINIO_KMS_REPLICATE_KEYID option minio#20909 is merged, then we will simply need to upgrade to that version, set MINIO_KMS_REPLICATE_KEYID=off, and the behavior described in 1. will continue unchanged, correct?

@aead
Copy link
Member

aead commented Feb 9, 2025

objects replicated via bucket replication from Site A to Site B have been encrypted at Site B with Site B's default KMS key, correct? (In other words, our replicated objects at Site B are being encrypted, correct?)

Only if you have a site-level or bucket-level encryption config on site B. For example, a bucket encryption config on all buckets on site B. Before minio/minio#20542 , site A would replicate the object without requesting encryption on the target. Hence, the target site was free to choose how to store the object. If the target site stored objects encrypted then it also stored replicated objects encrypted.

hen we will simply need to upgrade to that version, set MINIO_KMS_REPLICATE_KEYID=off, and the behavior described in 1. will continue unchanged, correct?

The behavior (in your case) will be the same as before. However, there is a difference. From now on, site A will tell site B that it should store the object encrypted using SSE-KMS. Site B can choose the KMS key but it has to store the object encrypted.

@dhess
Copy link
Author

dhess commented Feb 9, 2025

@aead Thanks. That will work for us, thank you!

@ramondeklein
Copy link
Contributor

@aead Should we add this changed behaviour to the release notes?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants