Skip to content

Add OIDC Recipes - #585

Open
MarkGotesman wants to merge 5 commits into
mainfrom
mgot/oidc-recipes
Open

Add OIDC Recipes#585
MarkGotesman wants to merge 5 commits into
mainfrom
mgot/oidc-recipes

Conversation

@MarkGotesman

@MarkGotesman MarkGotesman commented Aug 26, 2026

Copy link
Copy Markdown

Context

( See https://basetenlabs.slack.com/archives/C06CZ3RSXRU/p1787240030385759)
Supporting the runtime OIDC release, we want to add a home for recipes. Since runtime OIDC is a primitive we are handing to customers, a flexible git repo folder like this one makes sense. Me (@MarkGotesman) and @pat-baseten aligned on a Zoom call that this was a fair direction.

Content

Adding today:

  • Fetch a Resource. Similar to the example embedded in the docs (see here).
  • Envelope Encryption. Novel use of the token which has been often suggested to customers as a means to deliver encrypted data to and from the B10 platform (e.g. encrypted weights, see this thread. An object is sent/made available OIDC is used as a token to authorize a call to a remote key service (e.g. AWS KMS).

@CLAassistant

CLAassistant commented Aug 26, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@MarkGotesman MarkGotesman changed the title OIDC Recipes Add OIDC Recipes Aug 26, 2026
@MarkGotesman
MarkGotesman requested a review from moward August 27, 2026 14:51
@linear

linear Bot commented Aug 27, 2026

Copy link
Copy Markdown

ENT-1400

Comment thread oidc-recipes/README.md Outdated
Comment on lines +10 to +17
AWS KMS is designed to protect encryption keys, not to encrypt large model files directly. KMS `Encrypt` and `Decrypt` operations have small payload limits, while model weights may be many gigabytes.

Envelope encryption separates the work:

- A random **data key** encrypts the large payload locally.
- A KMS **key-encryption key** encrypts, or wraps, that data key.
- The encrypted payload and encrypted data key can be stored together safely.
- A workload must be authorized by KMS before it can recover the plaintext data key.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Why envelope encryption?" should answer why the customer wants this, which is not really what you're saying here. The goal is to protect the weights from exfiltration or misuse. Envelope encryption accomplishes this two ways:

  1. Customer owns the key lifecycle, including access management. They can revoke access at any time, rendering the encrypted weights unusable. And they get third party access logs (from AWS) tracking all reads of the DEK.
  2. Minimizes exposure of decrypted weights to only the model pod, dramatically reducing attack surface area

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's fair in the context of what if does for a B10 customer. How does this sound?
----

Envelope encryption protects proprietary model weights from exfiltration and misuse in two ways:

  • Customer-controlled access and key lifecycle. The customer owns the KMS key and its access policy, and can revoke access at any time. Without permission to decrypt the data-encryption key (DEK), a copy of the encrypted weights is unusable. AWS CloudTrail also provides an independent audit trail of every KMS Decrypt request used to recover the DEK.
  • Minimal plaintext exposure. Storage, transfer, and mirroring systems handle only encrypted artifacts. The weights are decrypted only inside the authorized model pod, significantly reducing the systems and identities that can access the plaintext weights.

-> /tmp/decrypted-weights/weights.json
```

The OIDC token is used to obtain temporary AWS credentials; it is not sent in the KMS request body. The encrypted model weights are never sent to KMS. Only the small encrypted data key and its encryption context are sent to KMS, and the returned plaintext data key is used inside the model container.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only the small encrypted data key and its encryption context are sent to KMS

The DEK originates from KSM, it's not sent to KMS, correct?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I think this is the process:

  • The encrypted weights and encrypted DEK are stored/mounted together, e.g. by BDN.
  • At runtime, the model container uses OIDC to assume an AWS role / obtain temporary AWS credentials.
  • Then the container sends the encrypted DEK plus encryption context to kms:Decrypt.
  • KMS returns the plaintext DEK.
  • The container uses that plaintext DEK locally to decrypt the model weights.

This is what happens in code:

def decrypt_weights(output: Path) -> Path:
    envelope = read_envelope()
    encrypted_data_key = ENCRYPTED_DATA_KEY_FILE.read_bytes()
    ciphertext = ENCRYPTED_WEIGHTS_FILE.read_bytes()

    response = get_kms_client().decrypt(
        CiphertextBlob=encrypted_data_key,
        EncryptionContext=envelope["encryption_context"],
    )
    data_key = response["Plaintext"]

We get the encrypted_data_key sent (e.g. by BDN), send it to KMS, and KMS sends us back the decrypted version.

Comment on lines +198 to +208
## Other use cases

The same pattern applies whenever a model must process sensitive payloads but should not carry a long-lived decryption credential. The snippets below focus on business logic and assume `decrypt_envelope()` and `encrypt_envelope()` implement the same authenticated envelope format.

- Decrypt an inference request supplied by a customer application

```python
def predict(self, model_input):
request = json.loads(self.decrypt_envelope(model_input["encrypted_request"]))
return self.model.generate(request["prompt"])
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO it's worth splitting out envelope payload encryption as a separate use case e2e since the setup and inference client code are separate, and the motivations behind it are separate too (some customers care more about weight security, others more about payload security). Maybe too much to take on right now, but as-is, it's a bit burried

@@ -0,0 +1,315 @@
#!/usr/bin/env bash

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this be clearer and simpler in python with boto3?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe, but I riffed off a one-shot script Daniel already had in the docs that was a shell script. I think either works fine. Since the shell examples are already there, I think it's easier to just keep it.

@@ -0,0 +1,269 @@
# OIDC: Envelope Encryption

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few comments on this README:

1.Add a terminology section at the top. It may look like basic info, but it's worth defining up front:
Root Key
KEK (Key Encryption Key)
DEK (Data Encryption Key)
Please also state explicitly that the customer owns the Root Key and KEK in their own AWS account, and that neither ever leaves AWS.

  1. Call out the performance cost. Customers need to be aware of the overhead this flow introduces.

3.Clarify the ownership boundary inside the pod. The code running in the pod is customer-owned. Once the DEK is unwrapped, handling the plaintext DEK — and discarding it after use — is the customer's responsibility.


Envelope encryption separates the work:

- A random **data key** encrypts the large payload locally.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use professional word like wrap or unwrap, instead of random or locally

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants