Back to portfolio
Case study · Security operations · May 2026

Security posture as an observable system

Turn monthly cloud security scans into dimensional metrics, freshness signals and a useful triage dashboard.

By Vitor SchiavoUpdated October 2026~7 min read
Solution at a glanceTurn batch scan results into a useful signal.
Security scansCollect results by project
Metric ingestionPush and preserve dimensions
DashboardsShow risk and freshness

Batch visibility includes risk dimensions and scan freshness; it is not real-time threat detection.

Contribution at a glance

My responsibility
Security-result exporter, metric enrichment, dashboarding and scoped secret controls.
Scope
Batch scan visibility plus separately validated scanner and secret-management changes.
Collaboration & boundaries
I built infrastructure visibility and reversible controls; this work is not a claim of real-time threat detection or complete vulnerability coverage.
Outcome
Scan risk and freshness became observable. Related work verified probe reachability and reversible secret-version controls within their recorded scopes.

The problem

Periodic cloud security reports required manual triage. A point-in-time report made it difficult to compare findings across projects and services or see whether the underlying scan had become stale.

My contribution

I connected monthly scan results from 14 cloud projects to a metrics pipeline and a Grafana dashboard. The work included CSV enrichment, a small exporter, a Pushgateway deployment, Prometheus configuration and dashboard views by project, service and risk.

The decisions

The scanner is a batch process, not a long-running service. Pushing results to a gateway lets Prometheus scrape them after the job exits. The exported metrics distinguish finding types, affected resources and the time of the last scan; those represent different questions and should not be collapsed into one count.

I kept the exporter dependency-free so it could run in the existing scanner image, and preserved labels needed for project/service/risk drill-down. Scan timestamp is essential: a dashboard that still displays the previous month's results must not imply a fresh scan.

Results and measurement

The delivery record includes a dry run covering all 14 projects, a successful end-to-end push, confirmation that Prometheus stored the metric and a dashboard populated with live results.

The scan cadence is monthly. Dashboard visibility between runs does not turn this into real-time vulnerability detection. No claim is made here about an independently verified reduction in security incidents or findings.

Make the scan repeatable and useful

In an earlier pipeline modernization, I moved scanner dependencies into a versioned image, parallelized scans and uploads, corrected exit handling and reduced permission-related noise. The recorded end-to-end run fell from about 50 minutes to 15 minutes for that project set. The later dashboard rollout covered 14 projects; the two validation scopes should not be merged into one benchmark.

A separate bucket-policy checker was refactored with bounded workers, typed results and actionable report messages. It recorded 80 unit tests and 93.62% coverage. Correct output still showed genuine policy failures; repairing the checker did not mean every bucket became compliant.

Prove the scanner reached its targets

I repaired a configuration-exposure scanner so an unreachable host could not be mistaken for a clean response. The final recorded run received HTTP responses for 5,681 probes across 299 hosts and 19 path variants, with zero connection failures. Its runtime was about 0.9 minute, compared with about nine minutes previously.

No exposed configuration file was identified in that run. That is a result for the tested paths and responses, not a claim that all services were free of vulnerabilities.

Bring the same discipline to secrets

I piloted External Secrets Operator with Secret Manager across three repositories, including 16 ExternalSecrets and updates to 12 ArgoCD applications. Development, staging and sandbox used workload identity; the legacy production path retained a service-account key exception.

I also changed a destructive secret-update workflow to preserve existing fields. A development validation added one field while retaining the original 183, then removed the test field and restored the original count. A later normalization reversibly disabled 133 older versions across 97 secrets in four projects, retaining the latest enabled version rather than destroying recovery options.

These are scoped controls and validation records. They do not establish that every credential was rotated, every application used a dedicated identity, or that Vitor independently certified the organization.

What I learned

Security reporting becomes an operating capability when its dimensions, freshness and ownership are clear. A total count alone cannot tell a team where to act or whether the source is still current.

Decisions and next steps

A retrospective view of the approach and its limits. The next improvement is a proposal, not a delivered result.

Alternative and rationale

Keeping only static reports is cheap but makes freshness and trends difficult to inspect. Exported metrics add shared visibility and maintenance responsibility.

Trade-off

Stale data can look reassuring; scan reachability and timestamps must remain separate from the number of findings.

What I would improve next

Next improvement: test stale-scan alerts and document triage ownership and exception expiry for each control.