Skip to content
Merged
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
90 changes: 90 additions & 0 deletions canary-checker/docs/concepts/request-chaining.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
---
title: Request Chaining
sidebar_position: 5
---

Request chaining allows you to create dependencies between checks within the same Canary, enabling complex multi-step verification workflows. A check can depend on other checks and access their output data through templating.

## Use Cases

- **Authentication flows**: Login first, then use the token for subsequent API calls
- **Multi-step API workflows**: Create a resource, then verify its state
- **Data-dependent checks**: Fetch configuration from one endpoint, use it in another

## How It Works

1. Define checks with unique names
2. Use `dependsOn` to specify which checks must complete first
3. Access previous check outputs via `outputs.<checkName>.<field>`

Checks are executed in topological order based on their dependencies, ensuring dependent checks only run after their prerequisites complete successfully.

## Example

```yaml title="http-depends-on.yaml" file=<rootDir>/modules/canary-checker/fixtures/minimal/http_depends_on_pass.yaml
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify that the referenced fixture file exists

echo "=== Checking for http_depends_on_pass.yaml ==="
fd -t f "http_depends_on_pass.yaml" modules/canary-checker/fixtures/

# If found, show the content
if fd -t f "http_depends_on_pass.yaml" modules/canary-checker/fixtures/ | grep -q .; then
  echo "=== File content ==="
  fd -t f "http_depends_on_pass.yaml" modules/canary-checker/fixtures/ -x cat {}
fi

Repository: flanksource/docs

Length of output: 363


🏁 Script executed:

#!/bin/bash
# Search for the fixture file across the repository
echo "=== Searching for http_depends_on_pass.yaml ==="
fd -t f "http_depends_on_pass.yaml"

echo ""
echo "=== Searching for fixtures directory ==="
fd -t d "fixtures"

echo ""
echo "=== Checking repository structure ==="
ls -la | head -20

Repository: flanksource/docs

Length of output: 1367


🏁 Script executed:

#!/bin/bash
# Check git submodules
echo "=== .gitmodules content ==="
cat .gitmodules

echo ""
echo "=== Looking for request-chaining.mdx ==="
fd -t f "request-chaining.mdx"

echo ""
echo "=== Reading request-chaining.mdx ==="
if fd -t f "request-chaining.mdx" | head -1 | xargs -I {} cat -n {}; then
  echo "File found and displayed"
fi

Repository: flanksource/docs

Length of output: 4727


🏁 Script executed:

#!/bin/bash
# Check if modules/canary-checker exists and search for the fixture file
echo "=== Checking modules/canary-checker directory ==="
if [ -d "modules/canary-checker" ]; then
  echo "canary-checker submodule exists"
  ls -la modules/canary-checker/ | head -20
else
  echo "canary-checker submodule not initialized"
fi

echo ""
echo "=== Searching for fixtures/minimal directory ==="
if [ -d "modules/canary-checker" ]; then
  find modules/canary-checker -type d -name "minimal" 2>/dev/null
fi

echo ""
echo "=== Searching for http_depends_on_pass.yaml in submodule ==="
if [ -d "modules/canary-checker" ]; then
  find modules/canary-checker -name "http_depends_on_pass.yaml" 2>/dev/null
fi

echo ""
echo "=== Listing all yaml files in fixtures ==="
if [ -d "modules/canary-checker/fixtures" ]; then
  find modules/canary-checker/fixtures -name "*.yaml" 2>/dev/null | head -20
fi

Repository: flanksource/docs

Length of output: 406


Fixture file reference is broken.

The example on line 24 references http_depends_on_pass.yaml at modules/canary-checker/fixtures/minimal/http_depends_on_pass.yaml, but this file does not exist. The canary-checker submodule is not initialized, and no fixtures directory is present. Either initialize the submodule or verify that the correct fixture file path exists before this documentation can be built.

🤖 Prompt for AI Agents
In @canary-checker/docs/concepts/request-chaining.mdx at line 24, The docs page
request-chaining.mdx references a non-existent fixture
(http_depends_on_pass.yaml) inside the code block titled "http-depends-on.yaml";
fix this by either initializing the canary-checker submodule so
modules/canary-checker/fixtures/minimal/http_depends_on_pass.yaml exists, or
update the code block to point to the correct existing fixture path or embed the
fixture contents inline (modify the ```yaml title="http-depends-on.yaml"
file=... line accordingly) so the documentation builds cleanly.


```

## Fields

<Fields rows={[
{
field: 'dependsOn',
description: 'List of check names that must complete before this check runs',
scheme: '[]string'
}
]}/>

## Accessing Outputs

When a check has dependencies, it can access the outputs from those checks using the `outputs` object:

| Expression | Description |
|------------|-------------|
| `outputs.<checkName>.json` | Parsed JSON response body |
| `outputs.<checkName>.code` | HTTP response code |
| `outputs.<checkName>.headers` | Response headers |
| `outputs.<checkName>.body` | Raw response body |

### Example: Using Previous Check Output

```yaml
apiVersion: canaries.flanksource.com/v1
kind: Canary
metadata:
name: auth-flow
spec:
schedule: "@every 5m"
http:
- name: login
url: https://api.example.com/auth/login
method: POST
body: '{"username": "user", "password": "pass"}'
test:
expr: "code == 200 && json.token != ''"

- name: get-profile
url: https://api.example.com/profile
dependsOn:
- login
headers:
- name: Authorization
# Use the token from the login check
value: "Bearer $(.outputs.login.json.token)"
test:
expr: "code == 200"
```
## Execution Order
Checks are automatically sorted using topological ordering based on their dependencies. If check B depends on check A, then:
1. Check A executes first
2. If Check A succeeds, Check B executes with access to A's outputs
3. If Check A fails, Check B is skipped
## Limitations
- Circular dependencies are not allowed
- `dependsOn` only works within the same Canary resource
- All referenced check names must exist in the same Canary
2 changes: 1 addition & 1 deletion canary-checker/docs/partials/_gotemplate.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ If you need to pass a template through a Helm Chart and prevent Helm from templa
{{`{{ .secret }}`}}
```

Alternatively [change the templating delimiters](#delimiters)
Alternatively change the templating delimiters (see below)

</Details>

Expand Down
310 changes: 211 additions & 99 deletions common/snippets/_resource-selector.mdx

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion common/src/components/CapabilityBadges.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,41 +5,47 @@ const capabilities = {
scraper: {
icon: ConfigDb,
label: 'Scraper',
anchor: 'catalog',
color: '#2563eb',
bg: '#dbeafe',
border: '#93c5fd'
},
healthcheck: {
icon: Health,
label: 'Health Check',
anchor: 'health-checks',
color: '#d97706',
bg: '#fef3c7',
border: '#fcd34d'
},
playbook: {
icon: Playbook,
label: 'Playbook',
anchor: 'playbooks',
color: '#7c3aed',
bg: '#ede9fe',
border: '#c4b5fd'
},
notifications: {
icon: Bell,
label: 'Notifications',
anchor: 'notifications',
color: '#16a34a',
bg: '#dcfce7',
border: '#86efac'
},
actions: {
icon: Webhook,
label: 'Actions',
anchor: 'actions',
color: '#4f46e5',
bg: '#e0e7ff',
border: '#a5b4fc'
},
'relationship': {
icon: ConfigDb,
label: 'Relationship',
anchor: 'relationship',
color: '#d97706',
bg: '#fef3c7',
border: '#fcd34d'
Expand Down Expand Up @@ -80,7 +86,7 @@ export function CapabilityHeading({ type }) {

const Icon = cap.icon;
return (
<h2 className="flex items-center gap-2 mt-8 mb-4 not-prose">
<h2 id={cap.anchor} className="flex items-center gap-2 mt-8 mb-4 not-prose">
<span
className="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-full text-base font-medium"
style={{
Expand Down
10 changes: 5 additions & 5 deletions common/src/components/flanksource/MissionControlPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ const MissionControlPage = () => {

<div className="flex flex-col sm:flex-row gap-4 mb-8">
<Link
to="/docs/mission-control"
to="/docs"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# First, let's verify the file exists and check the actual code at the specified lines
head -1 common/src/components/flanksource/MissionControlPage.jsx | wc -l
wc -l common/src/components/flanksource/MissionControlPage.jsx

Repository: flanksource/docs

Length of output: 122


🏁 Script executed:

# Check the specific lines mentioned in the review
sed -n '148,152p' common/src/components/flanksource/MissionControlPage.jsx
sed -n '376,380p' common/src/components/flanksource/MissionControlPage.jsx
sed -n '386,390p' common/src/components/flanksource/MissionControlPage.jsx
sed -n '396,400p' common/src/components/flanksource/MissionControlPage.jsx
sed -n '707,711p' common/src/components/flanksource/MissionControlPage.jsx

Repository: flanksource/docs

Length of output: 1063


🏁 Script executed:

# Search for documentation structure - look for docs directory and its structure
find . -type d -name "docs" | head -20

Repository: flanksource/docs

Length of output: 111


🏁 Script executed:

# Check what files exist in the docs directory
fd -t f --path "*docs*" "\.(md|mdx)$" | grep -E "(docs/index|docs/installation|docs/guide)" | head -30

Repository: flanksource/docs

Length of output: 293


🏁 Script executed:

# Let's find documentation files more correctly
find . -type f -name "*.md" -o -name "*.mdx" | grep -E "(docs/|installation|playbooks|canary-checker)" | head -30

Repository: flanksource/docs

Length of output: 1496


🏁 Script executed:

# Check the structure of the docs directory
ls -la docs/ 2>/dev/null || echo "docs directory not found at root"

Repository: flanksource/docs

Length of output: 745


🏁 Script executed:

# Look for index files in docs
find docs -maxdepth 2 -name "index.*" -o -name "README.*" 2>/dev/null

Repository: flanksource/docs

Length of output: 42


🏁 Script executed:

# Search for any references to the old mission-control paths
rg "mission-control" --type js --type jsx --type tsx --type ts -n common/src/

Repository: flanksource/docs

Length of output: 87


🏁 Script executed:

# Let's look at the actual structure of docs directory more carefully
find docs -type f -name "*.md" -o -name "*.mdx" 2>/dev/null | head -20

Repository: flanksource/docs

Length of output: 741


🏁 Script executed:

# Check mission-control/docs structure
find mission-control/docs -type f -name "*.md" -o -name "*.mdx" 2>/dev/null | head -30

Repository: flanksource/docs

Length of output: 1642


🏁 Script executed:

# Check if there's a guide directory
find . -maxdepth 3 -type d -name "guide" 2>/dev/null

Repository: flanksource/docs

Length of output: 88


🏁 Script executed:

# Let's check if there's any playbooks documentation
find . -type f -name "*playbook*" 2>/dev/null

Repository: flanksource/docs

Length of output: 1620


🏁 Script executed:

# Check docusaurus config or similar to understand routing
find . -maxdepth 2 -type f \( -name "docusaurus.config.js" -o -name "sidebars.js" -o -name "mkdocs.yml" -o -name "docusaurus.json" \) 2>/dev/null

Repository: flanksource/docs

Length of output: 156


🏁 Script executed:

# Let's check the sidebars configuration to understand routing
cat mission-control/sidebars.js | head -100

Repository: flanksource/docs

Length of output: 2044


🏁 Script executed:

# Check if there's documentation at the exact paths referenced in the code
find . -path "*/docs/installation*" -type f 2>/dev/null
find . -path "*/docs/guide/playbooks*" -type f 2>/dev/null  
find . -path "*/docs/guide/canary-checker*" -type f 2>/dev/null

Repository: flanksource/docs

Length of output: 4198


🏁 Script executed:

# Let's see what canary-checker installation looks like
find canary-checker/docs -name "*installation*" -o -name "*install*" 2>/dev/null

Repository: flanksource/docs

Length of output: 92


🏁 Script executed:

# Check the main docs directory more thoroughly
ls -la docs/ | head -30

Repository: flanksource/docs

Length of output: 745


🏁 Script executed:

# Check if there's a root docusaurus config
cat docusaurus.config.js 2>/dev/null | head -150

Repository: flanksource/docs

Length of output: 42


🏁 Script executed:

# Let's look for any routing/configuration that might map /docs to mission-control
find . -maxdepth 1 -name "*.config.js" -o -name "*.config.json" -o -name "docusaurus.config.js" 2>/dev/null | xargs ls -la 2>/dev/null

Repository: flanksource/docs

Length of output: 2775


🏁 Script executed:

# Check the actual URL structure - look at mission-control docusaurus config
cat mission-control/docusaurus.config.js 2>/dev/null | grep -A 5 -B 5 "routeBasePath\|baseUrl\|url" | head -50

Repository: flanksource/docs

Length of output: 42


Fix broken documentation links — paths do not exist in current repository structure.

The updated paths in the navigation links do not correspond to existing documentation files:

  • /docs/installation → should be /mission-control/installation (docs found at mission-control/docs/installation/)
  • /docs/guide/playbooks → should be /mission-control/guide/playbooks (docs found at mission-control/docs/guide/playbooks/)
  • /docs/guide/canary-checker → does not exist in repository; canary-checker docs are at canary-checker/docs/, not under a /docs/guide/ structure
  • /docs → no landing page found in docs/ root; would require docusaurus routing configuration

Verify the correct documentation URL structure and update the links accordingly, or ensure the deployment/build process configures routing to map these paths to the actual documentation locations.

className="inline-block bg-blue-600 hover:bg-blue-700 text-white font-semibold px-8 py-3 rounded-lg transition-colors duration-200 text-center"
>
Get Started
Expand Down Expand Up @@ -375,7 +375,7 @@ const MissionControlPage = () => {
image="flanksource/self-hosted.svg"
title="Self-Hosted First"
subtitle="SECURITY & CONTROL"
url="/docs/mission-control/installation"
url="/docs/installation"
left={false}
>
Mission Control is self-hosted first, and easy to install using a Helm Chart. Self-Hosted, SaaS or Hybrid Deployment Models with no network or proxy access required and no secrets stored in the SaaS.
Expand All @@ -385,7 +385,7 @@ const MissionControlPage = () => {
image="flanksource/playbooks.svg"
title="Playbooks & Automation"
subtitle="DEVELOPER ENABLEMENT"
url="/docs/mission-control/playbooks"
url="/docs/guide/playbooks"
left={true}
>
Empower developers to be more self-sufficient without the need to become experts in the Cloud and Kubernetes. Run playbooks automatically on failing health checks/alerts, implement security best practices of least privilege and just in time (JIT) access, and use the built-in library of actions.
Expand All @@ -395,7 +395,7 @@ const MissionControlPage = () => {
image="flanksource/status_pages.png"
title="Deep Health Monitoring"
subtitle="PROACTIVE OPERATIONS"
url="/docs/mission-control/canary-checker"
url="/docs/guide/canary-checker"
left={false}
>
Understand the health of complex services at a glance with red, amber, green statuses which leverage active/passive health checks and consolidated alerts from Prometheus, AWS, Dynatrace, and more.
Expand Down Expand Up @@ -706,7 +706,7 @@ const MissionControlPage = () => {

<div className="flex flex-col sm:flex-row gap-4 justify-center">
<Link
to="/docs/mission-control"
to="/docs"
className="inline-block bg-blue-600 hover:bg-blue-700 text-white font-semibold px-8 py-3 rounded-lg transition-colors duration-200"
>
Read the Docs
Expand Down
4 changes: 2 additions & 2 deletions common/src/css/custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ li::marker {
}

li {
font: var(--ifm-font-sans) !important;
font-family: var(--ifm-font-sans) !important;
}

li > svg {
Expand Down Expand Up @@ -573,7 +573,7 @@ pre {

.navbar__link--active {
color: var(--ifm-color-primary-light);
font: bold;
font-weight: bold;
}

a {
Expand Down
2 changes: 1 addition & 1 deletion mission-control-chart
Submodule mission-control-chart updated 38 files
+109 −16 .github/workflows/release.yml
+21 −14 .github/workflows/test.yml
+10 −1 Makefile
+3 −3 agent-chart/Chart.yaml
+5 −4 agent-chart/README.md
+671 −178 agent-chart/values.schema.json
+16 −8 agent-chart/values.yaml
+7 −0 chart/.gitignore
+5 −0 chart/.helmignore
+4 −4 chart/Chart.yaml
+45 −0 chart/Makefile
+17 −10 chart/README.md
+27 −0 chart/ci/basic-auth-values.yaml
+106 −2 chart/crds/mission-control.flanksource.com_connections.yaml
+1 −1 chart/crds/mission-control.flanksource.com_notifications.yaml
+472 −3 chart/crds/mission-control.flanksource.com_playbooks.yaml
+124 −0 chart/crds/mission-control.flanksource.com_teams.yaml
+95 −2 chart/crds/mission-control.flanksource.com_views.yaml
+16 −0 chart/templates/deployment.yaml
+10 −0 chart/templates/rbac.yaml
+11 −0 chart/templates/secrets.yaml
+6 −0 chart/test/Taskfile.yml
+133 −0 chart/test/basic_test.go
+237 −0 chart/test/go.mod
+751 −0 chart/test/go.sum
+140 −0 chart/test/mission-control.go
+87 −0 chart/test/suite_test.go
+87 −0 chart/test/utils_test.go
+147 −22 chart/values.schema.json
+57 −8 chart/values.yaml
+199 −1 crd-chart/templates/canary-checker.flanksource.com_Canary.yaml
+1,386 −114 crd-chart/templates/configs.flanksource.com_scrapeconfigs.yaml
+31 −3 crd-chart/templates/configs.flanksource.com_scrapeplugins.yaml
+106 −2 crd-chart/templates/mission-control.flanksource.com_connections.yaml
+1 −1 crd-chart/templates/mission-control.flanksource.com_notifications.yaml
+472 −3 crd-chart/templates/mission-control.flanksource.com_playbooks.yaml
+124 −0 crd-chart/templates/mission-control.flanksource.com_teams.yaml
+95 −2 crd-chart/templates/mission-control.flanksource.com_views.yaml
2 changes: 1 addition & 1 deletion mission-control/blog/control-plane-testing/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ To follow this tutorial, you need:
<Install/>

:::info Helm Installation
This tutorial uses the CLI for faster feedback, in production we recommend installing `canary-checker` as an operator using the [helm chart](https://canarychecker.io/getting-started) or as part of the full Mission Control [platform](/docs/installation/self-hosted/getting-started).
This tutorial uses the CLI for faster feedback, in production we recommend installing `canary-checker` as an operator using the [helm chart](https://canarychecker.io/getting-started) or as part of the full Mission Control [platform](/docs/installation/self-hosted).
1. Next create a `Canary` CustomResourceDefinition (CRD) using the `kubernetesResource` check type, the layout of the canary is as follows:

```yaml title=basic-canary.yaml file=template.yaml
Expand Down
2 changes: 2 additions & 0 deletions mission-control/blog/rust-ffi/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ For the past few years at [Flanksource](https://flanksource.com/), I've helped b

One Tuesday afternoon, one of our pods started crashing with an OOM (OutOfMemory) error.

{/* truncate */}

> When a container exceeds its memory limit in Kubernetes, the system restarts it with an OutOfMemory message. Memory leaks can trigger a crash loop cycle.

This issue occurred frequently enough to raise concerns, particularly since it only affected one customer's environment.
Expand Down
130 changes: 130 additions & 0 deletions mission-control/docs/guide/config-db/concepts/access-logs.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
---
title: Access Logs
sidebar_position: 6
sidebar_custom_props:
icon: mdi:account-clock
---

Access logs track who accessed configuration items and when. This enables compliance auditing, security monitoring, and access reviews for your infrastructure.

## Overview

When scraping configurations from external systems, you can also capture access logs that record:

- **Who** accessed a resource (external user)
- **What** was accessed (config item)
- **When** the access occurred
- **How** they authenticated (MFA status, properties)

Access logs are stored separately from configuration data and can be queried independently for audit purposes.

## Enabling Access Log Scraping

To scrape access logs, set `full: true` on your scraper configuration:

```yaml
apiVersion: configs.flanksource.com/v1
kind: ScrapeConfig
metadata:
name: database-config
spec:
# highlight-next-line
full: true
# ... scraper configuration
```

When `full` mode is enabled, the scraper expects each configuration item to potentially include an `access_logs` field containing access records.

## Access Log Schema

Each access log entry should include:

<Fields rows={[
{
field: 'config_id',
description: 'ID of the config item that was accessed',
scheme: 'uuid',
required: true
},
{
field: 'external_user_id',
description: 'ID of the external user who accessed the resource',
scheme: 'uuid',
required: true
},
{
field: 'created_at',
description: 'Timestamp when the access occurred',
scheme: 'timestamp'
},
{
field: 'mfa',
description: 'Whether multi-factor authentication was used',
scheme: 'bool'
},
{
field: 'properties',
description: 'Additional access metadata (IP address, session info, etc.)',
scheme: 'map[string]string'
}
]}/>

## Example: Custom Scraper with Access Logs

```json title="config-with-access-logs.json"
{
"id": "db-prod-001",
"config": {
"name": "production-database",
"engine": "postgres",
"version": "15.2"
},
"access_logs": [
{
"config_id": "db-prod-001",
"external_user_id": "user-123",
"created_at": "2025-01-08T10:30:00Z",
"mfa": true,
"properties": {
"ip_address": "192.168.1.100",
"client": "psql"
}
},
{
"config_id": "db-prod-001",
"external_user_id": "user-456",
"created_at": "2025-01-08T11:45:00Z",
"mfa": false
}
]
}
```

## Scrapers with Access Log Support

The following scrapers support access log extraction when `full: true` is enabled:

| Scraper | Use Case |
|---------|----------|
| [SQL](/docs/guide/config-db/scrapers/sql) | Database access logs from audit tables |
| [PostgreSQL](/docs/guide/config-db/scrapers/postgres) | PostgreSQL connection and query logs |
| [SQL Server](/docs/guide/config-db/scrapers/mssql) | SQL Server audit events |
| [Clickhouse](/docs/guide/config-db/scrapers/clickhouse) | Clickhouse query logs and S3 access |
| [HTTP](/docs/guide/config-db/scrapers/http) | API access logs from external systems |
| [File](/docs/guide/config-db/scrapers/file) | Access logs from log files |
| [Exec](/docs/guide/config-db/scrapers/exec) | Custom scripts that output access data |

## External Users and Groups

Access logs reference external users and groups that are also scraped from your systems. These entities enable:

- **User identification**: Track individual user access across configs
- **Group membership**: Understand access patterns by team or role
- **Access reviews**: Audit who has access to what resources

See the [SQL scraper](/docs/guide/config-db/scrapers/sql) for examples of scraping users, groups, and roles alongside access logs.

## Related

- [Config Access Reference](/docs/reference/config-db/config_access) - Access log schema details
- [Retention](/docs/guide/config-db/concepts/retention) - Configure access log retention policies
Loading
Loading