Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/Configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,12 @@ bucket = "name"
endpoint = "s3-us-east-1.amazonaws.com"
use_ssl = true
key_prefix = "s3prefix"
# SSE-S3 with an S3-managed key (AES256).
server_side_encryption = false
# SSE-KMS with the AWS-managed KMS key (aws/s3).
server_side_encryption_aws_kms = false
# SSE-KMS with a customer-managed KMS key (takes precedence when set).
# server_side_encryption_kms_key_id = "arn:aws:kms:us-east-1:111:key/abc"

[cache.webdav]
endpoint = "http://192.168.10.42:80/some/webdav.php"
Expand Down
7 changes: 6 additions & 1 deletion docs/S3.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@ If you want to use S3 storage for the sccache cache, you need to set the followi

If your endpoint requires HTTPS/TLS, set `SCCACHE_S3_USE_SSL=true`. If you don't need a secure network layer, HTTP (`SCCACHE_S3_USE_SSL=false`) might be better for performance.

Enable server-side encryption with s3 managed key (SSE-S3), set `SCCACHE_S3_SERVER_SIDE_ENCRYPTION=true`.
Server-side encryption can be enabled in one of three modes. They are resolved in the following order of precedence:

- **SSE-KMS with a customer-managed KMS key:** set `SCCACHE_S3_SERVER_SIDE_ENCRYPTION_KMS_KEY_ID` to the KMS key ID/ARN. This implies `aws:kms` and takes precedence over the other settings.
- **SSE-KMS with the AWS-managed KMS key (`aws/s3`):** set `SCCACHE_S3_SERVER_SIDE_ENCRYPTION_AWS_KMS=true`.
- **SSE-S3 with an S3-managed key (AES256):** set `SCCACHE_S3_SERVER_SIDE_ENCRYPTION=true`.

More details about encryption [here](https://opendal.apache.org/docs/services/s3/#server-side-encryption) and documentation [here](https://docs.rs/opendal/latest/opendal/services/struct.S3.html#method.server_side_encryption_with_s3_key).

You can also define a prefix that will be prepended to the keys of all cache objects created and read within the S3 bucket, effectively creating a scope. To do that use the `SCCACHE_S3_KEY_PREFIX` environment variable. This can be useful when sharing a bucket with another application.
Expand Down
2 changes: 2 additions & 0 deletions src/cache/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,8 @@ pub fn build_single_cache(
.with_endpoint(c.endpoint.clone())
.with_use_ssl(c.use_ssl)
.with_server_side_encryption(c.server_side_encryption)
.with_server_side_encryption_aws_kms(c.server_side_encryption_aws_kms)
.with_server_side_encryption_kms_key_id(c.server_side_encryption_kms_key_id.clone())
.with_enable_virtual_host_style(c.enable_virtual_host_style)
.build()
.map_err(|err| anyhow!("create s3 cache failed: {err:?}"))?;
Expand Down
27 changes: 26 additions & 1 deletion src/cache/s3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ pub struct S3Cache {
endpoint: Option<String>,
use_ssl: Option<bool>,
server_side_encryption: Option<bool>,
server_side_encryption_aws_kms: Option<bool>,
server_side_encryption_kms_key_id: Option<String>,
enable_virtual_host_style: Option<bool>,
}

Expand All @@ -39,6 +41,8 @@ impl S3Cache {
endpoint: None,
use_ssl: None,
server_side_encryption: None,
server_side_encryption_aws_kms: None,
server_side_encryption_kms_key_id: None,
enable_virtual_host_style: None,
}
}
Expand All @@ -58,6 +62,20 @@ impl S3Cache {
self.server_side_encryption = server_side_encryption;
self
}
pub fn with_server_side_encryption_aws_kms(
mut self,
server_side_encryption_aws_kms: Option<bool>,
) -> Self {
self.server_side_encryption_aws_kms = server_side_encryption_aws_kms;
self
}
pub fn with_server_side_encryption_kms_key_id(
mut self,
server_side_encryption_kms_key_id: Option<String>,
) -> Self {
self.server_side_encryption_kms_key_id = server_side_encryption_kms_key_id;
self
}
pub fn with_enable_virtual_host_style(
mut self,
enable_virtual_host_style: Option<bool>,
Expand Down Expand Up @@ -93,7 +111,14 @@ impl S3Cache {
builder = builder.endpoint(&endpoint_resolver(endpoint, self.use_ssl)?);
}

if self.server_side_encryption.unwrap_or_default() {
if let Some(kms_key_id) = &self.server_side_encryption_kms_key_id {
// SSE-KMS with a customer-managed KMS key.
builder = builder.server_side_encryption_with_customer_managed_kms_key(kms_key_id);
} else if self.server_side_encryption_aws_kms.unwrap_or_default() {
// SSE-KMS with the AWS-managed KMS key (aws/s3).
builder = builder.server_side_encryption_with_aws_managed_kms_key();
} else if self.server_side_encryption.unwrap_or_default() {
// SSE-S3 with an S3-managed key (AES256).
builder = builder.server_side_encryption_with_s3_key();
}

Expand Down
50 changes: 50 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,8 @@ pub struct S3CacheConfig {
pub endpoint: Option<String>,
pub use_ssl: Option<bool>,
pub server_side_encryption: Option<bool>,
pub server_side_encryption_aws_kms: Option<bool>,
pub server_side_encryption_kms_key_id: Option<String>,
pub enable_virtual_host_style: Option<bool>,
#[serde(default)]
pub rw_mode: CacheModeConfig,
Expand Down Expand Up @@ -886,6 +888,10 @@ fn config_from_env() -> Result<EnvConfig> {
let no_credentials = bool_from_env_var("SCCACHE_S3_NO_CREDENTIALS")?.unwrap_or(false);
let use_ssl = bool_from_env_var("SCCACHE_S3_USE_SSL")?;
let server_side_encryption = bool_from_env_var("SCCACHE_S3_SERVER_SIDE_ENCRYPTION")?;
let server_side_encryption_aws_kms =
bool_from_env_var("SCCACHE_S3_SERVER_SIDE_ENCRYPTION_AWS_KMS")?;
let server_side_encryption_kms_key_id =
string_from_env_var("SCCACHE_S3_SERVER_SIDE_ENCRYPTION_KMS_KEY_ID");
let endpoint = string_from_env_var("SCCACHE_ENDPOINT");
let key_prefix = key_prefix_from_env_var("SCCACHE_S3_KEY_PREFIX");
let enable_virtual_host_style = bool_from_env_var("SCCACHE_S3_ENABLE_VIRTUAL_HOST_STYLE")?;
Expand All @@ -900,6 +906,8 @@ fn config_from_env() -> Result<EnvConfig> {
endpoint,
use_ssl,
server_side_encryption,
server_side_encryption_aws_kms,
server_side_encryption_kms_key_id,
enable_virtual_host_style,
rw_mode,
})
Expand Down Expand Up @@ -2353,6 +2361,44 @@ fn test_s3_no_credentials_valid_false() {
}
}

#[test]
#[serial(config_from_env)]
#[cfg(feature = "s3")]
fn test_s3_sse_kms_from_env() {
unsafe {
env::set_var("SCCACHE_BUCKET", "my-bucket");
env::set_var("SCCACHE_S3_SERVER_SIDE_ENCRYPTION_AWS_KMS", "true");
env::set_var(
"SCCACHE_S3_SERVER_SIDE_ENCRYPTION_KMS_KEY_ID",
"arn:aws:kms:us-east-1:111:key/abc",
);
}

let cfg = config_from_env();

unsafe {
env::remove_var("SCCACHE_BUCKET");
env::remove_var("SCCACHE_S3_SERVER_SIDE_ENCRYPTION_AWS_KMS");
env::remove_var("SCCACHE_S3_SERVER_SIDE_ENCRYPTION_KMS_KEY_ID");
}

let env_cfg = cfg.unwrap();
match env_cfg.cache.s3 {
Some(S3CacheConfig {
server_side_encryption_aws_kms,
ref server_side_encryption_kms_key_id,
..
}) => {
assert_eq!(server_side_encryption_aws_kms, Some(true));
assert_eq!(
server_side_encryption_kms_key_id.as_deref(),
Some("arn:aws:kms:us-east-1:111:key/abc")
);
}
None => unreachable!(),
}
}

#[test]
#[serial(config_from_env)]
#[cfg(feature = "gcs")]
Expand Down Expand Up @@ -2528,6 +2574,8 @@ key_prefix = "cosprefix"
key_prefix: "s3prefix".into(),
no_credentials: true,
server_side_encryption: Some(false),
server_side_encryption_aws_kms: None,
server_side_encryption_kms_key_id: None,
enable_virtual_host_style: None,
rw_mode: CacheModeConfig::ReadWrite,
}),
Expand Down Expand Up @@ -3025,6 +3073,8 @@ fn test_get_cache_levels_single_cache() {
endpoint: None,
use_ssl: None,
server_side_encryption: None,
server_side_encryption_aws_kms: None,
server_side_encryption_kms_key_id: None,
enable_virtual_host_style: None,
rw_mode: CacheModeConfig::ReadWrite,
}),
Expand Down