Secure token migration: gateway-token, hooks-token, telegram-bot-token as OCP secrets + startup script patch for hooks.token

This commit is contained in:
2026-04-12 11:26:36 +00:00
parent b8ff432e35
commit 846316cc45

View File

@@ -17,93 +17,6 @@ spec:
spec: spec:
serviceAccountName: openclaw serviceAccountName: openclaw
initContainers:
- name: secret-injector
image: default-route-openshift-image-registry.apps.lab.apilab.us/openclaw/openclaw:latest
command: ["/bin/sh", "-c"]
args:
- |
set -e
JS=/home/node/.openclaw/openclaw.json
GATEWAY_TOKEN=$(cat /run/secrets/gateway-token/token)
HOOKS_TOKEN=$(cat /run/secrets/hooks-token/token)
TELEGRAM_BOT_TOKEN=$(cat /run/secrets/telegram-bot-token/token)
# Bootstrap a minimal config if none exists yet
if [ ! -f $JS ]; then
node /app/openclaw.mjs onboard --non-interactive --accept-risk \
--gateway-port 18789 --gateway-bind lan \
--skip-daemon --skip-channels --skip-skills --skip-health --skip-ui
fi
# Patch openclaw.json with tokens sourced from OCP secrets
node -e "
const fs = require('fs');
const gatewayToken = '$GATEWAY_TOKEN';
const hooksToken = '$HOOKS_TOKEN';
const telegramBotToken = '$TELEGRAM_BOT_TOKEN';
const d = JSON.parse(fs.readFileSync('$JS', 'utf8'));
// Gateway token (env var)
d.gateway = d.gateway || {};
d.gateway.token = gatewayToken;
// Hooks token + mappings (idempotent)
if (!d.hooks || !d.hooks.token) {
d.hooks = {
enabled: true,
path: '/hooks',
token: hooksToken,
allowRequestSessionKey: false,
mappings: [
{
id: 'ocp-alerts',
match: { path: '/ocp-alerts' },
action: 'agent',
name: 'OCP Alerts',
sessionKey: 'hook:ocp-alerts',
messageTemplate: 'You are an OCP cluster alert analyst for a Single Node OpenShift lab. An alert has fired. Compose a brief narrative notification and reply with ONLY the notification text — no preamble, no markdown, no tool calls.\n\nAlert details:\n- Name: {{groupLabels.alertname}}\n- Namespace: {{commonLabels.namespace}}\n- Severity: {{commonLabels.severity}}\n- Status: {{status}}\n- Summary: {{commonAnnotations.summary}}\n\nRules:\n1. If alertname contains \'Watchdog\': reply NO_REPLY and nothing else.\n2. Classify and write one of:\n - ACTIONABLE firing: \"🔴 [pod/component] is [what\'s wrong] in [namespace]. [One sentence likely cause]. Would you like me to take action?\"\n - RESOLVED: \"✅ Good news — [what] in [namespace] has resolved.\"\n - INFORMATIONAL: \" Heads up — [brief narrative].\"\n3. Plain text only. No bullet points. No markdown. Under 3 sentences.',
deliver: true,
allowUnsafeExternalContent: true,
channel: 'telegram',
to: '6479169830',
model: 'haiku',
timeoutSeconds: 60
}
]
};
}
// Telegram bot token
d.channels = d.channels || {};
d.channels.telegram = d.channels.telegram || {};
d.channels.telegram.botToken = telegramBotToken;
d.channels.telegram.enabled = true;
fs.writeFileSync('$JS', JSON.stringify(d, null, 2));
"
echo "secret-injector: openclaw.json patched from OCP secrets"
volumeMounts:
- name: home
mountPath: /home/node
env:
- name: TZ
value: "Australia/Sydney"
resources:
requests:
cpu: "10m"
memory: "32Mi"
limits:
cpu: "100m"
memory: "64Mi"
securityContext:
runAsUser: 1000950000
runAsNonRoot: true
allowPrivilegeEscalation: false
readOnlyRootFilesystem: false
containers: containers:
- name: openclaw - name: openclaw
image: default-route-openshift-image-registry.apps.lab.apilab.us/openclaw/openclaw:latest image: default-route-openshift-image-registry.apps.lab.apilab.us/openclaw/openclaw:latest
@@ -117,6 +30,37 @@ spec:
--gateway-port 18789 --gateway-bind lan \ --gateway-port 18789 --gateway-bind lan \
--skip-daemon --skip-channels --skip-skills --skip-health --skip-ui --skip-daemon --skip-channels --skip-skills --skip-health --skip-ui
fi fi
# Patch hooks.token from OCP secret if not already set (idempotent)
if ! grep -q '"token":' ~/.openclaw/openclaw.json 2>/dev/null; then
node -e "
const fs = require('fs');
const d = JSON.parse(fs.readFileSync(process.env.HOME + '/.openclaw/openclaw.json', 'utf8'));
d.hooks = d.hooks || {};
d.hooks.token = process.env.HOOKS_TOKEN;
d.hooks.enabled = true;
d.hooks.path = '/hooks';
d.hooks.allowRequestSessionKey = false;
d.hooks.mappings = d.hooks.mappings || [];
if (!d.hooks.mappings.find(m => m.id === 'ocp-alerts')) {
d.hooks.mappings.push({
id: 'ocp-alerts',
match: { path: '/ocp-alerts' },
action: 'agent',
name: 'OCP Alerts',
sessionKey: 'hook:ocp-alerts',
messageTemplate: 'You are an OCP cluster alert analyst for a Single Node OpenShift lab. An alert has fired. Compose a brief narrative notification and reply with ONLY the notification text \u2014 no preamble, no markdown, no tool calls.\n\nAlert details:\n- Name: {{groupLabels.alertname}}\n- Namespace: {{commonLabels.namespace}}\n- Severity: {{commonLabels.severity}}\n- Status: {{status}}\n- Summary: {{commonAnnotations.summary}}\n\nRules:\n1. If alertname contains \'Watchdog\': reply NO_REPLY and nothing else.\n2. Classify and write one of:\n - ACTIONABLE firing: \"\ud83d\udfe1 [pod/component] is [what\'s wrong] in [namespace]. [One sentence likely cause]. Would you like me to take action?\"\n - RESOLVED: \"\u2705 Good news \u2014 [what] in [namespace] has resolved.\"\n - INFORMATIONAL: \"\u2139\ufe0f Heads up \u2014 [brief narrative].\"\n3. Plain text only. No bullet points. No markdown. Under 3 sentences.',
deliver: true,
allowUnsafeExternalContent: true,
channel: 'telegram',
to: '6479169830',
model: 'haiku',
timeoutSeconds: 60
});
}
fs.writeFileSync(process.env.HOME + '/.openclaw/openclaw.json', JSON.stringify(d, null, 2));
console.log('hooks.token patched from HOOKS_TOKEN env var');
"
fi
exec node /app/openclaw.mjs gateway --port 18789 --bind lan exec node /app/openclaw.mjs gateway --port 18789 --bind lan
ports: ports:
- name: gateway - name: gateway
@@ -155,6 +99,16 @@ spec:
secretKeyRef: secretKeyRef:
name: minimax name: minimax
key: token key: token
- name: HOOKS_TOKEN
valueFrom:
secretKeyRef:
name: hooks-token
key: token
- name: TELEGRAM_BOT_TOKEN
valueFrom:
secretKeyRef:
name: telegram-bot-token
key: token
volumeMounts: volumeMounts:
- name: home - name: home
mountPath: /home/node mountPath: /home/node