-
Notifications
You must be signed in to change notification settings - Fork 94
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
CoCoKeyprovider | Support plug-ins of KMS #188
Comments
One thing to think about is whether we ever want to support "remote" attestation, meaning that the key never leaves the KMS. Option 2 fits better with this but it would be more complicated to implement. |
You're right. There is a trade off between the thought "Never-Leave-KMS" and the simplicity of the design. My idea is that the key can leave KMS. Now commercial KMSes always give two kinds of abstrations for keys: Customer Master Key (CMK) and Data Encryption Key (DEK or Datakey).
The DEK can work as the KEK, in this way "Never-Leave-KMS" is not ensured. The reasons are:
We might need more views upon this : ). |
Answer to 4.: public key is not sensitive, so there is no reason to enforce "never-leave-kms" on it. |
I have my doubts about "CMK" and "Datakey". You say "commercial KMS" support this, but I don't see direct equivalents with the same semantics in Azure Key Vault or Azure managed HSM. So I don't think we should specify the interface in those terms. |
Hi @jepio Thanks for your comments.
Agreed. What we can do is to export the public key after signing and store the public key inside the KBS before using it.
I must have ignored something important, for I can only learn from the open documents. In my mind
I did a rough research on some other KMSes like aliyun KMS, aws KMS, gcp KMS and Azure Key Vault. I found that they can all implement this abstraction. My biggest worry is that this abstraction is not good enough for us to leverage KMS to do image encryption and signing. However up to now I did not even get a better design idea. |
Maybe we should focus on the use cases and then figure out the common interface. I also thought KBS should be stateless if it uses a KMS as a backend, in that case all secret keys should be stored in the KMS. For encrypted images: we need a symmetric encryption key (LEK/Data Encryption Key/Content Encryption Key) that is used to perform layer decryption outside KMS. I say outside KMS because I don't see how it is feasible to do the cryptographic operations in an HSM for every single pod with the image sizes we deal with. So the encryption key needs to be protected (wrapped) with a KEK, which should also be symmetric. Ideally we could store the wrapped symmetric key inside container image metadata, so that it is transported together with the encrypted image, otherwise we could store the wrapped key in object storage. If the wrapped key is part of the container image, then KBS interface needs to change to support unwrapping. If the wrapped key is in object storage then KBS can retrieve it. The key wrapping might rely on vendor-specific wrapped key representation ("datakey"), or we could rely on a standard representation like JSON Web Encryption (https://datatracker.ietf.org/doc/html/rfc7516). For image signing the situation is different (more complicated) because signing really should happen inside a KMS. But I actually don't know if we should even try to address this, as there are various established ways to sign/verify images: sigstore, notary v2, gpg (does anyone have a good example of gpg integration with a KMS). So I'm not sure we should even try to involve KBS in this process. |
@jepio Currently the LEK is part of the container image. It is stored as part of the layer annotation packet. Hence the |
Good to know that the annotation packet already works the way I outlined above. If we agree that KMS support should be using fundamental KMS primitives (wrap key/unwrap key), then we can keep the annotation packet KMS-agnostic.
We could live with the gap, but if we want proper KMS support then we will want to support non-extractable KEKs, which means we'll need to expand KBS to support some KMS like operations (unwrap/wrap key at least?)
I'm not super familiar with the encryption flow, but my intuition tells me we could reuse the same KMS interface in the keyprovider, communicate directly to KMS and bypass KBS? |
This is Way 1 in my initial proposal. It sounds good for me to keep the KMS operations, s.t. unwrap/wrap key. An idea to work with the current
#[async_trait::async_trait]
pub trait KMSAgent {
/// Generate a key inside the KMS, and return the `keyid` of this key. The `keyid`
/// can then be used to encrypt or decrypt data slice using this key.
async fn generate_key(&mut self) -> Result<String>;
/// Use the key of `keyid` to encrypt the `data` slice inside KMS, and then
/// return the ciphertext of the `data`. The encryption operation should occur
/// inside KMS. This function only works as a wrapper for different KMS APIs
async fn encrypt(&mut self, data: &[u8], keyid: &str) -> Result<Vec<u8>>;
/// Use the key of `keyid` to decrypt the `ciphertext` slice inside KMS, and then
/// return the plaintext of the `data`. The decryption operation should occur
/// inside KMS. This function only works as a wrapper for different KMS APIs
async fn decrypt(&mut self, ciphertext: &[u8], keyid: &str) -> Result<Vec<u8>>;
} Here the
To avoid ambiguity, it should be clear that a keyid inside an Then the mapping from a KBS Resource URI to a keyid:
When encrypting the image, cocokeyprovider would do the following pseudocode
When decrypt the image
Either KBS has a unwrap/wrap API or not, the basic logic should exist (either inside KBS or a separate keyprovider). What about this? |
Now different commercial KMS have different API. Some like Azure gives detailed parameters when en/decrypt like An naive idea from my side is to encapsulate the |
duplication of #353 |
Background
Now CoCo KeyProvider has the following functions:
KEK
, itsKID
and registering theKEK
into KBSKEK
It's important that the KEK is either imported from a local file, or randomly generated inside the CoCoKeyprovider.
What we want
Different KMSes have already given a good practical implementation for managing cryptographic keys. As mentioned in confidential-containers/trustee#37, we should think about bringing in KMS plug-in for the whole lifetime of KEKs.
Initial Design Plan
Image Encryption
For CoCo Keyprovider, there are two basic functions:
1 requires keyprovider to generate a new (or fetch an old) datakey from KMS.
2 requires keyprovider to deliver "something" that presents the key into KBS. The "something" might not be the KEK itself, but with this "something", KBS can easily recover the original plaintext of the KEK.
Based on the two observations, we propose a unified trait
Encryptor
that refers to a specific key entity, such as aDataKey
in a KMS.Image Decryption
The decryption operation needs more discussion.
Now, we implement the decryption inside attestation-agent with manual crypto calculations. With KMS, there might be two different design ways
Way 1
The same as current implementation, s.t. decryption operation occurs inside attestation-agent. The data-flow will as the diagram
Pro: We do not need to change any APIs of KBS which CC-KBC calls. Concretely, now KBS just provides an API for CC-KBC to "fetch the resource" rather than "do decryption".
Con: (probably a con?) encryption and decryption are in different componants -- encryption in keyprovider but decryption in KBS.
Way 2
This way, we integrate both encryption and decryption inside KBS, and make coco-keyprovider an proxy for KBS.
Pro: encryption and decryption are in same componants -- KBS
Con: we need to open another HTTP API from KBS, and probably not related to the "confidential resource storage" functionality of KBS.
To avoid make KBS more complicated, I prefer way 1. And to make future work easy, I suggest make KMS plug-ins a single library like what this PR is doing. In this way we can import the library both in CoCo Keyprovider and KBS side.
In this way the
Encryptor
should be extended with the following functionsRelated Issue
confidential-containers/trustee#37
The text was updated successfully, but these errors were encountered: