dapr: Proposal: Building block API for cryptography
Note: Crypto as in cryptography, NOT cryptocurrency!!
Update: API Design proposal below: https://github.com/dapr/dapr/issues/4508#issuecomment-1260116173
In what area(s)?
/area runtime
Describe the proposal
This is a proposal for a new building block for Dapr to allow developers to leverage cryptography in a SAFE and consistent way. Goal is to expose an API that allows developers to ask Dapr to perform operations such as encrypting and decrypting messages, and calculating and verifying digital signatures.
Modern applications make extensive use of cryptography, which, when implemented correctly, can make solutions safer even in case data is compromised. Even more, in certain cases the use of crypto is required to comply with industry regulations (think banking) or even with legal requirements (GDPR). However, leveraging cryptography is hard: developers need to pick the right algorithms and options, and need to learn the proper way to manage and protect keys. Additionally, there are operational complexities when teams want to limit who has access to cryptographic key material.
Organizations have been increasingly started to leverage tools and services to perform crypto outside of applications. Examples include services such as Azure Key Vault, AWS KMS, Google Cloud KMS, etc. Customers may also use on-prem HSM products like Thales Luna. While those products/services perform the same or very similar operations, their APIs are very different.
This is an area where Dapr can help. Just like we’re offering an abstraction on top of secret stores, we can offer an abstraction layer on top key vaults.
Using this building block, developers would be able to perform cryptographic operations without having to access raw key material. We would also offer a selection of algorithms that are configured correctly and forbid the usage of unsafe algorithms and operations. Algorithms available will depend on what the backend vaults support, but in general developers should always find AES (encrypt/decrypt only) and RSA; when supported, we can offer also ChaCha20-Poly1305 (encrypt/decrypt only) and ECC with ECDSA or EdDSA (sign/verify only).
Benefits would allow:
- Making it easier for developers to perform cryptographic operations in a safe way. Dapr provides safeguards against using unsafe algorithms, or using algorithms with unsafe options.
- Keeping keys outside of applications. Applications never see key material, but can request the vault to perform operations with the keys.
- Allowing greater separation of concerns. By using external vaults, only authorized teams can access private/shared key materials.
- Simplify key management and key rotation. Keys are managed in the vault and outside of the application, and they can be rotated without needing the developers to be involved (or even without restarting the apps).
- Enabling better audit logging to monitor when operations are performed with keys in the vault.
The new building block would feature 7 APIs:
/encrypt: encrypts arbitrary data using a key stored in the vault. It supports symmetric and asymmetric ciphers, depending on the type of key in use (and the types of keys supported by the vault)./decrypt: decrypts arbitrary data, performing the opposite of what/encryptdoes./wrapkey: wraps keys using other keys stored in the vault. This is exactly like encrypting data, but it expects inputs to be formatted as keys (for example formatted as JSON Web Key) and it exposes additional algorithms not available when encrypting general data (like AES-KW)/unwrapkey: un-wraps (decrypts) keys, performing the opposite of what/wrapdoes/sign: signs an arbitrary message using an asymmetric key stored in the vault (we could also consider offering HMAC here, using symmetric keys, although not widely supported by the vault services)/verify: verifies a digital signature over an arbitrary message, using an asymmetric key stored in the vault (same: we may be able to offer HMAC too)/getkey: this can be used only with asymmetric keys stored in the vault, and returns the public part of the key
Different components would be developed to perform those operations on supported backends such as the products/services listed above. Dapr would “translate” these calls into whatever format the backends require. Dapr never sees the private/shared keys, which remain safely stored inside the vaults.
Additionally, we could offer a “local” crypto component where keys are stored as Kubernetes secrets and cryptographic operations are performed within the Dapr sidecar. Although this is not as secure as using an external key vault, it still offers some benefits such as using standardized APIs and separation of concerns/roles with regards to key management.
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 12
- Comments: 33 (22 by maintainers)
Commits related to this issue
- Add proposal for crypto building block Ported from dapr/dapr#4508 Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com> — committed to ItalyPaleAle/dapr-proposals by ItalyPaleAle 2 years ago
- Add proposal for crypto building block Ported from dapr/dapr#4508 Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com> — committed to ItalyPaleAle/dapr-proposals by ItalyPaleAle 2 years ago
- Add proposal for crypto building block (#3) * Add proposal for crypto building block Ported from dapr/dapr#4508 Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com> * Ad... — committed to dapr/proposals by ItalyPaleAle a year ago
I think we need a way to also make envelope encryption exposed through Dapr. Some cloud providers (AWS, IBM) expose envelope encryption as a first class concept. Additionally, it is a common pattern for enabling secure high-throughput client side encryption. It might be a worth concept to have as a building block for distributed apps exposed through Dapr.
Context
So what is envelop encryption?[1], [2], [3]
Why even doing this? From the KMS Tutorial (GCP docs for envelope encryption is also pretty good):
So the idea of envelope encryption is that
Why envelope encryption?
Support by cloud provider and encruption
AWS exposes envelope encryption as a first class concept in their SDK.
Azure Key Vault doesn’t expose this directly in its APIs. It is handled transparently with its managed services and performed by its client libraries for storage
GCP doesn’t explicitly offer envelop encryption as a first class concept in their SDK but its Tink Cryptographic library exposes it. That said, envelope encryption is the under-the-hood solution for encryption data with asymmetric cryptography (but that is expected).
IBM cloud exposes envelop encryption as an API
Hashicorp Vault
transitbackend also offers primitives for generating DEK through itsgenerate-data-keyoperation. srcWhy we need Dapr support? Can’t users implement this themselves?
One thing to keep in mind regarding envelop encryption is that when one performs the key wrapping step, metadata about the KEK used (version, name etc) has to be persisted together with the (now encrypted) DEK. This is required so so KEK rotation can be performed without impacting already issued DEK and data they encrypt. KEK metadata is not something we are exposing to clients in this proposal. So in order to offer client-side encryption using envelop encryption we would need to do it on the component side.
Again, some SDKs expose this as a first class concept. If we don’t offer the right abstraction for this customers will be barred from this.
EDITS
transitbackend having support for envelope encryptionWe discussed this issue in the community call today. Here goes the general feedback on it (including some of my recommendations too):
Response: RAW encrypted payload in the HTTP response body, passing response metadata (encryptedKey) via Headers Alternative: Return the Dapr’s encryption envelope as JSON
Response: RAW plaintext in the HTTP response body.
encryptresponse or serialized as JSON.Correct.
In the proposal I wrote above, the key name is always dynamic, meaning that components have access to all keys they are authorized to, and apps need to specify what key they want to use.
I think doing the opposite (hardcoding a key in the component’s YAML) would also encourage bad practices, such as using the same key for data encipherment and signing.
Yes, this is a situation where we’re essentially trying to protect the developers from themselves. The idea is that access to the high level APIs should happen using the Dapr SDKs (also because the code to perform the “back and forth” over the gRPC streams is not going to be very simple).
If there’s strong demand for the API to be exposed over HTTP, I think it can be considered. But people should be aware that it does require all data to be loaded into memory first, ballooning the memory requirements of the Dapr sidecar.
The value Dapr provides is that it abstracts the various cloud key vaults. All libraries that offer the primitives expect the key material to be passed directly.