id: openbao-seal-status-and-cluster-health-sentinel
namespace: company.security
description: "Continuously audits OpenBao open-source secret management cluster
health, detects sealed server states, validates storage engine responsiveness,
and alerts on secret resolution outages."
inputs:
- id: openbao_host
type: STRING
defaults: "localhost"
description: "Hostname or IP address of the OpenBao server or cluster load balancer."
- id: openbao_port
type: INT
defaults: 8200
description: "HTTP/HTTPS port for the OpenBao API (default: 8200)."
- id: standby_ok
type: BOOL
defaults: true
description: "When true, considers unsealed standby nodes in high-availability
clusters as healthy."
- id: slack_channel
type: STRING
defaults: "#security-alerts"
description: "Target Slack channel for secret engine alerts and incident escalation."
triggers:
- id: periodic_openbao_audit
type: io.kestra.plugin.core.trigger.Schedule
cron: "*/15 * * * *"
disabled: true
tasks:
- id: probe_sys_health
type: io.kestra.plugin.core.http.Request
description: "Queries the OpenBao /v1/sys/health endpoint to evaluate
initialization state, seal status, and cluster role."
uri: "http://{{ inputs.openbao_host }}:{{ inputs.openbao_port
}}/v1/sys/health?standbyok={{ inputs.standby_ok }}"
method: GET
options:
allowFailed: true
timeout:
readIdleTimeout: PT15S
- id: classify_seal_and_health_state
type: io.kestra.plugin.core.flow.Switch
description: "Evaluates HTTP status code and response payload to classify
OpenBao cluster state into OPENBAO_SEALED, UNINITIALIZED,
ENDPOINT_UNREACHABLE, or HEALTHY."
value: >-
{% if outputs.probe_sys_health.code == 503 or
(outputs.probe_sys_health.body is defined and
outputs.probe_sys_health.body.sealed is defined and
outputs.probe_sys_health.body.sealed == true) %}
OPENBAO_SEALED
{% elseif outputs.probe_sys_health.code == 501 or
(outputs.probe_sys_health.body is defined and
outputs.probe_sys_health.body.initialized is defined and
outputs.probe_sys_health.body.initialized == false) %}
UNINITIALIZED
{% elseif outputs.probe_sys_health.code != 200 and
outputs.probe_sys_health.code != 429 %}
ENDPOINT_UNREACHABLE
{% else %}
HEALTHY
{% endif %}
cases:
OPENBAO_SEALED:
- id: alert_openbao_sealed
type: io.kestra.plugin.slack.notifications.SlackIncomingWebhook
description: "Dispatches emergency incident notification when an OpenBao server
node enters a sealed state, preventing secret decryption."
url: "{{ secret('SLACK_WEBHOOK_URL') }}"
payload: |
{
"text": "[CRITICAL] OpenBao Secret Engine is SEALED",
"blocks": [
{
"type": "header",
"text": {
"type": "plain_text",
"text": "[ALERT] OpenBao Secret Engine Sealed"
}
},
{
"type": "section",
"fields": [
{
"type": "mrkdwn",
"text": "*Target Host:*\n`{{ inputs.openbao_host }}:{{ inputs.openbao_port }}`"
},
{
"type": "mrkdwn",
"text": "*HTTP Status:*\n`{{ outputs.probe_sys_health.code }}`"
},
{
"type": "mrkdwn",
"text": "*Seal Status:*\n`SEALED (Keys Encrypted)`"
},
{
"type": "mrkdwn",
"text": "*Severity:*\n`CRITICAL`"
}
]
},
{
"type": "context",
"elements": [
{
"type": "mrkdwn",
"text": "Immediate action required: Execute unseal key ceremony via 'bao operator unseal' or verify auto-unseal KMS credentials."
}
]
}
]
}
- id: fail_on_sealed
type: io.kestra.plugin.core.execution.Fail
description: "Fails the workflow execution to record an SLA violation."
UNINITIALIZED:
- id: alert_uninitialized
type: io.kestra.plugin.slack.notifications.SlackIncomingWebhook
description: "Alerts security teams when an OpenBao node reports uninitialized
state."
url: "{{ secret('SLACK_WEBHOOK_URL') }}"
payload: |
{
"text": "[CRITICAL] OpenBao Cluster Node is Uninitialized",
"blocks": [
{
"type": "header",
"text": {
"type": "plain_text",
"text": "[ALERT] OpenBao Node Uninitialized"
}
},
{
"type": "section",
"fields": [
{
"type": "mrkdwn",
"text": "*Target Host:*\n`{{ inputs.openbao_host }}:{{ inputs.openbao_port }}`"
},
{
"type": "mrkdwn",
"text": "*HTTP Status:*\n`{{ outputs.probe_sys_health.code }}`"
},
{
"type": "mrkdwn",
"text": "*State:*\n`NOT_INITIALIZED`"
},
{
"type": "mrkdwn",
"text": "*Severity:*\n`HIGH`"
}
]
},
{
"type": "context",
"elements": [
{
"type": "mrkdwn",
"text": "Action required: Run 'bao operator init' or check Raft storage cluster joining logs."
}
]
}
]
}
- id: fail_on_uninitialized
type: io.kestra.plugin.core.execution.Fail
description: "Fails the workflow execution to enforce initialization checks."
ENDPOINT_UNREACHABLE:
- id: alert_unreachable
type: io.kestra.plugin.slack.notifications.SlackIncomingWebhook
description: "Dispatches critical notification when OpenBao server endpoint is
offline or returning HTTP server errors."
url: "{{ secret('SLACK_WEBHOOK_URL') }}"
payload: |
{
"text": "[CRITICAL] OpenBao Server Endpoint Unreachable",
"blocks": [
{
"type": "header",
"text": {
"type": "plain_text",
"text": "[ALERT] OpenBao Endpoint Offline"
}
},
{
"type": "section",
"fields": [
{
"type": "mrkdwn",
"text": "*Target Host:*\n`{{ inputs.openbao_host }}:{{ inputs.openbao_port }}`"
},
{
"type": "mrkdwn",
"text": "*HTTP Status:*\n`{{ outputs.probe_sys_health.code }}`"
},
{
"type": "mrkdwn",
"text": "*Execution ID:*\n`{{ execution.id }}`"
},
{
"type": "mrkdwn",
"text": "*Timestamp:*\n`{{ now() }}`"
}
]
},
{
"type": "context",
"elements": [
{
"type": "mrkdwn",
"text": "Immediate action required: Check OpenBao systemd service, container runtime, and ingress proxy."
}
]
}
]
}
- id: fail_on_unreachable
type: io.kestra.plugin.core.execution.Fail
description: "Fails the execution on endpoint unreachable."
HEALTHY:
- id: log_cluster_healthy
type: io.kestra.plugin.core.log.Log
description: "Records nominal cluster state when OpenBao is unsealed,
initialized, and responsive."
message: "[OK] OpenBao cluster at {{ inputs.openbao_host }}:{{
inputs.openbao_port }} is unsealed and operational. Version: {{
outputs.probe_sys_health.body.version ?? 'verified' }}. Server time:
{{ outputs.probe_sys_health.body.server_time_utc ?? now() }}."
- id: audit_sentinel_run
type: io.kestra.plugin.core.log.Log
description: "Final audit log summarizing execution metrics and verified secret
engine state."
message: "[AUDIT] OpenBao sentinel completed execution {{ execution.id }}.
Target host: {{ inputs.openbao_host }}:{{ inputs.openbao_port }}. Sealed:
{{ outputs.probe_sys_health.body.sealed ?? 'unknown' }}. Version: {{
outputs.probe_sys_health.body.version ?? 'N/A' }}."