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
8 changes: 5 additions & 3 deletions .github/workflows/dependency-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ jobs:
- uses: actions/dependency-review-action@2031cfc080254a8a887f58cffee85186f0e49e48 # v4
with:
fail-on-severity: high
# The wheel omits license metadata, but Microsoft's upstream Azure
# SDK repository licenses this package under MIT:
# These wheels omit license metadata, but Microsoft's upstream Azure
# SDK repository licenses both packages under MIT:
# https://github.com/Azure/azure-sdk-for-python/blob/main/LICENSE
allow-dependencies-licenses: pkg:pypi/azure-mgmt-containerservice@41.3.0
allow-dependencies-licenses: >-
pkg:pypi/azure-mgmt-containerservice@41.3.0,
pkg:pypi/azure-mgmt-recoveryservices@4.1.0
comment-summary-in-pr: always
3 changes: 3 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,9 @@ Use the existing wrapper methods in `scanner/azure_client.py` rather than constr
| `azure_client.get_subscription_role_assignments()` | Subscription RBAC assignments, or `None` on API failure |
| `azure_client.get_service_principals()` | List of role assignments for service principals |
| `azure_client.get_conditional_access_policies()` | List of Conditional Access policy dicts from Microsoft Graph |
| `azure_client.get_function_app_security_posture()` | Cached, secret-free Function App posture dicts, or `None` on API failure |
| `azure_client.get_private_endpoint_posture()` | Public-access and approved Private Link state for supported PaaS resources, or `None` on API failure |
| `azure_client.get_recovery_vault_security_posture()` | Cached Recovery Services vault security settings, or `None` on API failure |

Most list methods return an empty list on failure. Methods that fetch one resource or one policy return `None` when the result cannot be determined.

Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@ Findings map to NIST FIPS 203 (ML-KEM), FIPS 204 (ML-DSA), and FIPS 205 (SLH-DSA

| Feature | Description |
|---|---|
| **Misconfiguration Scanner** | Runs 51 Azure security rules across storage, network, identity, database, compute, Key Vault, AKS, and post-quantum cryptography |
| **Misconfiguration Scanner** | Runs 72 Azure security rules across storage, network, identity, database, compute, Key Vault, AKS, and post-quantum cryptography |
| **Compliance Mapper** | Maps findings to CIS Benchmarks, NIST CSF, ISO 27001, and SOC 2 framework JSON files |
| **Scan History API** | Stores scans and findings in PostgreSQL and exposes findings, score, scan history, compliance posture, drift, and resource inventory over REST |
| **Remediation Playbooks** | Every rule ships with a matching Azure CLI remediation script (51 playbooks) |
| **Remediation Playbooks** | Every rule ships with a matching Azure CLI remediation script (72 playbooks) |
| **Security Dashboard** | Full React dashboard deployed on Vercel - live monitoring, findings, compliance, drift, prioritization, and AI-layer views |
| **Project Website** | Documentation and reference site at [openshield-website.vercel.app](https://openshield-website.vercel.app) - blog, rules gallery, docs, roadmap, releases, and interactive playground |
| **Sentinel Integration** | Normalises findings and pushes them into Microsoft Sentinel via a Log Analytics custom table and KQL analytics rules |
Expand Down Expand Up @@ -93,11 +93,11 @@ Project policies and assurance evidence:
flowchart TD
A["React Dashboard\nVercel · Live"]
B["Flask REST API\nJWT · CORS · Blueprints"]
C["Scanner Engine\n51 Python rules"]
C["Scanner Engine\n72 Python rules"]
D["Azure Subscription\nScanned via Azure SDK + Graph"]
E["Compliance Framework JSON\nCIS · NIST · ISO 27001 · SOC 2"]
F["PostgreSQL Database\nFindings · Scans"]
G["Azure CLI Playbooks\n51 remediation scripts"]
G["Azure CLI Playbooks\n72 remediation scripts"]
H["sentinel/ingest.py\nNormalise + HMAC upload"]
I["Microsoft Sentinel\nOpenShieldFindings_CL · KQL rules"]

Expand Down
17 changes: 16 additions & 1 deletion compliance/frameworks/cis_azure_benchmark.json
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,21 @@
"control_id": "TBD-IDN-015",
"control_name": "Managed Identity least privilege (not mapped in CIS Azure Foundations 2.0.0)",
"description": "Microsoft recommends least-privilege roles and scopes for managed identities. This check has no direct control in the repository's CIS Azure Foundations 2.0.0 benchmark."
}
},
"AZ-FUNC-001": {"control_id":"TBD-FUNC-001","control_name":"Function HTTPS baseline placeholder","description":"Numbered placeholder pending maintainer approval of a direct CIS mapping."},
"AZ-FUNC-002": {"control_id":"TBD-FUNC-002","control_name":"Function TLS baseline placeholder","description":"Numbered placeholder pending maintainer approval of a direct CIS mapping."},
"AZ-FUNC-003": {"control_id":"TBD-FUNC-003","control_name":"Function publishing baseline placeholder","description":"Numbered placeholder pending maintainer approval of a direct CIS mapping."},
"AZ-FUNC-004": {"control_id":"TBD-FUNC-004","control_name":"Function debugging baseline placeholder","description":"Numbered placeholder pending maintainer approval of a direct CIS mapping."},
"AZ-FUNC-005": {"control_id":"TBD-FUNC-005","control_name":"Function identity baseline placeholder","description":"Numbered placeholder pending maintainer approval of a direct CIS mapping."},
"AZ-PE-001": {"control_id":"TBD-PE-001","control_name":"Storage Private Link baseline placeholder","description":"Numbered placeholder pending maintainer approval of a direct CIS mapping."},
"AZ-PE-002": {"control_id":"TBD-PE-002","control_name":"SQL Private Link baseline placeholder","description":"Numbered placeholder pending maintainer approval of a direct CIS mapping."},
"AZ-PE-003": {"control_id":"TBD-PE-003","control_name":"PostgreSQL private networking placeholder","description":"Numbered placeholder pending maintainer approval of a direct CIS mapping."},
"AZ-PE-004": {"control_id":"TBD-PE-004","control_name":"App Service Private Link baseline placeholder","description":"Numbered placeholder pending maintainer approval of a direct CIS mapping."},
"AZ-PE-005": {"control_id":"TBD-PE-005","control_name":"Recovery Services Private Link placeholder","description":"Numbered placeholder pending maintainer approval of a direct CIS mapping."},
"AZ-PE-006": {"control_id":"TBD-PE-006","control_name":"Private endpoint approval placeholder","description":"Numbered placeholder pending maintainer approval of a direct CIS mapping."},
"AZ-BAK-001": {"control_id":"TBD-BAK-001","control_name":"Backup soft delete placeholder","description":"Numbered placeholder pending maintainer approval of a direct CIS mapping."},
"AZ-BAK-002": {"control_id":"TBD-BAK-002","control_name":"Backup immutability placeholder","description":"Numbered placeholder pending maintainer approval of a direct CIS mapping."},
"AZ-BAK-004": {"control_id":"TBD-BAK-004","control_name":"Backup MUA placeholder","description":"Numbered placeholder pending maintainer approval of a direct CIS mapping."},
"AZ-BAK-006": {"control_id":"TBD-BAK-006","control_name":"Backup monitoring placeholder","description":"Numbered placeholder pending maintainer approval of a direct CIS mapping."}
}
}
93 changes: 69 additions & 24 deletions compliance/frameworks/iso27001.json
Original file line number Diff line number Diff line change
Expand Up @@ -258,35 +258,80 @@
"control_name": "Management of technical vulnerabilities",
"description": "Automatic AKS node OS upgrades help deploy tested security patches within a managed maintenance process."
},
"AZ-IDN-010": {
"control_id": "A.9.2.1",
"control_name": "User registration and de-registration",
"description": "App Registration ownership supports accountable identity lifecycle administration."
"AZ-BAK-001": {
"control_id": "A.12.3.1",
"control_name": "Information backup",
"description": "The Recovery Services vault lacks the approved soft-delete recovery window, risking permanent loss of backup data before it can be restored."
},
"AZ-IDN-011": {
"control_id": "A.14.1.2",
"control_name": "Securing application services on public networks",
"description": "Secure redirect URIs protect identity protocol responses traversing public networks."
"AZ-BAK-002": {
"control_id": "A.12.3.1",
"control_name": "Information backup",
"description": "Vault immutability is disabled, allowing destructive changes to protected recovery points and undermining the integrity of backup copies."
},
"AZ-IDN-012": {
"control_id": "A.9.4.2",
"control_name": "Secure log-on procedures",
"description": "Modern authorization code flow with PKCE provides stronger token handling than implicit grant."
"AZ-BAK-004": {
"control_id": "A.9.2.3",
"control_name": "Management of privileged access rights",
"description": "The vault does not enable Resource Guard multiuser authorization, allowing a single compromised or malicious identity to disable backup protections unilaterally."
},
"AZ-IDN-013": {
"control_id": "A.9.4.3",
"control_name": "Password management system",
"description": "Avoiding client secrets reduces password-style application credential exposure."
"AZ-BAK-006": {
"control_id": "A.12.4.1",
"control_name": "Event logging",
"description": "The Recovery Services vault does not enable built-in monitoring for backup job failures, so a failed or tampered backup could go undetected."
},
"AZ-IDN-014": {
"control_id": "A.12.1.2",
"control_name": "Change management",
"description": "Property lock prevents unauthorized changes to sensitive service-principal instance configuration."
"AZ-FUNC-001": {
"control_id": "A.13.2.1",
"control_name": "Information transfer policies and procedures",
"description": "The Function App accepts unencrypted HTTP traffic, so requests and responses can cross the network without encryption in transit."
},
"AZ-IDN-015": {
"control_id": "A.9.2.3",
"control_name": "Management of privileged access rights",
"description": "Subscription Owner and Contributor assignments to managed identities require least-privilege reduction."
"AZ-FUNC-002": {
"control_id": "A.13.2.1",
"control_name": "Information transfer policies and procedures",
"description": "The Function App permits TLS older than 1.2, weakening the encryption protecting traffic in transit."
},
"AZ-FUNC-003": {
"control_id": "A.13.1.1",
"control_name": "Network controls",
"description": "The Function App exposes an FTP or FTPS deployment channel, widening the network attack surface beyond the primary HTTPS endpoint."
},
"AZ-FUNC-004": {
"control_id": "A.13.1.1",
"control_name": "Network controls",
"description": "Remote debugging expands the Function App management attack surface by opening an additional network-reachable control channel."
},
"AZ-FUNC-005": {
"control_id": "A.13.1.1",
"control_name": "Network controls",
"description": "The Function App has no Azure managed identity for secretless resource access, pushing workloads toward long-lived credentials that cross network and service boundaries."
},
"AZ-PE-001": {
"control_id": "A.13.1.1",
"control_name": "Network controls",
"description": "A Storage Account remains publicly reachable; an approved private endpoint alone does not disable its public endpoint, leaving the network boundary uncontrolled."
},
"AZ-PE-002": {
"control_id": "A.13.1.1",
"control_name": "Network controls",
"description": "An Azure SQL logical server remains publicly reachable, regardless of whether a private endpoint also exists, leaving the network boundary uncontrolled."
},
"AZ-PE-003": {
"control_id": "A.13.1.1",
"control_name": "Network controls",
"description": "A PostgreSQL Flexible Server remains publicly reachable instead of using private networking only, leaving the network boundary uncontrolled."
},
"AZ-PE-004": {
"control_id": "A.13.1.1",
"control_name": "Network controls",
"description": "An App Service workload remains publicly reachable without a default-deny access policy, leaving the network boundary uncontrolled."
},
"AZ-PE-005": {
"control_id": "A.13.1.1",
"control_name": "Network controls",
"description": "A Recovery Services vault permits public access, even if a private endpoint also exists, leaving the network boundary uncontrolled."
},
"AZ-PE-006": {
"control_id": "A.13.1.1",
"control_name": "Network controls",
"description": "A private endpoint connection is pending, rejected, or disconnected and does not provide an active private path, leaving traffic to traverse the public network boundary instead."
}
}
}
87 changes: 66 additions & 21 deletions compliance/frameworks/nist_csf.json
Original file line number Diff line number Diff line change
Expand Up @@ -258,35 +258,80 @@
"control_name": "A vulnerability management plan is developed and implemented",
"description": "Managed node OS upgrade channels apply tested security updates to reduce exposure to known operating-system vulnerabilities."
},
"AZ-IDN-010": {
"AZ-BAK-001": {
"control_id": "PR.IP-4",
"control_name": "Backups of information are conducted, maintained, and tested",
"description": "The Recovery Services vault lacks the approved soft-delete recovery window, risking permanent loss of backup data before it can be restored."
},
"AZ-BAK-002": {
"control_id": "PR.IP-4",
"control_name": "Backups of information are conducted, maintained, and tested",
"description": "Vault immutability is disabled, allowing destructive changes to protected recovery points and undermining the integrity of backup copies."
},
"AZ-BAK-004": {
"control_id": "PR.AC-4",
"control_name": "Access permissions and authorizations are managed",
"description": "Assigned owners establish accountability for reviewing and maintaining application access."
"description": "The vault does not enable Resource Guard multiuser authorization, allowing a single compromised or malicious identity to disable backup protections unilaterally."
},
"AZ-IDN-011": {
"AZ-BAK-006": {
"control_id": "DE.CM-1",
"control_name": "The network is monitored to detect potential cybersecurity events",
"description": "The Recovery Services vault does not enable built-in monitoring for backup job failures, so a failed or tampered backup could go undetected."
},
"AZ-FUNC-001": {
"control_id": "PR.DS-2",
"control_name": "Data in transit is protected",
"description": "HTTPS redirect URIs protect authorization responses from interception and modification in transit."
"control_name": "Data-in-transit is protected",
"description": "The Function App accepts unencrypted HTTP traffic, so requests and responses can cross the network without encryption in transit."
},
"AZ-IDN-012": {
"control_id": "PR.AC-3",
"control_name": "Remote access is managed",
"description": "Disabling implicit grant reduces exposure of front-channel tokens used for remote application access."
"AZ-FUNC-002": {
"control_id": "PR.DS-2",
"control_name": "Data-in-transit is protected",
"description": "The Function App permits TLS older than 1.2, weakening the encryption protecting traffic in transit."
},
"AZ-IDN-013": {
"control_id": "PR.AC-1",
"control_name": "Identities and credentials are managed",
"description": "Replacing client secrets with managed credentials reduces credential leakage and rotation risk."
"AZ-FUNC-003": {
"control_id": "PR.AC-5",
"control_name": "Network integrity is protected",
"description": "The Function App exposes an FTP or FTPS deployment channel, widening the network attack surface beyond the primary HTTPS endpoint."
},
"AZ-IDN-014": {
"control_id": "PR.IP-1",
"control_name": "A baseline configuration is created and maintained",
"description": "Application-instance property lock preserves the approved sensitive-property baseline across tenants."
"AZ-FUNC-004": {
"control_id": "PR.AC-5",
"control_name": "Network integrity is protected",
"description": "Remote debugging expands the Function App management attack surface by opening an additional network-reachable control channel."
},
"AZ-IDN-015": {
"control_id": "PR.AC-4",
"control_name": "Access permissions and authorizations are managed",
"description": "Managed identities should receive only the minimum role and scope required by their workloads."
"AZ-FUNC-005": {
"control_id": "PR.AC-5",
"control_name": "Network integrity is protected",
"description": "The Function App has no Azure managed identity for secretless resource access, pushing workloads toward long-lived credentials that cross network and service boundaries."
},
"AZ-PE-001": {
"control_id": "PR.AC-5",
"control_name": "Network integrity is protected",
"description": "A Storage Account remains publicly reachable; an approved private endpoint alone does not disable its public endpoint, leaving the network boundary uncontrolled."
},
"AZ-PE-002": {
"control_id": "PR.AC-5",
"control_name": "Network integrity is protected",
"description": "An Azure SQL logical server remains publicly reachable, regardless of whether a private endpoint also exists, leaving the network boundary uncontrolled."
},
"AZ-PE-003": {
"control_id": "PR.AC-5",
"control_name": "Network integrity is protected",
"description": "A PostgreSQL Flexible Server remains publicly reachable instead of using private networking only, leaving the network boundary uncontrolled."
},
"AZ-PE-004": {
"control_id": "PR.AC-5",
"control_name": "Network integrity is protected",
"description": "An App Service workload remains publicly reachable without a default-deny access policy, leaving the network boundary uncontrolled."
},
"AZ-PE-005": {
"control_id": "PR.AC-5",
"control_name": "Network integrity is protected",
"description": "A Recovery Services vault permits public access, even if a private endpoint also exists, leaving the network boundary uncontrolled."
},
"AZ-PE-006": {
"control_id": "PR.AC-5",
"control_name": "Network integrity is protected",
"description": "A private endpoint connection is pending, rejected, or disconnected and does not provide an active private path, leaving traffic to traverse the public network boundary instead."
}
}
}
Loading
Loading