Skip to content

Commit a85bae1

Browse files
committed
Add support for AWS STS endpoint in the Bucket API
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
1 parent 218af57 commit a85bae1

File tree

10 files changed

+482
-41
lines changed

10 files changed

+482
-41
lines changed

api/v1beta2/bucket_types.go

+24
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ const (
4949

5050
// BucketSpec specifies the required configuration to produce an Artifact for
5151
// an object storage bucket.
52+
// +kubebuilder:validation:XValidation:rule="self.provider != 'aws' || !has(self.sts) || self.sts.provider == 'aws'", message="'aws' is the only supported STS provider for the 'aws' Bucket provider"
5253
type BucketSpec struct {
5354
// Provider of the object storage bucket.
5455
// Defaults to 'generic', which expects an S3 (API) compatible object
@@ -66,6 +67,14 @@ type BucketSpec struct {
6667
// +required
6768
Endpoint string `json:"endpoint"`
6869

70+
// STS specifies the required configuration to use a Security Token
71+
// Service for fetching temporary credentials to authenticate in a
72+
// Bucket provider.
73+
//
74+
// This field is only supported for the `aws` provider.
75+
// +optional
76+
STS *BucketSTSSpec `json:"sts,omitempty"`
77+
6978
// Insecure allows connecting to a non-TLS HTTP Endpoint.
7079
// +optional
7180
Insecure bool `json:"insecure,omitempty"`
@@ -140,6 +149,21 @@ type BucketSpec struct {
140149
AccessFrom *acl.AccessFrom `json:"accessFrom,omitempty"`
141150
}
142151

152+
// BucketSTSSpec specifies the required configuration to use a Security Token
153+
// Service for fetching temporary credentials to authenticate in a Bucket
154+
// provider.
155+
type BucketSTSSpec struct {
156+
// Provider of the Security Token Service.
157+
// +kubebuilder:validation:Enum=aws
158+
// +required
159+
Provider string `json:"provider"`
160+
161+
// Endpoint is the HTTP/S endpoint of the Security Token Service from
162+
// where temporary credentials will be fetched.
163+
// +required
164+
Endpoint string `json:"endpoint"`
165+
}
166+
143167
// BucketStatus records the observed state of a Bucket.
144168
type BucketStatus struct {
145169
// ObservedGeneration is the last observed generation of the Bucket object.

api/v1beta2/sts_types.go

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
Copyright 2024 The Flux authors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package v1beta2
18+
19+
const (
20+
// STSProviderAmazon represents the AWS provider for Security Token Service.
21+
// Provides support for fetching temporary credentials from an AWS STS endpoint.
22+
STSProviderAmazon string = "aws"
23+
)

api/v1beta2/zz_generated.deepcopy.go

+20
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/source.toolkit.fluxcd.io_buckets.yaml

+28
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,29 @@ spec:
420420
required:
421421
- name
422422
type: object
423+
sts:
424+
description: |-
425+
STS specifies the required configuration to use a Security Token
426+
Service for fetching temporary credentials to authenticate in a
427+
Bucket provider.
428+
429+
430+
This field is only supported for the `aws` provider.
431+
properties:
432+
endpoint:
433+
description: |-
434+
Endpoint is the HTTP/S endpoint of the Security Token Service from
435+
where temporary credentials will be fetched.
436+
type: string
437+
provider:
438+
description: Provider of the Security Token Service.
439+
enum:
440+
- aws
441+
type: string
442+
required:
443+
- endpoint
444+
- provider
445+
type: object
423446
suspend:
424447
description: |-
425448
Suspend tells the controller to suspend the reconciliation of this
@@ -435,6 +458,11 @@ spec:
435458
- endpoint
436459
- interval
437460
type: object
461+
x-kubernetes-validations:
462+
- message: '''aws'' is the only supported STS provider for the ''aws''
463+
Bucket provider'
464+
rule: self.provider != 'aws' || !has(self.sts) || self.sts.provider
465+
== 'aws'
438466
status:
439467
default:
440468
observedGeneration: -1

docs/api/v1beta2/source.md

+80
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,23 @@ string
114114
</tr>
115115
<tr>
116116
<td>
117+
<code>sts</code><br>
118+
<em>
119+
<a href="#source.toolkit.fluxcd.io/v1beta2.BucketSTSSpec">
120+
BucketSTSSpec
121+
</a>
122+
</em>
123+
</td>
124+
<td>
125+
<em>(Optional)</em>
126+
<p>STS specifies the required configuration to use a Security Token
127+
Service for fetching temporary credentials to authenticate in a
128+
Bucket provider.</p>
129+
<p>This field is only supported for the <code>aws</code> provider.</p>
130+
</td>
131+
</tr>
132+
<tr>
133+
<td>
117134
<code>insecure</code><br>
118135
<em>
119136
bool
@@ -1424,6 +1441,52 @@ map[string]string
14241441
</table>
14251442
</div>
14261443
</div>
1444+
<h3 id="source.toolkit.fluxcd.io/v1beta2.BucketSTSSpec">BucketSTSSpec
1445+
</h3>
1446+
<p>
1447+
(<em>Appears on:</em>
1448+
<a href="#source.toolkit.fluxcd.io/v1beta2.BucketSpec">BucketSpec</a>)
1449+
</p>
1450+
<p>BucketSTSSpec specifies the required configuration to use a Security Token
1451+
Service for fetching temporary credentials to authenticate in a Bucket
1452+
provider.</p>
1453+
<div class="md-typeset__scrollwrap">
1454+
<div class="md-typeset__table">
1455+
<table>
1456+
<thead>
1457+
<tr>
1458+
<th>Field</th>
1459+
<th>Description</th>
1460+
</tr>
1461+
</thead>
1462+
<tbody>
1463+
<tr>
1464+
<td>
1465+
<code>provider</code><br>
1466+
<em>
1467+
string
1468+
</em>
1469+
</td>
1470+
<td>
1471+
<p>Provider of the Security Token Service.</p>
1472+
</td>
1473+
</tr>
1474+
<tr>
1475+
<td>
1476+
<code>endpoint</code><br>
1477+
<em>
1478+
string
1479+
</em>
1480+
</td>
1481+
<td>
1482+
<p>Endpoint is the HTTP/S endpoint of the Security Token Service from
1483+
where temporary credentials will be fetched.</p>
1484+
</td>
1485+
</tr>
1486+
</tbody>
1487+
</table>
1488+
</div>
1489+
</div>
14271490
<h3 id="source.toolkit.fluxcd.io/v1beta2.BucketSpec">BucketSpec
14281491
</h3>
14291492
<p>
@@ -1480,6 +1543,23 @@ string
14801543
</tr>
14811544
<tr>
14821545
<td>
1546+
<code>sts</code><br>
1547+
<em>
1548+
<a href="#source.toolkit.fluxcd.io/v1beta2.BucketSTSSpec">
1549+
BucketSTSSpec
1550+
</a>
1551+
</em>
1552+
</td>
1553+
<td>
1554+
<em>(Optional)</em>
1555+
<p>STS specifies the required configuration to use a Security Token
1556+
Service for fetching temporary credentials to authenticate in a
1557+
Bucket provider.</p>
1558+
<p>This field is only supported for the <code>aws</code> provider.</p>
1559+
</td>
1560+
</tr>
1561+
<tr>
1562+
<td>
14831563
<code>insecure</code><br>
14841564
<em>
14851565
bool

docs/spec/v1beta2/buckets.md

+17
Original file line numberDiff line numberDiff line change
@@ -749,6 +749,23 @@ HTTP endpoint requires enabling [`.spec.insecure`](#insecure).
749749
Some endpoints require the specification of a [`.spec.region`](#region),
750750
see [Provider](#provider) for more (provider specific) examples.
751751

752+
### STS
753+
754+
`.spec.sts` is an optional field for specifying the Security Token Service
755+
configuration. A Security Token Service (STS) is a web service that issues
756+
temporary security credentials. By adding this field, one may specify the
757+
STS endpoint from where temporary credentials will be fetched.
758+
759+
If using `.spec.sts`, the following fields are required:
760+
761+
- `.spec.sts.provider`, the Security Token Service provider. The only supported
762+
option is `aws`.
763+
- `.spec.sts.endpoint`, the HTTP/S endpoint of the Security Token Service. In
764+
the case of AWS, this can be `https://sts.amazonaws.com`, or a Regional STS
765+
Endpoint, or an Interface Endpoint created inside a VPC.
766+
767+
This field is only supported for the `aws` bucket provider.
768+
752769
### Bucket name
753770

754771
`.spec.bucketName` is a required field that specifies which object storage

pkg/minio/minio.go

+36-15
Original file line numberDiff line numberDiff line change
@@ -88,21 +88,6 @@ func NewClient(bucket *sourcev1.Bucket, opts ...Option) (*MinioClient, error) {
8888
// auto access, which we believe can cover most use cases.
8989
}
9090

91-
if secret != nil {
92-
var accessKey, secretKey string
93-
if k, ok := secret.Data["accesskey"]; ok {
94-
accessKey = string(k)
95-
}
96-
if k, ok := secret.Data["secretkey"]; ok {
97-
secretKey = string(k)
98-
}
99-
if accessKey != "" && secretKey != "" {
100-
minioOpts.Creds = credentials.NewStaticV4(accessKey, secretKey, "")
101-
}
102-
} else if bucket.Spec.Provider == sourcev1.AmazonBucketProvider {
103-
minioOpts.Creds = credentials.NewIAM("")
104-
}
105-
10691
var transportOpts []func(*http.Transport)
10792

10893
if minioOpts.Secure && tlsConfig != nil {
@@ -117,6 +102,42 @@ func NewClient(bucket *sourcev1.Bucket, opts ...Option) (*MinioClient, error) {
117102
})
118103
}
119104

105+
switch bucketProvider := bucket.Spec.Provider; {
106+
case secret != nil:
107+
var accessKey, secretKey string
108+
if k, ok := secret.Data["accesskey"]; ok {
109+
accessKey = string(k)
110+
}
111+
if k, ok := secret.Data["secretkey"]; ok {
112+
secretKey = string(k)
113+
}
114+
if accessKey != "" && secretKey != "" {
115+
minioOpts.Creds = credentials.NewStaticV4(accessKey, secretKey, "")
116+
}
117+
case bucketProvider == sourcev1.AmazonBucketProvider:
118+
stsEndpoint := ""
119+
if sts := bucket.Spec.STS; sts != nil {
120+
if sts.Provider != sourcev1.STSProviderAmazon {
121+
return nil, fmt.Errorf("STS provider '%s' is not supported for Bucket provider '%s'",
122+
sts.Provider, sourcev1.AmazonBucketProvider)
123+
}
124+
stsEndpoint = sts.Endpoint
125+
}
126+
127+
creds := credentials.NewIAM(stsEndpoint)
128+
if len(transportOpts) > 0 {
129+
transport := http.DefaultTransport.(*http.Transport).Clone()
130+
for _, opt := range transportOpts {
131+
opt(transport)
132+
}
133+
creds = credentials.New(&credentials.IAM{
134+
Client: &http.Client{Transport: transport},
135+
Endpoint: stsEndpoint,
136+
})
137+
}
138+
minioOpts.Creds = creds
139+
}
140+
120141
if len(transportOpts) > 0 {
121142
transport, err := minio.DefaultTransport(minioOpts.Secure)
122143
if err != nil {

0 commit comments

Comments
 (0)