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
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
apiVersion: runwhen.com/v1
kind: GenerationRules
spec:
platform: mongodb_atlas
generationRules:
- resourceTypes:
- mongodb_atlas_project
matchRules:
- type: pattern
pattern: ".+"
properties: [name]
mode: substring
slxs:
- baseName: atlas-operations-health
levelOfDetail: basic
qualifiers: ["organization", "project"]
baseTemplateName: mongodb-atlas-operations-health
outputItems:
- type: slx
- type: sli
- type: runbook
templateName: mongodb-atlas-operations-health-taskset.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
apiVersion: runwhen.com/v1
kind: ServiceLevelIndicator
metadata:
name: {{slx_name}}
labels:
{% include "common-labels.yaml" %}
annotations:
{% include "common-annotations.yaml" %}
spec:
displayUnitsLong: Health Score
displayUnitsShort: score
locations:
- {{default_location}}
description: Computes a 0–1 MongoDB Atlas operations posture score (alerts, backup coverage, network baseline) for the discovered project.
codeBundle:
{% if repo_url %}
repoUrl: {{repo_url}}
{% else %}
repoUrl: https://github.com/runwhen-contrib/rw-cli-codecollection.git
{% endif %}
{% if ref %}
ref: {{ref}}
{% else %}
ref: main
{% endif %}
pathToRobot: codebundles/mongodb-atlas-operations-health/sli.robot
intervalStrategy: intermezzo
intervalSeconds: 300
configProvided:
- name: ATLAS_PROJECT_ID
value: "{{ match_resource.resource.project_id | default(match_resource.id) }}"
- name: ATLAS_ORG_ID
value: "{{ match_resource.resource.organization_id | default('') }}"
- name: CLUSTER_FILTER
value: "{{ custom.atlas_cluster_filter | default('') }}"
secretsProvided:
{% if wb_version %}
{% include "mongodb-atlas-auth.yaml" ignore missing %}
{% else %}
- name: atlas_api_key_credentials
workspaceKey: {{ custom.atlas_api_key_credentials | default("atlas_api_key_credentials") }}
{% endif %}
alertConfig:
tasks:
persona: eager-edgar
sessionTTL: 10m
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
apiVersion: runwhen.com/v1
kind: ServiceLevelX
metadata:
name: {{slx_name}}
labels:
{% include "common-labels.yaml" %}
annotations:
{% include "common-annotations.yaml" %}
spec:
imageURL: https://cdn.simpleicons.org/mongodb/47A248
alias: MongoDB Atlas Operations Health — {{ match_resource.name | default(match_resource.qualified_name) }}
asMeasuredBy: Aggregate SLI from Atlas alerts, dedicated-cluster backup flags, and project IP access posture APIs.
configProvided:
- name: SLX_PLACEHOLDER
value: SLX_PLACEHOLDER
owners:
- {{workspace.owner_email}}
statement: Atlas project alerting, backup continuity, and network allowlists should stay within organizational guardrails.
additionalContext:
qualified_name: "{{ match_resource.qualified_name }}"
tags:
- name: cloud
value: mongodb_atlas
- name: service
value: atlas
- name: scope
value: project
- name: access
value: read-only
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
apiVersion: runwhen.com/v1
kind: Runbook
metadata:
name: {{slx_name}}
labels:
{% include "common-labels.yaml" %}
annotations:
{% include "common-annotations.yaml" %}
spec:
location: {{default_location}}
description: Evaluates MongoDB Atlas project operations posture (alerts, backups, IP access) via the Admin API.
codeBundle:
{% if repo_url %}
repoUrl: {{repo_url}}
{% else %}
repoUrl: https://github.com/runwhen-contrib/rw-cli-codecollection.git
{% endif %}
{% if ref %}
ref: {{ref}}
{% else %}
ref: main
{% endif %}
pathToRobot: codebundles/mongodb-atlas-operations-health/runbook.robot
configProvided:
- name: ATLAS_PROJECT_ID
value: "{{ match_resource.resource.project_id | default(match_resource.id) }}"
- name: ATLAS_ORG_ID
value: "{{ match_resource.resource.organization_id | default('') }}"
- name: CLUSTER_FILTER
value: "{{ custom.atlas_cluster_filter | default('') }}"
- name: ALERT_LOOKBACK_HOURS
value: "{{ custom.atlas_alert_lookback_hours | default('24') }}"
secretsProvided:
{% if wb_version %}
{% include "mongodb-atlas-auth.yaml" ignore missing %}
{% else %}
- name: atlas_api_key_credentials
workspaceKey: {{ custom.atlas_api_key_credentials | default("atlas_api_key_credentials") }}
{% endif %}
27 changes: 27 additions & 0 deletions codebundles/mongodb-atlas-operations-health/.test/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Testing mongodb-atlas-operations-health

This bundle talks to the live MongoDB Atlas Admin API. Automated tests in CI are limited to shell syntax checks so we never embed real Atlas API keys.

## Prerequisites

- MongoDB Atlas project with a Project Read Only (or higher) API key
- `ATLAS_PROJECT_ID` and credentials matching the workspace secret format documented in the bundle `README.md`

## Local validation

From `.test/`:

```bash
task validate-scripts
```

## Manual integration

Export `ATLAS_PROJECT_ID` and either `ATLAS_PUBLIC_API_KEY` / `ATLAS_PRIVATE_API_KEY` or `ATLAS_API_KEY_CREDENTIALS` JSON, then run individual scripts from the bundle root, for example:

```bash
cd ..
./check-atlas-open-alerts.sh
```

Expect `atlas_*_issues.json` files and human-readable stdout suitable for Robot `Add Pre To Report`.
12 changes: 12 additions & 0 deletions codebundles/mongodb-atlas-operations-health/.test/Taskfile.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
version: "3"

tasks:
default:
desc: "Syntax-check Atlas helper and task scripts (no live API calls)"
cmds:
- task: validate-scripts

validate-scripts:
desc: "Run bash -n on bundle shell scripts"
cmds:
- bash .test/validate-bundle-scripts.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env bash
set -euo pipefail
# Static validation only — MongoDB Atlas test projects require customer-provided org/project credentials.
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
failed=0
while IFS= read -r -d '' f; do
if ! bash -n "$f"; then
echo "bash -n failed: $f" >&2
failed=1
fi
done < <(find "$ROOT" -maxdepth 1 -name '*.sh' -print0)
exit "$failed"
46 changes: 46 additions & 0 deletions codebundles/mongodb-atlas-operations-health/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# MongoDB Atlas Operations Health

This CodeBundle performs read-only checks against the MongoDB Atlas Admin API for a single project: live alert posture, whether dedicated clusters report cloud backup enabled, and whether the project IP access list shows risky openness or inconsistencies with public cluster DNS names.

## Overview

- **Alert posture**: Surfaces OPEN and TRACKING alerts (and CLOSED items whose timestamps fall inside `ALERT_LOOKBACK_HOURS` when date parsing works), scoped by optional `CLUSTER_FILTER`, with a short blast-radius summary.
- **Backup coverage**: For `REPLICA_SET`, `SHARDED`, and `GEOSHARDED` clusters, validates `backupEnabled` / `providerBackupEnabled` and records when the cloud backup schedule endpoint is unavailable on lower tiers (downgraded context instead of hard failure).
- **Network access**: Flags `0.0.0.0/0`, very broad `0.0.0.0/N` prefixes, and an empty allowlist when in-scope clusters still publish `connectionStrings.standardSrv` hostnames.
- **SLI**: Averages three binary dimensions into a 0–1 operations health score for periodic monitoring.

API reference: [Atlas Admin API v2](https://www.mongodb.com/docs/api/doc/atlas-admin-api-v2/).

## Configuration

### Required variables

- `ATLAS_PROJECT_ID`: 24-hex MongoDB Atlas project (group) id used in `/groups/{groupId}/...` paths.

### Optional variables

- `ATLAS_ORG_ID`: Organization id for workspace context (reserved for future org-level checks).
- `CLUSTER_FILTER`: Comma-separated Atlas cluster names to limit alert, backup, and network correlation (default: empty, meaning all clusters in the project).
- `ALERT_LOOKBACK_HOURS`: Hours of history for treating recently CLOSED alerts as relevant in the deep-dive runbook task (default: `24`).

### Secrets

- `atlas_api_key_credentials`: Programmatic API key material — preferred shape is JSON `{"ATLAS_PUBLIC_API_KEY":"...","ATLAS_PRIVATE_API_KEY":"..."}` (aliases `publicKey` / `privateKey` are also accepted). Plain multi-line `KEY=value` text works as well. The RunWhen platform injects this for digest authentication to `https://cloud.mongodb.com/api/atlas/v2`.

## Tasks overview

### Check MongoDB Atlas Open Alerts for Project

Paginates `GET /groups/{groupId}/alerts`, applies the cluster scope filter, evaluates OPEN/TRACKING and recent CLOSED signals, and raises a consolidated issue when anything relevant is found.

### Verify MongoDB Atlas Backup Configuration for Project

Lists clusters, checks backup flags on dedicated layouts, and probes `GET .../backup/schedule` for extra context when the tier supports it.

### Review MongoDB Atlas Network Access for Project

Reads `GET /groups/{groupId}/accessList`, warns on open CIDR patterns, and combines cluster connection string hints to detect empty allowlists paired with public SRV endpoints.

### SLI (sli.robot)

Runs lightweight variants of the three checks and publishes sub-metrics `atlas_alerts_clear`, `atlas_backup_ok`, and `atlas_network_ok` plus the aggregate health score.
81 changes: 81 additions & 0 deletions codebundles/mongodb-atlas-operations-health/atlas-helpers.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#!/usr/bin/env bash
# Shared Atlas Admin API helpers (digest auth, credential parsing).
# shellcheck shell=bash

ATLAS_API_ROOT="${ATLAS_API_ROOT:-https://cloud.mongodb.com/api/atlas/v2}"
ATLAS_ACCEPT="${ATLAS_ACCEPT:-application/vnd.atlas.2024-08-05+json}"

atlas_resolve_credentials() {
if [[ -n "${ATLAS_PUBLIC_API_KEY:-}" && -n "${ATLAS_PRIVATE_API_KEY:-}" ]]; then
return 0
fi

local raw=""
raw="${ATLAS_API_KEY_CREDENTIALS:-}"
if [[ -z "$raw" ]]; then
raw="${atlas_api_key_credentials:-}"
fi
if [[ -z "$raw" ]]; then
echo "atlas-helpers: set ATLAS_PUBLIC_API_KEY and ATLAS_PRIVATE_API_KEY, or provide atlas_api_key_credentials / ATLAS_API_KEY_CREDENTIALS (JSON or KEY=value lines)." >&2
return 1
fi

if echo "$raw" | jq -e . >/dev/null 2>&1; then
ATLAS_PUBLIC_API_KEY="$(echo "$raw" | jq -r '.ATLAS_PUBLIC_API_KEY // .publicKey // .username // empty')"
ATLAS_PRIVATE_API_KEY="$(echo "$raw" | jq -r '.ATLAS_PRIVATE_API_KEY // .privateKey // .password // empty')"
else
while IFS= read -r line || [[ -n "$line" ]]; do
[[ "$line" =~ ^[[:space:]]*# ]] && continue
[[ -z "${line// /}" ]] && continue
if [[ "$line" =~ ^ATLAS_PUBLIC_API_KEY[[:space:]]*=[[:space:]]*(.*)$ ]]; then
ATLAS_PUBLIC_API_KEY="${BASH_REMATCH[1]}"
ATLAS_PUBLIC_API_KEY="${ATLAS_PUBLIC_API_KEY%\"}"
ATLAS_PUBLIC_API_KEY="${ATLAS_PUBLIC_API_KEY#\"}"
fi
if [[ "$line" =~ ^ATLAS_PRIVATE_API_KEY[[:space:]]*=[[:space:]]*(.*)$ ]]; then
ATLAS_PRIVATE_API_KEY="${BASH_REMATCH[1]}"
ATLAS_PRIVATE_API_KEY="${ATLAS_PRIVATE_API_KEY%\"}"
ATLAS_PRIVATE_API_KEY="${ATLAS_PRIVATE_API_KEY#\"}"
fi
done <<< "$raw"
fi

if [[ -z "${ATLAS_PUBLIC_API_KEY:-}" || -z "${ATLAS_PRIVATE_API_KEY:-}" ]]; then
echo "atlas-helpers: could not parse Atlas API keys from credentials payload." >&2
return 1
fi
return 0
}

atlas_get() {
local path_qs="$1"
local outf code
outf="$(mktemp)"
code="$(
curl -sS -o "$outf" -w "%{http_code}" \
--digest \
-u "${ATLAS_PUBLIC_API_KEY}:${ATLAS_PRIVATE_API_KEY}" \
-H "Accept: ${ATLAS_ACCEPT}" \
"${ATLAS_API_ROOT%/}/${path_qs#\/}" 2>/dev/null || echo "000"
)"
ATLAS_LAST_HTTP_CODE="$code"
ATLAS_LAST_BODY="$(cat "$outf" 2>/dev/null || true)"
rm -f "$outf"
}

cluster_matches_filter() {
local cname="$1"
local filt="${CLUSTER_FILTER:-}"
filt="${filt//[[:space:]]/}"
if [[ -z "$filt" ]]; then
return 0
fi
local IFS=','; local tok
for tok in $filt; do
[[ -z "$tok" ]] && continue
if [[ "$cname" == "$tok" ]]; then
return 0
fi
done
return 1
}
Loading