| name | implementing-api-security-posture-management |
| description | Implement API Security Posture Management to continuously discover, classify, and score APIs based on risk while enforcing security policies across the API lifecycle. |
| domain | cybersecurity |
| subdomain | api-security |
| tags | ["api-security","aspm","api-posture-management","api-discovery","risk-scoring","api-governance","continuous-monitoring","api-inventory"] |
| version | 1.0 |
| author | mahipal |
| license | Apache-2.0 |
Implementing API Security Posture Management
Overview
API Security Posture Management (API-SPM) provides continuous visibility into an organization's API attack surface by automatically discovering, classifying, and risk-scoring all APIs including internal, external, partner, and shadow endpoints. Unlike point-in-time testing tools, API-SPM operates continuously to detect configuration drift, policy violations, missing security controls, sensitive data exposure, and compliance gaps. It aggregates findings from DAST, SAST, SCA, and runtime monitoring tools to provide a unified view of API risk posture across the organization.
Prerequisites
- API gateway with traffic logging (Kong, AWS API Gateway, Apigee, Envoy)
- OpenAPI specifications for documented APIs
- SIEM or log aggregation platform (Splunk, Elastic)
- CI/CD pipeline access for shift-left integration
- Cloud provider APIs for infrastructure discovery
- Python 3.8+ for custom posture assessment tooling
Core Components
1. API Discovery and Inventory
"""API Security Posture Management Engine
Continuously discovers, classifies, and risk-scores APIs
to maintain a comprehensive security posture inventory.
"""
import json
import re
import hashlib
from datetime import datetime, timedelta
from typing import Dict, List, Optional, Set
from dataclasses import dataclass, field
from enum import Enum
class APIClassification(Enum):
EXTERNAL = "external"
INTERNAL = "internal"
PARTNER = "partner"
SHADOW = "shadow"
DEPRECATED = "deprecated"
class RiskLevel(Enum):
CRITICAL = 4
HIGH = 3
MEDIUM = 2
LOW = 1
INFO = 0
@dataclass
class SecurityControl:
name: str
present: bool
required: bool
severity: RiskLevel
details: str = ""
@dataclass
class APIEndpoint:
api_id: str
method: str
path: str
service_name: str
classification: APIClassification
owner: [] =
version: [] =
first_discovered: =
last_seen: =
documented: =
security_controls: [SecurityControl] = field(default_factory=)
risk_score: =
sensitive_data_types: [] = field(default_factory=)
compliance_tags: [] = field(default_factory=)
traffic_volume_daily: =
:
SENSITIVE_PATTERNS = {
: re.(),
: re.(),
: re.(),
: re.(),
: re.(),
: re.(),
}
():
.inventory: [, APIEndpoint] = {}
.policy_rules: [] = []
() -> :
raw =
hashlib.sha256(raw.encode()).hexdigest()[:]
() -> APIEndpoint:
api_id = .generate_api_id(method, path, service_name)
now = datetime.now().isoformat()
api_id .inventory:
endpoint = .inventory[api_id]
endpoint.last_seen = now
endpoint
endpoint = APIEndpoint(
api_id=api_id,
method=method,
path=path,
service_name=service_name,
classification=classification,
owner=owner,
first_discovered=now,
last_seen=now,
documented=documented
)
.inventory[api_id] = endpoint
endpoint
() -> [SecurityControl]:
controls = []
has_auth = (h traffic_sample.get(, {})
h [, , ])
controls.append(SecurityControl(
name=,
present=has_auth,
required=,
severity=RiskLevel.CRITICAL,
details= has_auth
))
is_https = traffic_sample.get(, ).lower() ==
controls.append(SecurityControl(
name=,
present=is_https,
required=,
severity=RiskLevel.CRITICAL,
details= is_https
))
has_rate_limit = (h.startswith() h ==
h traffic_sample.get(, {}).keys())
controls.append(SecurityControl(
name=,
present=has_rate_limit,
required=,
severity=RiskLevel.HIGH,
details= has_rate_limit
))
cors_origin = traffic_sample.get(, {}).get(, )
has_strict_cors = cors_origin cors_origin !=
controls.append(SecurityControl(
name=,
present=has_strict_cors,
required=endpoint.classification == APIClassification.EXTERNAL,
severity=RiskLevel.HIGH cors_origin == RiskLevel.MEDIUM,
details= cors_origin
))
sec_headers = traffic_sample.get(, {})
required_headers = {
: ,
: ,
: ,
: ,
}
missing = [h h required_headers h sec_headers]
controls.append(SecurityControl(
name=,
present=(missing) == ,
required=,
severity=RiskLevel.MEDIUM,
details= missing
))
has_validation = traffic_sample.get(, )
controls.append(SecurityControl(
name=,
present=has_validation,
required=,
severity=RiskLevel.HIGH,
details= has_validation
))
endpoint.security_controls = controls
controls
() -> :
score =
max_score =
control endpoint.security_controls:
weight = control.severity.value *
max_score += weight
control.present control.required:
score += weight
classification_weights = {
APIClassification.EXTERNAL: ,
APIClassification.PARTNER: ,
APIClassification.SHADOW: ,
APIClassification.DEPRECATED: ,
APIClassification.INTERNAL: ,
}
multiplier = classification_weights.get(endpoint.classification, )
endpoint.documented:
score +=
score += (endpoint.sensitive_data_types) *
max_score > :
normalized = (, (score / max_score) * * multiplier)
:
normalized =
endpoint.risk_score = (normalized, )
endpoint.risk_score
() -> :
total = (.inventory)
total == :
{: }
risk_distribution = {level.name: level RiskLevel}
classification_counts = {c.value: c APIClassification}
undocumented =
missing_auth =
missing_tls =
endpoint .inventory.values():
.calculate_risk_score(endpoint)
endpoint.risk_score >= :
risk_distribution[] +=
endpoint.risk_score >= :
risk_distribution[] +=
endpoint.risk_score >= :
risk_distribution[] +=
:
risk_distribution[] +=
classification_counts[endpoint.classification.value] +=
endpoint.documented:
undocumented +=
control endpoint.security_controls:
control.name == control.present:
missing_auth +=
control.name == control.present:
missing_tls +=
avg_risk = (e.risk_score e .inventory.values()) / total
{
: datetime.now().isoformat(),
: total,
: (avg_risk, ),
: risk_distribution,
: classification_counts,
: undocumented,
: missing_auth,
: missing_tls,
: (
[{: e.api_id, : e.method, : e.path,
: e.service_name, : e.risk_score,
: e.classification.value}
e .inventory.values()],
key= x: x[],
reverse=
)[:]
}
2. Policy Enforcement
Define and enforce security policies across all APIs:
policies:
- name: require-authentication
description: All external APIs must require authentication
scope:
classification: [external, partner]
rule:
control: authentication
required: true
severity: critical
remediation: "Add OAuth2, API key, or JWT authentication"
- name: enforce-tls
description: All APIs must use HTTPS
scope:
classification: [external, internal, partner]
rule:
control: transport_encryption
required: true
severity: critical
remediation: "Configure TLS certificates and redirect HTTP to HTTPS"
- name: require-rate-limiting
description: External APIs
[]
[]
[, ]
[]
Continuous Monitoring Dashboard Metrics
| Metric | Description | Target |
|---|
| API Discovery Coverage | % of APIs with documentation | > 95% |
| Average Risk Score | Mean risk score across all APIs | < 25 |
| Critical Findings | Number of critical-risk APIs | 0 |
| Shadow API Count | Undocumented/unmanaged APIs | 0 |
| Authentication Coverage | % of APIs with auth controls | 100% |
| TLS Coverage | % of APIs using HTTPS | 100% |
| Policy Compliance | % of APIs meeting all policies | > 90% |
| Mean Time to Remediate | Average days to fix findings | < 7 days |
References