Visitar URL original
feat(bucket): add publicRead to serve a bucket without credentials · cozystack/cozystack@2568555 · GitHub
Skip to content

Commit 2568555

Browse files
feat(bucket): add publicRead to serve a bucket without credentials
A bucket cannot serve its objects without a signature: every BucketAccess issues a key, and the keys grant neither WriteAcp nor PutBucketPolicy, so a tenant cannot open the bucket themselves with put-bucket-acl. Static assets then need a proxy, presigned URLs or an operator running weed shell by hand, which no reconcile tracks and which outlives the bucket. publicRead renders one more BucketAccess on a new -public access class whose accessPolicy is public-read. The COSI driver handles that policy by adding Read:<bucket> to the gateway's anonymous identity and removing only that action on revoke, so deleting the bucket or turning the flag off closes it again without touching other public buckets. Anonymous callers can read objects but cannot list the bucket or write to it. The access is named <bucket>-public-read, the name a user called public-read would take, so that combination fails to render instead of fighting over one BucketAccess. Assisted-by: LLM Signed-off-by: Mattia Eleuteri <mattia@hidora.io>
1 parent 1f35c26 commit 2568555

13 files changed

Lines changed: 231 additions & 11 deletions

File tree

‎api/apps/v1alpha1/bucket/types.go‎

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

‎packages/apps/bucket/README.md‎

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@
44

55
### Parameters
66

7-
| Name | Description | Type | Value |
8-
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- | ------- |
9-
| `locking` | Provisions bucket from the `-lock` BucketClass (with object lock enabled). | `bool` | `false` |
10-
| `storagePool` | Selects a specific BucketClass by storage pool name. | `string` | `""` |
11-
| `ui` | Deploys the web UI (s3manager) with its Service and its Ingress or HTTPRoute at `<bucket>.<tenant host>`. Set to `false` to run the bucket without them. | `bool` | `true` |
12-
| `users` | Users configuration map. | `map[string]object` | `{}` |
13-
| `users[name].readonly` | Whether the user has read-only access. | `bool` | `false` |
7+
| Name | Description | Type | Value |
8+
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- | ------- |
9+
| `locking` | Provisions bucket from the `-lock` BucketClass (with object lock enabled). | `bool` | `false` |
10+
| `storagePool` | Selects a specific BucketClass by storage pool name. | `string` | `""` |
11+
| `ui` | Deploys the web UI (s3manager) with its Service and its Ingress or HTTPRoute at `<bucket>.<tenant host>`. Set to `false` to run the bucket without them. | `bool` | `true` |
12+
| `publicRead` | Serves the bucket's objects to anyone without credentials at `<endpoint>/<bucket>/<key>`. Anonymous callers can read objects but cannot list the bucket or write to it. | `bool` | `false` |
13+
| `users` | Users configuration map. | `map[string]object` | `{}` |
14+
| `users[name].readonly` | Whether the user has read-only access. | `bool` | `false` |
1415

‎packages/apps/bucket/templates/bucketclaim.yaml‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,18 @@ spec:
2222
credentialsSecretName: {{ $.Release.Name }}-{{ $name }}
2323
protocol: s3
2424
{{- end }}
25+
{{- if .Values.publicRead }}
26+
{{- if hasKey .Values.users "public-read" }}
27+
{{- fail "publicRead creates the BucketAccess <bucket>-public-read, which the user \"public-read\" already owns: rename that user" }}
28+
{{- end }}
29+
---
30+
apiVersion: objectstorage.k8s.io/v1alpha1
31+
kind: BucketAccess
32+
metadata:
33+
name: {{ .Release.Name }}-public-read
34+
spec:
35+
bucketAccessClassName: {{ $seaweedfs }}{{- if $pool }}-{{ $pool }}{{- end }}-public
36+
bucketClaimName: {{ .Release.Name }}
37+
credentialsSecretName: {{ .Release.Name }}-public-read
38+
protocol: s3
39+
{{- end }}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
suite: bucket publicRead
2+
templates:
3+
- templates/bucketclaim.yaml
4+
5+
release:
6+
name: bucket-my-bucket
7+
namespace: tenant-root
8+
9+
set:
10+
_namespace:
11+
seaweedfs: tenant-root
12+
13+
tests:
14+
- it: renders no public BucketAccess by default
15+
asserts:
16+
- hasDocuments:
17+
count: 1
18+
- isKind:
19+
of: BucketClaim
20+
21+
- it: renders a public-read BucketAccess on the -public class
22+
set:
23+
publicRead: true
24+
documentSelector:
25+
path: metadata.name
26+
value: bucket-my-bucket-public-read
27+
asserts:
28+
- isKind:
29+
of: BucketAccess
30+
- equal:
31+
path: spec.bucketAccessClassName
32+
value: tenant-root-public
33+
- equal:
34+
path: spec.bucketClaimName
35+
value: bucket-my-bucket
36+
- equal:
37+
path: spec.credentialsSecretName
38+
value: bucket-my-bucket-public-read
39+
40+
- it: uses the storage pool's -public class
41+
set:
42+
publicRead: true
43+
storagePool: fast
44+
documentSelector:
45+
path: metadata.name
46+
value: bucket-my-bucket-public-read
47+
asserts:
48+
- equal:
49+
path: spec.bucketAccessClassName
50+
value: tenant-root-fast-public
51+
52+
- it: keeps the access class free of -lock on a locked bucket
53+
set:
54+
publicRead: true
55+
locking: true
56+
documentSelector:
57+
path: metadata.name
58+
value: bucket-my-bucket-public-read
59+
asserts:
60+
- equal:
61+
path: spec.bucketAccessClassName
62+
value: tenant-root-public
63+
64+
- it: keeps the users' BucketAccesses next to the public one
65+
set:
66+
publicRead: true
67+
users:
68+
app: {}
69+
reader:
70+
readonly: true
71+
asserts:
72+
- hasDocuments:
73+
count: 4
74+
75+
- it: refuses a user that would own the public BucketAccess name
76+
set:
77+
publicRead: true
78+
users:
79+
public-read: {}
80+
asserts:
81+
- failedTemplate:
82+
errorPattern: user "public-read" already owns

‎packages/apps/bucket/values.schema.json‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@
2020
"type": "boolean",
2121
"default": true
2222
},
23+
"publicRead": {
24+
"description": "Serves the bucket's objects to anyone without credentials at `\u003cendpoint\u003e/\u003cbucket\u003e/\u003ckey\u003e`. Anonymous callers can read objects but cannot list the bucket or write to it.",
25+
"type": "boolean",
26+
"default": false
27+
},
2328
"users": {
2429
"description": "Users configuration map.",
2530
"type": "object",

‎packages/apps/bucket/values.yaml‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ storagePool: ""
88
## @param {bool} ui=true - Deploys the web UI (s3manager) with its Service and its Ingress or HTTPRoute at `<bucket>.<tenant host>`. Set to `false` to run the bucket without them.
99
ui: true
1010

11+
## @param {bool} publicRead=false - Serves the bucket's objects to anyone without credentials at `<endpoint>/<bucket>/<key>`. Anonymous callers can read objects but cannot list the bucket or write to it.
12+
publicRead: false
13+
1114
## @typedef {struct} User - Bucket user configuration.
1215
## @field {bool} [readonly] - Whether the user has read-only access.
1316

‎packages/extra/seaweedfs/templates/client/cosi-bucket-class.yaml‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,13 @@ driverName: {{ .Release.Namespace }}.seaweedfs.objectstorage.k8s.io
3535
authenticationType: KEY
3636
parameters:
3737
accessPolicy: readonly
38+
---
39+
kind: BucketAccessClass
40+
apiVersion: objectstorage.k8s.io/v1alpha1
41+
metadata:
42+
name: {{ .Release.Namespace }}-public
43+
driverName: {{ .Release.Namespace }}.seaweedfs.objectstorage.k8s.io
44+
authenticationType: KEY
45+
parameters:
46+
accessPolicy: public-read
3847
{{- end }}

‎packages/extra/seaweedfs/templates/storage-pool-bucket-classes.yaml‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,5 +51,14 @@ driverName: {{ $.Release.Namespace }}.seaweedfs.objectstorage.k8s.io
5151
authenticationType: KEY
5252
parameters:
5353
accessPolicy: readonly
54+
---
55+
kind: BucketAccessClass
56+
apiVersion: objectstorage.k8s.io/v1alpha1
57+
metadata:
58+
name: {{ $.Release.Namespace }}-{{ $poolName }}-public
59+
driverName: {{ $.Release.Namespace }}.seaweedfs.objectstorage.k8s.io
60+
authenticationType: KEY
61+
parameters:
62+
accessPolicy: public-read
5463
{{- end }}
5564
{{- end }}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
suite: seaweedfs public-read BucketAccessClass
2+
release:
3+
name: seaweedfs
4+
namespace: tenant-root
5+
6+
set:
7+
filer:
8+
grpcHost: seaweedfs-filer.tenant-other.svc
9+
_namespace:
10+
host: example.org
11+
ingress: tenant-root
12+
_cluster:
13+
issuer-name: letsencrypt-prod
14+
solver: http01
15+
16+
tests:
17+
- it: offers a -public access class to a Client instance
18+
template: templates/client/cosi-bucket-class.yaml
19+
set:
20+
topology: Client
21+
documentSelector:
22+
path: metadata.name
23+
value: tenant-root-public
24+
asserts:
25+
- isKind:
26+
of: BucketAccessClass
27+
- equal:
28+
path: parameters.accessPolicy
29+
value: public-read
30+
- equal:
31+
path: driverName
32+
value: tenant-root.seaweedfs.objectstorage.k8s.io
33+
34+
- it: offers a -public access class per storage pool
35+
template: templates/storage-pool-bucket-classes.yaml
36+
set:
37+
topology: Simple
38+
volume:
39+
pools:
40+
fast:
41+
diskType: ssd
42+
documentSelector:
43+
path: metadata.name
44+
value: tenant-root-fast-public
45+
asserts:
46+
- isKind:
47+
of: BucketAccessClass
48+
- equal:
49+
path: parameters.accessPolicy
50+
value: public-read

‎packages/system/bucket-rd/cozyrds/bucket.yaml‎

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

0 commit comments

Comments
 (0)