Skip to content

Commit af07a53

Browse files
authored
Add s3 credential support (#1606)
1 parent 2e1de90 commit af07a53

File tree

17 files changed

+246
-134
lines changed

17 files changed

+246
-134
lines changed

Cargo.lock

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/rtconfgen/convert.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -384,8 +384,10 @@ func (c *legacyConverter) Convert() (*config.Runtime, error) {
384384
switch prov := cluster.Provider.(type) {
385385
case *runtimev1.BucketCluster_S3_:
386386
p.S3 = &config.S3BucketProvider{
387-
Region: prov.S3.GetRegion(),
388-
Endpoint: prov.S3.Endpoint,
387+
Region: prov.S3.GetRegion(),
388+
Endpoint: prov.S3.Endpoint,
389+
AccessKeyID: prov.S3.AccessKeyId,
390+
SecretAccessKey: ptrOrNil(c.secretString(prov.S3.SecretAccessKey)),
389391
}
390392
case *runtimev1.BucketCluster_Gcs:
391393
p.GCS = &config.GCSBucketProvider{
@@ -640,6 +642,14 @@ func ptr[T comparable](val T) *T {
640642
return &val
641643
}
642644

645+
func ptrOrNil[T comparable](val T) *T {
646+
var zero T
647+
if val == zero {
648+
return nil
649+
}
650+
return &val
651+
}
652+
643653
func randomMapValue[K comparable, V any](m map[K]V) (V, bool) {
644654
for _, v := range m {
645655
return v, true

proto/encore/runtime/v1/infra.pb.go

Lines changed: 121 additions & 92 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

proto/encore/runtime/v1/infra.proto

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,11 @@ message BucketCluster {
323323

324324
// Endpoint override, if any. Must be specified if using a non-standard AWS region.
325325
optional string endpoint = 2;
326+
327+
// Set these to use explicit credentials for this bucket,
328+
// as opposed to resolving using AWS's default credential chain.
329+
optional string access_key_id = 3;
330+
optional SecretData secret_access_key = 4;
326331
}
327332

328333
message GCS {

runtimes/core/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ md5 = "0.7.0"
9393
aws-sdk-s3 = "1.58.0"
9494
aws-smithy-types = { version = "1.2.8", features = ["byte-stream-poll-next", "rt-tokio"] }
9595
percent-encoding = "2.3.1"
96+
aws-credential-types = "1.2.1"
9697

9798
[build-dependencies]
9899
prost-build = "0.12.3"

runtimes/core/src/infracfg.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ pub struct GCS {
4646
pub struct S3 {
4747
pub region: String,
4848
pub endpoint: Option<String>,
49+
pub access_key_id: Option<String>,
50+
pub secret_access_key: Option<EnvString>,
4951
pub buckets: HashMap<String, Bucket>,
5052
}
5153

@@ -461,6 +463,11 @@ pub fn map_infra_to_runtime(infra: InfraConfig) -> RuntimeConfig {
461463
pbruntime::bucket_cluster::S3 {
462464
region: s3.region,
463465
endpoint: s3.endpoint,
466+
access_key_id: s3.access_key_id,
467+
secret_access_key: s3
468+
.secret_access_key
469+
.as_ref()
470+
.map(map_env_string_to_secret_data),
464471
},
465472
)),
466473
buckets: s3

runtimes/core/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,8 @@ impl Runtime {
331331
.context("failed to resolve gateway push subscriptions")?;
332332

333333
let pubsub = pubsub::Manager::new(tracer.clone(), resources.pubsub_clusters, &md)?;
334-
let objects = objects::Manager::new(tracer.clone(), resources.bucket_clusters, &md);
334+
let objects =
335+
objects::Manager::new(&secrets, tracer.clone(), resources.bucket_clusters, &md);
335336
let sqldb = sqldb::ManagerConfig {
336337
clusters: resources.sql_clusters,
337338
creds: &creds,

runtimes/core/src/objects/gcs/bucket.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ impl objects::ObjectImpl for Object {
363363
return Err(PublicUrlError::PrivateBucket);
364364
};
365365

366-
let url = objects::public_url(base_url, self.bkt.key_prefix.as_deref(), &self.key);
366+
let url = objects::public_url(base_url, &self.key);
367367
Ok(url)
368368
}
369369
}

runtimes/core/src/objects/manager.rs

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::encore::parser::meta::v1 as meta;
55
use crate::encore::runtime::v1 as pb;
66
use crate::names::EncoreName;
77
use crate::objects::{gcs, noop, s3, BucketImpl, ClusterImpl};
8+
use crate::secrets;
89
use crate::trace::Tracer;
910

1011
use super::Bucket;
@@ -17,8 +18,13 @@ pub struct Manager {
1718
}
1819

1920
impl Manager {
20-
pub fn new(tracer: Tracer, clusters: Vec<pb::BucketCluster>, md: &meta::Data) -> Self {
21-
let bucket_cfg = make_cfg_maps(clusters, md);
21+
pub fn new(
22+
secrets: &secrets::Manager,
23+
tracer: Tracer,
24+
clusters: Vec<pb::BucketCluster>,
25+
md: &meta::Data,
26+
) -> Self {
27+
let bucket_cfg = make_cfg_maps(secrets, clusters, md);
2228

2329
Self {
2430
tracer,
@@ -54,13 +60,20 @@ impl Manager {
5460
}
5561

5662
fn make_cfg_maps(
63+
secrets: &secrets::Manager,
5764
clusters: Vec<pb::BucketCluster>,
5865
_md: &meta::Data,
5966
) -> HashMap<EncoreName, (Arc<dyn ClusterImpl>, pb::Bucket)> {
6067
let mut bucket_map = HashMap::new();
6168

6269
for cluster_cfg in clusters {
63-
let cluster = new_cluster(&cluster_cfg);
70+
let cluster = match cluster_cfg.provider {
71+
Some(provider) => new_cluster(secrets, provider),
72+
None => {
73+
log::error!("missing bucket cluster provider: {}", cluster_cfg.rid);
74+
Arc::new(noop::Cluster)
75+
}
76+
};
6477

6578
for bucket_cfg in cluster_cfg.buckets {
6679
bucket_map.insert(
@@ -73,14 +86,18 @@ fn make_cfg_maps(
7386
bucket_map
7487
}
7588

76-
fn new_cluster(cluster: &pb::BucketCluster) -> Arc<dyn ClusterImpl> {
77-
let Some(provider) = &cluster.provider else {
78-
log::error!("missing bucket cluster provider: {}", cluster.rid);
79-
return Arc::new(noop::Cluster);
80-
};
81-
89+
fn new_cluster(
90+
secrets: &secrets::Manager,
91+
provider: pb::bucket_cluster::Provider,
92+
) -> Arc<dyn ClusterImpl> {
8293
match provider {
83-
pb::bucket_cluster::Provider::S3(s3cfg) => Arc::new(s3::Cluster::new(s3cfg)),
94+
pb::bucket_cluster::Provider::S3(s3cfg) => {
95+
let secret_access_key = s3cfg
96+
.secret_access_key
97+
.as_ref()
98+
.map(|k| secrets.load(k.clone()));
99+
Arc::new(s3::Cluster::new(s3cfg, secret_access_key))
100+
}
84101
pb::bucket_cluster::Provider::Gcs(gcscfg) => Arc::new(gcs::Cluster::new(gcscfg.clone())),
85102
}
86103
}

runtimes/core/src/objects/mod.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -493,16 +493,13 @@ fn escape_path(s: &str) -> Cow<'_, str> {
493493
percent_encoding::percent_encode(s.as_bytes(), PATH).into()
494494
}
495495

496-
/// Computes the public url given a base url, optional key prefix, and object name.
497-
fn public_url(base_url: String, key_prefix: Option<&str>, name: &str) -> String {
496+
/// Computes the public url given a base url and object name.
497+
fn public_url(base_url: String, name: &str) -> String {
498498
let mut url = base_url;
499499

500500
if !url.ends_with('/') {
501501
url.push('/');
502502
}
503-
if let Some(key_prefix) = key_prefix {
504-
url.push_str(&escape_path(key_prefix));
505-
}
506503
url.push_str(&escape_path(name));
507504
url
508505
}

0 commit comments

Comments
 (0)