owncloud / owncloud/ocis

[Proposal] Secure message holder microservice

Open
#12,412 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Go
Stars
2.1k
Forks
274
Avg merge
2d 1h
Merged PRs (30d)
103

Description

## Is your feature request related to a problem? Please describe.
There are cases where we need to transfer data from one microservice to another. The underlying communication channel or the protocols used (HTTP / GRPC) might not be inherently secure, so the assumption is that the data being transferred is public and anyone can see it.

It's possible to encrypt the data before sending it, but this implies additional management such as using shared password (in case of symmetric encryption) or having some key exchange (in case of asymmetric encryption). What's more, some forms of communications such as "one-way messages" (communication from A to B, but not the other way around) is a challenge, specially without additional support from all the microservices.

## Describe the solution you'd like
The Secure Message Holder (SMH for short) will be a new microservice in charge of holding messages securely. The expected workflow is described below.

## Describe alternatives you've considered
* Using a shared password won't scale since we'd need a password for each microservice combination. In addition, reusing the same password isn't recommended, and the password should change from time to time.
* Most of the algorithms for key exchange involves communication from A to B but also from B to A. Unfortunately, communication from B to A isn't always possible.

## Additional context
The process will be as follows:
1. All the microservices will generate an asymmetric private key
1. Each replica of each microservice will have their own private key, so each replica will be independent from eachother.
2. The related public key will be registered in the SMH
1. The expected parameters are something like `register(service_replica_id, service_replica_pubkey, duration)`
1. The `service_replica_id` needs to be random to prevent collisions, but also be easy to identify. Something like "thumbnails_123abc"
2. The duration might be optional, but if so, the SMH needs to force a default duration.
2. The registered public key will be "active" for the provided duration. After that, the public key will be removed and a new one will need to be registered.
1. We want relatively frequent key registrations. Guessing a key shouldn't be much of a problem when it has been changed.
2. Expected duration should be around 1-2 weeks. (To be discussed)
3. The SMH might enforce a maximum duration. (To be discussed).
3. The SMH will respond with his own public key (the SMH's public key), and its validity period.
1. Same as with the registered keys, the SMH's key needs to be changed periodically.
2. The maximum duration enforced in 2.2.3 can be used to determine the validity period of the SMH's key.
4. The SMH **MUST** ensure that only registrations from trusted hosts are allowed.
3. The message to be send will be encrypted and signed locally.
1. Common utilities to perform this operation need to be available to all microservices.
1. This is specially relevant taking into account that cryptographic information must match to prevent problems.
2. In addition, these utilities need to be easy to use.
2. We'll use the `rsa.EncryptOAEP` function
4. Both the message and the signature will be sent to the SMH
1. The expected parameters are something like `send(service_replica_id, encrypted_message, signature, duration)`
1. The `service_replica_id` must be the same as the one used to register the public key
2. The SMH will use the `service_replica_id` to fetch the registered public key for that service and verify the signature.
3. If the signature is correct, the message will be stored for the specified duration.
2. The message will be available only for a specific duration.
1. Messages are expected to be short-lived, so a few seconds should be enough.
2. A maximum duration might be enforced by the SMH. This might be a couple of hours.
3. The message is expected to be kept encrypted in memory (to be discussed, it might be problematic)
4. The SMH will respond with a random id
1. This random id will be used later to retrieve the message.
5. Only valid messages must be accepted.
1. Valid messages must be from a known `service_replica_id`, must have a valid public key registered, and the signature must be correct.
2. Different errors might be responded: "unknown service", "key not found", "invalid signature", etc.
5. The random id returned by the SMH in step 4 will be sent through the public insecure channel
1. The id is completely random and it can't be used to guess the message.
6. Anyone with the random id AND access to the SMH can get and decypher the message.
1. Only trusted services should be allowed to register and have access. See 2.4
2. The service can retrieve the message with `receive(service_replica_id2, message_id)`
1. The SMH will encrypt and sign the message using the stored public key from `service_replica_id2`.
2. A rogue unregistered service won't be able to decrypt the message even if it knows a valid service id and message id.
7. The service will decrypt locally the returned message from the SMH.

Additional notes:
* There is no persistence planned in the service.
* Private keys are expected to be kept in memory for each service replica.
* If a replica is restarted, a new key must be generated and registered in the SMH.
* If the SMH is restarted, the services will get errors about missing keys. They must register their keys again (either the current or a new one).
* Public keys and messages in the SMH are expected to be kept in memory too.
* Expiration for both keys and messages is required. We don't want to keep data for too long.
* Multiple SMH replicas aren't planned.
* We'd need a key-value store to keep the public keys and messages available for each SMH replica.
* The private key would need to be shared among the SMH replicas to be able to decrypt the messages.
* Multiple message types might be implemented in the future (likely using different endpoints).
* For now, this proposal works as a "temporary broadcast" where the message can be read by anyone (assuming access) any number of times as long as the message is available.
* This is what we need at the moment for the autopropagation and vault mode.
* "direct messaging" might be possible if the SMH allows reading the message only by the requested service and not anyone else.
* "one time read" should be easy to implement if the message is removed right after the receiver request the message.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.