AKSGuard is a read-only, CLI-first PowerShell assessment tool for Azure Kubernetes Service. It collects Azure management-plane evidence, correlates Microsoft Defender for Cloud and Azure Advisor security recommendations, validates Defender for Containers configuration, and performs direct Kubernetes data-plane checks when connectivity and read-only permissions are available.
AKSGuard currently evaluates:
- Defender for Containers subscription pricing
- AKS Defender security-monitoring profile configuration
- Agentless discovery for Kubernetes
- Agentless container vulnerability assessment
- Azure Policy add-on configuration
- Microsoft.Security assessments associated with the exact AKS resource
- Azure Advisor security recommendations associated with the exact AKS resource
- Cross-source recommendation correlation and provenance
- Defender-related DaemonSet readiness
- Kubernetes pod and node visibility for sensor coverage checks
- Azure Policy and Gatekeeper deployment readiness
AKSGuard keeps successful evidence collection separate from security posture. A successful query does not mean that the target passed the assessed control.
AKSGuard/
|-- Invoke-AKSGuard.ps1
|-- Modules/
| |-- Test-AKSDefenderForContainers.ps1
| `-- Test-AKSKubernetesPostureManagement.ps1
|-- .gitignore
`-- README.md
One of the following:
- Windows PowerShell 5.1
- PowerShell 7 or later
Verify:
$PSVersionTable.PSVersionInstall Azure CLI on Windows with WinGet:
winget install --exact --id Microsoft.AzureCLI `
--accept-package-agreements `
--accept-source-agreementsClose and reopen PowerShell, then verify:
az versionAKSGuard uses az graph query to collect management-plane recommendations.
az extension add --name resource-graph --upgrade
az extension show `
--name resource-graph `
--query '{Name:name,Version:version}' `
--output tablekubectl is required for direct Kubernetes data-plane validation. It is not required when using -SkipKubernetesDataPlane.
winget install --exact --id Kubernetes.kubectl `
--accept-package-agreements `
--accept-source-agreementsClose and reopen PowerShell, then verify:
kubectl version --clientMicrosoft Entra-integrated AKS clusters commonly require kubelogin for user authentication.
winget install --exact --id Microsoft.Azure.Kubelogin `
--accept-package-agreements `
--accept-source-agreementsClose and reopen PowerShell, then verify:
kubelogin --versionGit is optional when AKSGuard is downloaded as an archive. Install it when cloning or updating the repository in place:
winget install --exact --id Git.Git `
--accept-package-agreements `
--accept-source-agreementsAKSGuard reuses the active Azure CLI identity and does not request Microsoft Graph permissions.
Management-plane collection requires permission to read:
- The target AKS resource
- Microsoft Defender for Cloud pricing configuration
- Microsoft.Security assessments
- Azure Advisor security recommendations
Direct Kubernetes validation requires:
- Network and DNS connectivity to the Kubernetes API endpoint
- A user kubeconfig for the target cluster
- Microsoft Entra authentication where configured
- Read permission for nodes, pods, DaemonSets, and deployments
Private AKS clusters require a working private network route and private DNS resolution from the machine running AKSGuard. Retrieving credentials with az aks get-credentials does not prove that the private Kubernetes API is reachable.
Authenticate and select the target subscription:
az login
az account set --subscription '<subscription-id>'Retrieve normal user credentials for the cluster:
az aks get-credentials `
--subscription '<subscription-id>' `
--resource-group '<resource-group>' `
--name '<cluster-name>'Do not use --admin for a normal read-only assessment.
Validate the current context, connectivity, and effective permissions:
$KubeContext = kubectl config current-context
kubectl --context $KubeContext cluster-info --request-timeout=15s
kubectl --context $KubeContext auth can-i get nodes
kubectl --context $KubeContext auth can-i list pods --all-namespaces
kubectl --context $KubeContext auth can-i list daemonsets --all-namespaces
kubectl --context $KubeContext auth can-i list deployments --all-namespaces.\Invoke-AKSGuard.ps1 `
-SubscriptionId '<subscription-id>' `
-ResourceGroupName '<resource-group>' `
-ClusterName '<cluster-name>'.\Invoke-AKSGuard.ps1 `
-SubscriptionId '<subscription-id>' `
-ResourceGroupName '<resource-group>' `
-ClusterName '<cluster-name>' `
-KubeContext '<kubernetes-context>'Use this mode when direct Kubernetes API connectivity or Kubernetes read access is unavailable:
.\Invoke-AKSGuard.ps1 `
-SubscriptionId '<subscription-id>' `
-ResourceGroupName '<resource-group>' `
-ClusterName '<cluster-name>' `
-SkipKubernetesDataPlaneSkipped data-plane controls are reported as inconclusive. They are not reported as healthy.
Each run creates a timestamped directory under AKSGuard-Results:
AKSGuard-Results/<cluster>-<timestamp>/
|-- Evidence/
|-- Logs/
`-- Report/
|-- index.html
|-- defender-for-containers.html
|-- kubernetes-posture.html
|-- findings.csv
`-- summary.json
The HTML report is offline and does not require a web server or internet-hosted JavaScript.
Raw evidence remains separated by source. The report correlates matching Microsoft.Security and Azure Advisor observations into unique recommendations while preserving source provenance.
AKSGuard uses conservative evidence labels:
- Confirmed healthy
- Confirmed enabled
- Confirmed issue
- Likely issue
- Inconclusive
- Not detected
- Access denied
- Failed
Important distinctions:
Not detecteddoes not mean confirmed absent.- An enabled subscription plan does not prove that runtime sensors are deployed and healthy.
- A successful Azure Resource Graph query does not prove that no recommendations exist.
- A management-plane recommendation is evidence requiring validation, not automatic proof of exploitability.
- Missing network access or permissions are reported as coverage limitations.
AKSGuard is designed for read-only assessment.
The scripts do not:
- Modify Azure resources
- Modify Kubernetes resources
- Request AKS administrative credentials
- Retrieve Kubernetes Secrets
- Retrieve service-account token contents
- Retrieve registry credentials
- Export kubeconfig contents
Review the scripts and use an appropriately scoped audit identity before running them in any environment.
Close and reopen PowerShell after installing Azure CLI, then run:
az versionaz extension add --name resource-graph --upgradeA TLS-inspecting corporate proxy can be trusted by Windows while remaining untrusted by the Python certificate bundle used by Azure CLI. Do not disable TLS verification. Install kubectl and kubelogin through WinGet, or have the infrastructure team provide the authoritative corporate CA bundle for Azure CLI.
Close and reopen PowerShell after installation, then verify:
Get-Command kubectl, kubelogin |
Select-Object Name, SourceErrors such as no such host, DNS name does not exist, or NXDOMAIN indicate a DNS or private-network integration problem before Kubernetes authentication and RBAC are evaluated.
$Context = kubectl config current-context
$Server = kubectl config view `
--context $Context `
--minify `
--output 'jsonpath={.clusters[0].cluster.server}'
$HostName = ([uri]$Server).Host
Resolve-DnsName -Name $HostName -Type A
Test-NetConnection -ComputerName $HostName -Port 443Validate the client VNet, private DNS zone association, custom DNS forwarding, and network route to the private endpoint.
Network connectivity and authentication may be working, but the identity lacks the required Kubernetes read permission. Request only the minimum missing read access.