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

Implement a secure key storage #329

Open
wants to merge 40 commits into
base: main
Choose a base branch
from

Conversation

Hermann-Core
Copy link
Collaborator

No description provided.

Copy link
Collaborator

@IngridPuppet IngridPuppet left a comment

Choose a reason for hiding this comment

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

The keystore is now responsible for encryption and decryption operations via an Encryptor dependency, not the repository layer. I largely prefer this design. I left some comments though, please could you check?

Comment on lines 35 to 37
.env
.env.example

Copy link
Collaborator

Choose a reason for hiding this comment

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

.env.example is not intended to be ignored.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I don't think that we require it anymore since it is constructed dynamically in the pipeline for the tests.

Comment on lines 3 to 5
# Stage 1: Build
FROM rust:1.80-alpine AS builder
FROM rust:1.83-alpine AS builder

Copy link
Collaborator

Choose a reason for hiding this comment

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

Please limit your changes to the requirements of this ticket.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

One dependency that I used required a higher Rust version. So I've updated the builder image version to follow that requirement.

crates/database/src/lib.rs Show resolved Hide resolved
Comment on lines +29 to +32
#[error("decryption error")]
DecryptionError,
#[error("error deserializing to jwk")]
JwkDeserializationError,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Did you mean to leave this behind?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I don't get it.

Comment on lines +101 to 114
/// Create a new key store with mocked repository and encryption backends.
/// This will be use for testing purposes.
#[cfg(any(test, feature = "test-utils"))]
pub fn with_mock_configs<T>(secrets: Vec<(String, T)>) -> Self
where
T: Serialize + DeserializeOwned + Send + Sync + 'static,
{
let mock_repository = MockSecretRepository::new(secrets);
let encryptor = NoEncryption;
Self {
repository: Arc::new(mock_repository),
encryptor: Arc::new(encryptor),
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could you consider moving this logic to the tests module altogether?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Makes sense.

Comment on lines +6 to +12
#[derive(Default)]
pub struct MockSecretRepository<T>
where
T: Serialize + DeserializeOwned,
{
secrets: RwLock<Vec<(String, T)>>,
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

You really mean to write mocks with locks? How necessary is that?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I want interior mutability on the vector since the methods of the SecretRepository trait take self by reference. I could have used something cheaper like RefCell but the tests don't run for long so I think it is fine.

Comment on lines +51 to +54
None => Err(Error::msg(
ErrorKind::RepositoryFailure,
format!("Secret with kid {kid} not found"),
)),
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this behavior matching the concrete repository impl? I think that was removed and not finding the resource not considered an error.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Just checked the delete function of the Repository and you are right. Let me fix that.
But anyways it is just for the test. In real scenarios, it will not throw an error.

Comment on lines +85 to +89

#[tokio::test]
async fn test_keystore_flow() {
let jwk1 = secret1();
let jwk2 = secret2();
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm surprised you aren't also testing that keys are not persisted in clear. I could not find tests at the encryptor module layer either.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Hmm right. I only wanted to test the keystore flow. But I can also provide a mock encryptor.

Comment on lines +37 to +45
/// * [`CircuitBreaker::retries(self, max_retries: usize)`]: Sets the maximum number of consecutive failures allowed before the circuit opens.
/// A value of 0 means the circuit will open on the first failure.
/// * [`half_open_max_failures(self, max_retries: usize)`](half_open_max_failures): Sets the maximum number of attempts in half-open state
/// * [`CircuitBreaker::half_open_max_failures(self, max_retries: usize)`]: Sets the maximum number of attempts in half-open state
/// before reopening the circuit.
/// * [`reset_timeout(self, reset_timeout: Duration)`](timeout): Sets the duration the circuit remains open after tripping.
/// * [`CircuitBreaker::reset_timeout(self, reset_timeout: Duration)`]: Sets the duration the circuit remains open after tripping.
/// After this timeout, the circuit transitions to the half-open state.
/// * [`exponential_backoff(self, initial_delay: Duration)`](exponential_backoff): Configures an exponential backoff strategy for retries.
/// * [`CircuitBreaker::exponential_backoff(self, initial_delay: Duration)`]: Configures an exponential backoff strategy for retries.
/// The delay between retries increases exponentially. This overrides any previously set backoff.
/// * [`constant_backoff(self, delay: Duration)`](constant_backoff): Configures a constant backoff strategy for retries.
/// * [`CircuitBreaker::constant_backoff(self, delay: Duration)`]: Configures a constant backoff strategy for retries.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please refrain from adding changes not related to your PR. It leaves the reviewer confused, especially when they are not qualified to review them.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We added a step in the CI to check the docs too. These changes have been done to make the pipeline happy.

src/main.rs Show resolved Hide resolved
@Hermann-Core
Copy link
Collaborator Author

Hermann-Core commented Feb 18, 2025

The keystore is now responsible for encryption and decryption operations via an Encryptor dependency, not the repository layer. I largely prefer this design. I left some comments though, please could you check?

Testing would have been very hard that way. Plus we can decide to change the storage backend later, so it will be easy to switch to a new one without breaking anything. This keystore impl could be used for further projects too, not only for the mediator.

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.

implement a secure key storage functionality for the pop-server E3
3 participants