Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions charts/substrate/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ See `values.yaml` for the full set; the important keys:
| `atenetEgress.extraCredentialProviders` | `[]` | Credential providers you deploy, added after the bundled `k8s.io` provider, each `{name, address}`. `name` is the host of the `ate-secret://` URIs it serves; `address` is the `host:port` the egress gateway dials over mTLS. Its serving certificate must chain to the servicedns CA. See [egress credential injection](../../docs/guides/egress-credential-injection.md#the-plugin-api) |
| `atenetEgress.agentgateway.logLevel` | `info` | Egress proxy `RUST_LOG` filter, e.g. `debug` or `info,agentgateway=debug` when troubleshooting |
| `rustfs.enabled` | `true` | Deploy an in-cluster S3-compatible RustFS bucket for snapshots |
| `rustfs.existingSecret` | `""` | Secret with `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` for RustFS, its bucket-init Job and the object-store plugin, instead of the literal `rustfs.accessKey`/`rustfs.secretKey`. The atelet chart's `objectStore.credentialsSecret` takes the same keys |
| `ateApi.snapshotLocation` | `""` | Cluster-wide snapshot URI; defaults to `gs://<rustfs.bucket>/` with bundled RustFS |
| `atelet.enabled` | `true` | Deprecated. Set to `false` and install atelet with the [substrate-atelet](../substrate-atelet/README.md) chart |
| `atelet.storageBackend` | `s3` | Default snapshot backend, wired to RustFS when `rustfs.enabled=true` |
Expand Down
35 changes: 31 additions & 4 deletions charts/substrate/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -250,16 +250,43 @@ definition so the fallback cannot drift between pods.
value: http://{{ include "substrate.fullname" (list "rustfs" .) }}.{{ .Release.Namespace }}.svc:9000
- name: AWS_S3_USE_PATH_STYLE
value: "true"
- name: AWS_ACCESS_KEY_ID
value: {{ .Values.rustfs.accessKey | quote }}
- name: AWS_SECRET_ACCESS_KEY
value: {{ .Values.rustfs.secretKey | quote }}
{{ include "substrate.rustfs.credentialsEnv" (list "AWS_ACCESS_KEY_ID" "AWS_SECRET_ACCESS_KEY" .) }}
{{- end }}
{{- with .Values.objectStorePlugin.extraEnv }}
{{ toYaml . }}
{{- end }}
{{- end }}

{{/*
RustFS credential env vars. Usage:
include "substrate.rustfs.credentialsEnv" (list "<access key var>" "<secret key var>" .)
With rustfs.existingSecret the values come from that Secret's
AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY keys, otherwise from
rustfs.accessKey and rustfs.secretKey.
*/}}
{{- define "substrate.rustfs.credentialsEnv" -}}
{{- $ctx := index . 2 -}}
{{- $secret := $ctx.Values.rustfs.existingSecret -}}
- name: {{ index . 0 }}
{{- if $secret }}
valueFrom:
secretKeyRef:
name: {{ $secret | quote }}
key: AWS_ACCESS_KEY_ID
{{- else }}
value: {{ $ctx.Values.rustfs.accessKey | quote }}
{{- end }}
- name: {{ index . 1 }}
{{- if $secret }}
valueFrom:
secretKeyRef:
name: {{ $secret | quote }}
key: AWS_SECRET_ACCESS_KEY
{{- else }}
value: {{ $ctx.Values.rustfs.secretKey | quote }}
{{- end }}
{{- end -}}

{{/*
The egress gateway's credentialProviders: the bundled k8s.io provider when
credentialProvider.enabled, then atenetEgress.extraCredentialProviders. Renders
Expand Down
10 changes: 2 additions & 8 deletions charts/substrate/templates/rustfs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,7 @@ spec:
value: "true"
- name: RUSTFS_VOLUMES
value: "/data"
- name: RUSTFS_ACCESS_KEY
value: {{ .Values.rustfs.accessKey | quote }}
- name: RUSTFS_SECRET_KEY
value: {{ .Values.rustfs.secretKey | quote }}
{{- include "substrate.rustfs.credentialsEnv" (list "RUSTFS_ACCESS_KEY" "RUSTFS_SECRET_KEY" .) | nindent 8 }}
volumeMounts:
- name: data
mountPath: /data
Expand All @@ -124,10 +121,7 @@ spec:
resources:
{{ toYaml .Values.rustfs.bucketInit.resources | indent 10 }}
env:
- name: AWS_ACCESS_KEY_ID
value: {{ .Values.rustfs.accessKey | quote }}
- name: AWS_SECRET_ACCESS_KEY
value: {{ .Values.rustfs.secretKey | quote }}
{{- include "substrate.rustfs.credentialsEnv" (list "AWS_ACCESS_KEY_ID" "AWS_SECRET_ACCESS_KEY" .) | nindent 8 }}
- name: AWS_REGION
value: us-east-1
- name: AWS_ENDPOINT_URL
Expand Down
123 changes: 123 additions & 0 deletions charts/substrate/tests/rustfs_credentials_test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# Copyright 2026 The Agent Substrate Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

suite: RustFS credentials
templates:
- rustfs.yaml
- ate-api-server-envvars.yaml
- ate-api-server.yaml
tests:
- it: renders the inline credentials by default
template: rustfs.yaml
documentSelector:
path: kind
value: Deployment
asserts:
- contains:
path: spec.template.spec.containers[0].env
content:
name: RUSTFS_ACCESS_KEY
value: rustfsadmin
- contains:
path: spec.template.spec.containers[0].env
content:
name: RUSTFS_SECRET_KEY
value: rustfsadmin

- it: renders the inline object-store plugin credentials by default
template: ate-api-server.yaml
documentSelector:
path: kind
value: Deployment
asserts:
- contains:
path: spec.template.spec.initContainers[?(@.name == "objectstore-plugin")].env
content:
name: AWS_SECRET_ACCESS_KEY
value: rustfsadmin

- it: reads the RustFS server credentials from rustfs.existingSecret
template: rustfs.yaml
documentSelector:
path: kind
value: Deployment
set:
rustfs.existingSecret: rustfs-credentials
asserts:
- contains:
path: spec.template.spec.containers[0].env
content:
name: RUSTFS_ACCESS_KEY
valueFrom:
secretKeyRef:
name: rustfs-credentials
key: AWS_ACCESS_KEY_ID
- contains:
path: spec.template.spec.containers[0].env
content:
name: RUSTFS_SECRET_KEY
valueFrom:
secretKeyRef:
name: rustfs-credentials
key: AWS_SECRET_ACCESS_KEY

- it: reads the bucket-init credentials from rustfs.existingSecret
template: rustfs.yaml
documentSelector:
path: kind
value: Job
set:
rustfs.existingSecret: rustfs-credentials
asserts:
- contains:
path: spec.template.spec.containers[0].env
content:
name: AWS_ACCESS_KEY_ID
valueFrom:
secretKeyRef:
name: rustfs-credentials
key: AWS_ACCESS_KEY_ID
- contains:
path: spec.template.spec.containers[0].env
content:
name: AWS_SECRET_ACCESS_KEY
valueFrom:
secretKeyRef:
name: rustfs-credentials
key: AWS_SECRET_ACCESS_KEY

- it: reads the object-store plugin credentials from rustfs.existingSecret
template: ate-api-server.yaml
documentSelector:
path: kind
value: Deployment
set:
rustfs.existingSecret: rustfs-credentials
asserts:
- contains:
path: spec.template.spec.initContainers[?(@.name == "objectstore-plugin")].env
content:
name: AWS_ACCESS_KEY_ID
valueFrom:
secretKeyRef:
name: rustfs-credentials
key: AWS_ACCESS_KEY_ID
- contains:
path: spec.template.spec.initContainers[?(@.name == "objectstore-plugin")].env
content:
name: AWS_SECRET_ACCESS_KEY
valueFrom:
secretKeyRef:
name: rustfs-credentials
key: AWS_SECRET_ACCESS_KEY
4 changes: 4 additions & 0 deletions charts/substrate/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ rustfs:
bucket: ate-snapshots
accessKey: rustfsadmin
secretKey: rustfsadmin
# Name of an existing Secret in the release namespace with the keys
# AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY. When set, every RustFS
# consumer reads the credentials from it and accessKey/secretKey are ignored.
existingSecret: ""
resources:
requests:
cpu: 50m
Expand Down