Skip to content

Commit 2bf819f

Browse files
els-tmillerostafen
authored andcommitted
enable fargate credentials
1 parent ec39ec8 commit 2bf819f

File tree

8 files changed

+96
-18
lines changed

8 files changed

+96
-18
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,12 @@ export IMMUDB_S3_ENDPOINT="https://${IMMUDB_S3_BUCKET_NAME}.s3.${IMMUDB_S3_LOCAT
184184
./immudb
185185
```
186186

187+
If using Fargate, the credentials URL can be sourced automatically:
188+
189+
```bash
190+
export IMMUDB_S3_USE_FARGATE_CREDENTIALS=true
191+
```
192+
187193
Optionally, you can specify the exact role immudb should be using with:
188194

189195
```bash

cmd/immudb/command/init.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ func (cl *Commandline) setupFlags(cmd *cobra.Command, options *server.Options) {
8989
cmd.Flags().String("s3-path-prefix", "", "s3 path prefix (multiple immudb instances can share the same bucket if they have different prefixes)")
9090
cmd.Flags().Bool("s3-external-identifier", false, "use the remote identifier if there is no local identifier")
9191
cmd.Flags().String("s3-instance-metadata-url", "http://169.254.169.254", "s3 instance metadata url")
92+
cmd.Flags().String("s3-use-fargate-credentials", "false", "use fargate credentials for s3 authentication: true/false")
9293
cmd.Flags().Int("max-sessions", 100, "maximum number of simultaneously opened sessions")
9394
cmd.Flags().Duration("max-session-inactivity-time", 3*time.Minute, "max session inactivity time is a duration after which an active session is declared inactive by the server. A session is kept active if server is still receiving requests from client (keep-alive or other methods)")
9495
cmd.Flags().Duration("max-session-age-time", 0, "the current default value is infinity. max session age time is a duration after which session will be forcibly closed")

cmd/immudb/command/parse_options.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ func parseOptions() (options *server.Options, err error) {
106106
s3PathPrefix := viper.GetString("s3-path-prefix")
107107
s3ExternalIdentifier := viper.GetBool("s3-external-identifier")
108108
s3MetadataURL := viper.GetString("s3-instance-metadata-url")
109+
s3UseFargateCredentials := viper.GetBool("s3-use-fargate-credentials")
109110

110111
remoteStorageOptions := server.DefaultRemoteStorageOptions().
111112
WithS3Storage(s3Storage).
@@ -118,7 +119,8 @@ func parseOptions() (options *server.Options, err error) {
118119
WithS3Location(s3Location).
119120
WithS3PathPrefix(s3PathPrefix).
120121
WithS3ExternalIdentifier(s3ExternalIdentifier).
121-
WithS3InstanceMetadataURL(s3MetadataURL)
122+
WithS3InstanceMetadataURL(s3MetadataURL).
123+
WithS3UseFargateCredentials(s3UseFargateCredentials)
122124

123125
sessionOptions := sessions.DefaultOptions().
124126
WithMaxSessions(viper.GetInt("max-sessions")).

embedded/remotestorage/s3/s3.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ type Storage struct {
5656

5757
awsInstanceMetadataURL string
5858
awsCredsRefreshPeriod time.Duration
59+
60+
useFargateCredentials bool
5961
}
6062

6163
var (
@@ -99,6 +101,7 @@ func Open(
99101
location string,
100102
prefix string,
101103
awsInstanceMetadataURL string,
104+
useFargateCredentials bool,
102105
) (remotestorage.Storage, error) {
103106

104107
// Endpoint must always end with '/'
@@ -137,6 +140,7 @@ func Open(
137140
},
138141
awsInstanceMetadataURL: awsInstanceMetadataURL,
139142
awsCredsRefreshPeriod: time.Minute,
143+
useFargateCredentials: useFargateCredentials,
140144
}
141145

142146
err := s3storage.getRoleCredentials()
@@ -807,6 +811,45 @@ func (s *Storage) getRoleCredentials() error {
807811
}
808812

809813
func (s *Storage) requestCredentials() (string, string, string, error) {
814+
if s.useFargateCredentials {
815+
// Use Fargate credentials
816+
817+
const fargateMetadataEndpoint = "http://169.254.170.2"
818+
819+
fargateCredentialsRelativeURI := os.Getenv("AWS_CONTAINER_CREDENTIALS_RELATIVE_URI")
820+
if fargateCredentialsRelativeURI == "" {
821+
return "", "", "", errors.New("environment variable AWS_CONTAINER_CREDENTIALS_RELATIVE_URI is not set or empty")
822+
}
823+
fargateCredentialsURL := fargateMetadataEndpoint + fargateCredentialsRelativeURI
824+
825+
fargateReq, err := http.NewRequest("GET", fargateCredentialsURL, nil)
826+
if err != nil {
827+
return "", "", "", errors.New("cannot form fargate credentials request")
828+
}
829+
830+
fargateResp, err := http.DefaultClient.Do(fargateReq)
831+
if err != nil {
832+
return "", "", "", errors.New("cannot get fargate credentials")
833+
}
834+
defer fargateResp.Body.Close()
835+
836+
creds, err := io.ReadAll(fargateResp.Body)
837+
if err != nil {
838+
return "", "", "", errors.New("cannot read fargate credentials")
839+
}
840+
841+
var credentials struct {
842+
AccessKeyID string `json:"AccessKeyId"`
843+
SecretAccessKey string `json:"SecretAccessKey"`
844+
SessionToken string `json:"Token"`
845+
}
846+
if err := json.Unmarshal(creds, &credentials); err != nil {
847+
return "", "", "", errors.New("cannot parse fargate credentials")
848+
}
849+
850+
return credentials.AccessKeyID, credentials.SecretAccessKey, credentials.SessionToken, nil
851+
}
852+
810853
tokenReq, err := http.NewRequest("PUT", fmt.Sprintf("%s%s",
811854
s.awsInstanceMetadataURL,
812855
"/latest/api/token",

embedded/remotestorage/s3/s3_test.go

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ func TestOpen(t *testing.T) {
4141
"",
4242
"prefix",
4343
"",
44+
false,
4445
)
4546
require.NoError(t, err)
4647
require.NotNil(t, s)
@@ -90,6 +91,7 @@ func TestCornerCases(t *testing.T) {
9091
"",
9192
"",
9293
"",
94+
false,
9395
)
9496
require.ErrorIs(t, err, ErrInvalidArguments)
9597
require.ErrorIs(t, err, ErrInvalidArgumentsBucketEmpty)
@@ -107,6 +109,7 @@ func TestCornerCases(t *testing.T) {
107109
"",
108110
"",
109111
"",
112+
false,
110113
)
111114
require.ErrorIs(t, err, ErrInvalidArguments)
112115
require.ErrorIs(t, err, ErrInvalidArgumentsBucketSlash)
@@ -124,6 +127,7 @@ func TestCornerCases(t *testing.T) {
124127
"",
125128
"",
126129
"",
130+
false,
127131
)
128132
require.NoError(t, err)
129133
require.Equal(t, "", s.(*Storage).prefix)
@@ -138,6 +142,7 @@ func TestCornerCases(t *testing.T) {
138142
"",
139143
"/test/",
140144
"",
145+
false,
141146
)
142147
require.NoError(t, err)
143148
require.Equal(t, "test/", s.(*Storage).prefix)
@@ -152,6 +157,7 @@ func TestCornerCases(t *testing.T) {
152157
"",
153158
"/test",
154159
"",
160+
false,
155161
)
156162
require.NoError(t, err)
157163
require.Equal(t, "test/", s.(*Storage).prefix)
@@ -168,6 +174,7 @@ func TestCornerCases(t *testing.T) {
168174
"",
169175
"",
170176
"",
177+
false,
171178
)
172179
require.NoError(t, err)
173180
require.Equal(t, "s3(misconfigured)", s.String())
@@ -184,6 +191,7 @@ func TestCornerCases(t *testing.T) {
184191
"",
185192
"",
186193
"",
194+
false,
187195
)
188196
require.NoError(t, err)
189197

@@ -211,6 +219,7 @@ func TestCornerCases(t *testing.T) {
211219
"",
212220
"",
213221
"",
222+
false,
214223
)
215224
require.NoError(t, err)
216225

@@ -230,6 +239,7 @@ func TestCornerCases(t *testing.T) {
230239
"",
231240
"",
232241
"",
242+
false,
233243
)
234244
require.Error(t, err)
235245
require.Nil(t, s)
@@ -246,6 +256,7 @@ func TestCornerCases(t *testing.T) {
246256
"",
247257
"",
248258
"",
259+
false,
249260
)
250261
require.NoError(t, err)
251262

@@ -262,7 +273,7 @@ func TestCornerCases(t *testing.T) {
262273
}))
263274
defer ts.Close()
264275

265-
s, err := Open(ts.URL, false, "", "", "", "bucket", "", "", "")
276+
s, err := Open(ts.URL, false, "", "", "", "bucket", "", "", "", false)
266277
require.NoError(t, err)
267278

268279
ctx := context.Background()
@@ -277,7 +288,7 @@ func TestCornerCases(t *testing.T) {
277288
}))
278289
defer ts.Close()
279290

280-
s, err := Open(ts.URL, false, "", "", "", "bucket", "", "", "")
291+
s, err := Open(ts.URL, false, "", "", "", "bucket", "", "", "", false)
281292
require.NoError(t, err)
282293

283294
ctx := context.Background()
@@ -300,6 +311,7 @@ func TestSignatureV4(t *testing.T) {
300311
"us-east-1",
301312
"",
302313
"",
314+
false,
303315
)
304316
require.NoError(t, err)
305317

@@ -378,7 +390,7 @@ func TestHandlingRedirects(t *testing.T) {
378390
}))
379391
defer ts.Close()
380392

381-
s, err := Open(ts.URL, false, "", "", "", "bucket", "", "", "")
393+
s, err := Open(ts.URL, false, "", "", "", "bucket", "", "", "", false)
382394
require.NoError(t, err)
383395

384396
ctx := context.Background()
@@ -761,7 +773,7 @@ func TestListEntries(t *testing.T) {
761773
}))
762774
defer ts.Close()
763775

764-
s, err := Open(ts.URL, false, "", "", "", "bucket", "", "", "")
776+
s, err := Open(ts.URL, false, "", "", "", "bucket", "", "", "", false)
765777
require.NoError(t, err)
766778

767779
ctx := context.Background()

embedded/remotestorage/s3/s3_with_minio_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ func TestS3WithServer(t *testing.T) {
4545
"",
4646
fmt.Sprintf("prefix_%x", randomBytes),
4747
"",
48+
false,
4849
)
4950
require.NoError(t, err)
5051

pkg/server/options.go

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -87,17 +87,18 @@ type Options struct {
8787
}
8888

8989
type RemoteStorageOptions struct {
90-
S3Storage bool
91-
S3RoleEnabled bool
92-
S3Role string
93-
S3Endpoint string
94-
S3AccessKeyID string
95-
S3SecretKey string `json:"-"`
96-
S3BucketName string
97-
S3Location string
98-
S3PathPrefix string
99-
S3ExternalIdentifier bool
100-
S3InstanceMetadataURL string
90+
S3Storage bool
91+
S3RoleEnabled bool
92+
S3Role string
93+
S3Endpoint string
94+
S3AccessKeyID string
95+
S3SecretKey string `json:"-"`
96+
S3BucketName string
97+
S3Location string
98+
S3PathPrefix string
99+
S3ExternalIdentifier bool
100+
S3InstanceMetadataURL string
101+
S3UseFargateCredentials bool
101102
}
102103

103104
type ReplicationOptions struct {
@@ -370,7 +371,11 @@ func (o *Options) String() string {
370371
opts = append(opts, "S3 storage")
371372
if o.RemoteStorageOptions.S3RoleEnabled {
372373
opts = append(opts, rightPad(" role auth", o.RemoteStorageOptions.S3RoleEnabled))
373-
opts = append(opts, rightPad(" role name", o.RemoteStorageOptions.S3Role))
374+
if o.RemoteStorageOptions.S3UseFargateCredentials {
375+
opts = append(opts, rightPad(" fargate creds", o.RemoteStorageOptions.S3UseFargateCredentials))
376+
} else {
377+
opts = append(opts, rightPad(" role name", o.RemoteStorageOptions.S3Role))
378+
}
374379
}
375380
opts = append(opts, rightPad(" endpoint", o.RemoteStorageOptions.S3Endpoint))
376381
opts = append(opts, rightPad(" bucket name", o.RemoteStorageOptions.S3BucketName))
@@ -379,7 +384,9 @@ func (o *Options) String() string {
379384
}
380385
opts = append(opts, rightPad(" prefix", o.RemoteStorageOptions.S3PathPrefix))
381386
opts = append(opts, rightPad(" external id", o.RemoteStorageOptions.S3ExternalIdentifier))
382-
opts = append(opts, rightPad(" metadata url", o.RemoteStorageOptions.S3InstanceMetadataURL))
387+
if !o.RemoteStorageOptions.S3UseFargateCredentials {
388+
opts = append(opts, rightPad(" metadata url", o.RemoteStorageOptions.S3InstanceMetadataURL))
389+
}
383390
}
384391
if o.AdminPassword == auth.SysAdminPassword {
385392
opts = append(opts, "----------------------------------------")
@@ -599,6 +606,11 @@ func (opts *RemoteStorageOptions) WithS3InstanceMetadataURL(url string) *RemoteS
599606
return opts
600607
}
601608

609+
func (opts *RemoteStorageOptions) WithS3UseFargateCredentials(s3UseFargateCredentials bool) *RemoteStorageOptions {
610+
opts.S3UseFargateCredentials = s3UseFargateCredentials
611+
return opts
612+
}
613+
602614
// ReplicationOptions
603615

604616
func (opts *ReplicationOptions) WithIsReplica(isReplica bool) *ReplicationOptions {

pkg/server/remote_storage.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ func (s *ImmuServer) createRemoteStorageInstance() (remotestorage.Storage, error
6060
s.Options.RemoteStorageOptions.S3Location,
6161
s.Options.RemoteStorageOptions.S3PathPrefix,
6262
s.Options.RemoteStorageOptions.S3InstanceMetadataURL,
63+
s.Options.RemoteStorageOptions.S3UseFargateCredentials,
6364
)
6465
}
6566

0 commit comments

Comments
 (0)