Files
claude 528a48b667
Helm Chart Release / release-chart (push) Successful in 9s
Build Session Image / build-push (push) Successful in 2m8s
feat: credentials 認証モードとトークン自動リフレッシュ CronJob を追加 (v2.1.263-b)
トークンが定期的に失効・ローテーションしても再デプロイ不要にする。

- anthropic.authMode: credentials(新既定)
  ~/.claude/.credentials.json 全体(refreshToken 込み)を Secret に格納。
  セッション Pod にはファイルとしてマウントし $HOME/.claude へコピー(書き込み可)、
  セッション内 claude が refreshToken で自己更新
- anthropic.refresher CronJob(credentials 時・既定有効, files/token-refresher.py)
  Secret 内 refreshToken で OAuth トークンを更新し Secret を書き戻す。
  専用 SA + resourceNames 限定 Role で該当 Secret の get/patch のみ。
  tokenUrl/clientId は Claude Code CLI の非公式値(values 上書き可)
- manager.py build_pod: credentials は envFrom を使わずファイルマウント +
  SEED_CREDENTIALS_FILE。apiKey/oauth は従来どおり envFrom
- Secret に helm.sh/resource-policy: keep(credentials 時)で refresher の書込を保持
- fix: values.schema.json の $schema 行を削除(一部の Helm で
  "no schema with key or ref https://json-schema.org/draft-07/schema#" エラー)
- helm lint / template(credentials/apiKey/oauth)検証済み
2026-09-08 15:18:21 +09:00

116 lines
4.0 KiB
YAML

{{- if and (eq .Values.anthropic.authMode "credentials") .Values.anthropic.refresher.enabled }}
{{- $sa := printf "%s-refresher" (include "claude-code.fullname" .) -}}
{{- $sessNs := include "claude-code.sessionsNamespace" . -}}
{{- $secret := include "claude-code.anthropicSecretName" . -}}
{{- $r := .Values.anthropic.refresher -}}
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ $sa }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "claude-code.labels" . | nindent 4 }}
app.kubernetes.io/component: token-refresher
automountServiceAccountToken: true
---
# セッション NS の Claude 認証情報 Secret 1 個に対する get / patch のみ。
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: {{ include "claude-code.fullname" . }}-refresher
namespace: {{ $sessNs }}
labels:
{{- include "claude-code.labels" . | nindent 4 }}
rules:
- apiGroups: [""]
resources: ["secrets"]
resourceNames: [{{ $secret | quote }}]
verbs: ["get", "patch", "update"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: {{ include "claude-code.fullname" . }}-refresher
namespace: {{ $sessNs }}
labels:
{{- include "claude-code.labels" . | nindent 4 }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: {{ include "claude-code.fullname" . }}-refresher
subjects:
- kind: ServiceAccount
name: {{ $sa }}
namespace: {{ .Release.Namespace }}
---
apiVersion: batch/v1
kind: CronJob
metadata:
name: {{ include "claude-code.fullname" . }}-token-refresher
namespace: {{ .Release.Namespace }}
labels:
{{- include "claude-code.labels" . | nindent 4 }}
app.kubernetes.io/component: token-refresher
spec:
schedule: {{ $r.schedule | quote }}
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 1
failedJobsHistoryLimit: 3
startingDeadlineSeconds: 120
jobTemplate:
spec:
activeDeadlineSeconds: 120
backoffLimit: 2
template:
metadata:
labels:
{{- include "claude-code.selectorLabels" . | nindent 12 }}
app.kubernetes.io/component: token-refresher
spec:
restartPolicy: Never
serviceAccountName: {{ $sa }}
automountServiceAccountToken: true
securityContext:
{{- include "claude-code.podSecurityContext" . | nindent 12 }}
containers:
- name: token-refresher
image: "{{ .Values.image.manager.registry }}/{{ .Values.image.manager.repository }}:{{ .Values.image.manager.tag }}"
imagePullPolicy: {{ .Values.image.manager.pullPolicy }}
command: ["python3", "-u", "/app/token-refresher.py"]
env:
- name: PYTHONDONTWRITEBYTECODE
value: "1"
- name: SESSIONS_NAMESPACE
value: {{ $sessNs | quote }}
- name: ANTHROPIC_SECRET
value: {{ $secret | quote }}
- name: CREDENTIALS_KEY
value: {{ .Values.anthropic.existingSecretKeyCredentials | default ".credentials.json" | quote }}
- name: TOKEN_URL
value: {{ $r.tokenUrl | quote }}
- name: CLIENT_ID
value: {{ $r.clientId | quote }}
- name: REFRESH_IF_EXPIRES_IN
value: {{ $r.refreshIfExpiresInSeconds | quote }}
securityContext:
{{- include "claude-code.containerSecurityContext" . | nindent 16 }}
resources:
{{- toYaml $r.resources | nindent 16 }}
volumeMounts:
- name: app
mountPath: /app
readOnly: true
- name: tmp
mountPath: /tmp
volumes:
- name: app
configMap:
name: {{ include "claude-code.fullname" . }}-manager
defaultMode: 0555
- name: tmp
emptyDir:
medium: Memory
sizeLimit: 8Mi
{{- end }}