Skip to content

Commit 9ae861c

Browse files
committed
Support a separate URL base for pre-signed URLs
This allows the Ark server to use one URL for the majority of communications with S3 (or compatible) object storage, and a different URL base for pre-signed URLs (for streaming logs, etc. to clients). Signed-off-by: Andy Goldstein <[email protected]>
1 parent 449cac5 commit 9ae861c

File tree

2 files changed

+44
-17
lines changed

2 files changed

+44
-17
lines changed

docs/api-types/backupstoragelocation.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ The configurable parameters are as follows:
4949
| `region` | string | Empty | *Example*: "us-east-1"<br><br>See [AWS documentation][3] for the full list.<br><br>Queried from the AWS S3 API if not provided. |
5050
| `s3ForcePathStyle` | bool | `false` | Set this to `true` if you are using a local storage service like Minio. |
5151
| `s3Url` | string | Required field for non-AWS-hosted storage| *Example*: http://minio:9000<br><br>You can specify the AWS S3 URL here for explicitness, but Ark can already generate it from `region`, and `bucket`. This field is primarily for local storage services like Minio.|
52+
| `publicUrl` | string | Empty | *Example*: https://minio.mycluster.com<br><br>If specified, use this instead of `s3Url` when generating download URLs (e.g., for logs). This field is primarily for local storage services like Minio.|
5253
| `kmsKeyId` | string | Empty | *Example*: "502b409c-4da1-419f-a16e-eif453b3i49f" or "alias/`<KMS-Key-Alias-Name>`"<br><br>Specify an [AWS KMS key][10] id or alias to enable encryption of the backups stored in S3. Only works with AWS S3 and may require explicitly granting key usage rights.|
5354

5455
#### Azure
@@ -67,4 +68,4 @@ No parameters required.
6768
[0]: #aws
6869
[1]: #gcp
6970
[2]: #azure
70-
[3]: http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions
71+
[3]: http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions

pkg/cloudprovider/aws/object_store.go

+42-16
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import (
3434

3535
const (
3636
s3URLKey = "s3Url"
37+
publicURLKey = "publicUrl"
3738
kmsKeyIDKey = "kmsKeyId"
3839
s3ForcePathStyleKey = "s3ForcePathStyle"
3940
bucketKey = "bucket"
@@ -42,6 +43,7 @@ const (
4243
type objectStore struct {
4344
log logrus.FieldLogger
4445
s3 *s3.S3
46+
preSignS3 *s3.S3
4547
s3Uploader *s3manager.Uploader
4648
kmsKeyID string
4749
}
@@ -54,6 +56,7 @@ func (o *objectStore) Init(config map[string]string) error {
5456
var (
5557
region = config[regionKey]
5658
s3URL = config[s3URLKey]
59+
publicURL = config[publicURLKey]
5760
kmsKeyID = config[kmsKeyIDKey]
5861
s3ForcePathStyleVal = config[s3ForcePathStyleKey]
5962

@@ -83,20 +86,52 @@ func (o *objectStore) Init(config map[string]string) error {
8386
}
8487
}
8588

89+
serverConfig, err := newAWSConfig(s3URL, region, s3ForcePathStyle)
90+
if err != nil {
91+
return err
92+
}
93+
94+
serverSession, err := getSession(serverConfig)
95+
if err != nil {
96+
return err
97+
}
98+
99+
o.s3 = s3.New(serverSession)
100+
o.s3Uploader = s3manager.NewUploader(serverSession)
101+
o.kmsKeyID = kmsKeyID
102+
103+
if publicURL != "" {
104+
publicConfig, err := newAWSConfig(publicURL, region, s3ForcePathStyle)
105+
if err != nil {
106+
return err
107+
}
108+
publicSession, err := getSession(publicConfig)
109+
if err != nil {
110+
return err
111+
}
112+
o.preSignS3 = s3.New(publicSession)
113+
} else {
114+
o.preSignS3 = o.s3
115+
}
116+
117+
return nil
118+
}
119+
120+
func newAWSConfig(url, region string, forcePathStyle bool) (*aws.Config, error) {
86121
awsConfig := aws.NewConfig().
87122
WithRegion(region).
88-
WithS3ForcePathStyle(s3ForcePathStyle)
123+
WithS3ForcePathStyle(forcePathStyle)
89124

90-
if s3URL != "" {
91-
if !IsValidS3URLScheme(s3URL) {
92-
return errors.Errorf("Invalid s3Url: %s", s3URL)
125+
if url != "" {
126+
if !IsValidS3URLScheme(url) {
127+
return nil, errors.Errorf("Invalid s3 url: %s", url)
93128
}
94129

95130
awsConfig = awsConfig.WithEndpointResolver(
96131
endpoints.ResolverFunc(func(service, region string, optFns ...func(*endpoints.Options)) (endpoints.ResolvedEndpoint, error) {
97132
if service == endpoints.S3ServiceID {
98133
return endpoints.ResolvedEndpoint{
99-
URL: s3URL,
134+
URL: url,
100135
}, nil
101136
}
102137

@@ -105,16 +140,7 @@ func (o *objectStore) Init(config map[string]string) error {
105140
)
106141
}
107142

108-
sess, err := getSession(awsConfig)
109-
if err != nil {
110-
return err
111-
}
112-
113-
o.s3 = s3.New(sess)
114-
o.s3Uploader = s3manager.NewUploader(sess)
115-
o.kmsKeyID = kmsKeyID
116-
117-
return nil
143+
return awsConfig, nil
118144
}
119145

120146
func (o *objectStore) PutObject(bucket, key string, body io.Reader) error {
@@ -208,7 +234,7 @@ func (o *objectStore) DeleteObject(bucket, key string) error {
208234
}
209235

210236
func (o *objectStore) CreateSignedURL(bucket, key string, ttl time.Duration) (string, error) {
211-
req, _ := o.s3.GetObjectRequest(&s3.GetObjectInput{
237+
req, _ := o.preSignS3.GetObjectRequest(&s3.GetObjectInput{
212238
Bucket: aws.String(bucket),
213239
Key: aws.String(key),
214240
})

0 commit comments

Comments
 (0)