Back to Checks
Prowlerprowler-provider-azure
Key Vault uses private endpoints
keyvault_private_endpoints
Service: keyvaultSeverity: high
OfficialBuilt-inVerified
Categories:internet-exposedtrust-boundaries
Resource Type:microsoft.keyvault/vaults
Azure Key Vault has private endpoint connections to serve secret and key operations over a private IP within your virtual network via Azure Private Link.
Risk
Without private endpoints, the vault relies on a public endpoint, expanding exposure to scanning and misconfigured allowlists. Egress controls are harder to enforce, enabling unauthorized secret retrieval for data exfiltration and potential key misuse, impacting confidentiality and integrity.
Run this check with Prowler
Run in Prowler CloudRun
prowler azure --checks keyvault_private_endpointsRecommendation
Enable Private Endpoints for each Key Vault and disable public network access. Use private DNS so the vault FQDN resolves to the private IP. Apply least privilege with RBAC and managed identities, restrict traffic with NSGs and routing, and monitor access logs as part of defense in depth.
Remediation
CLI
az network private-endpoint create --name <example_resource_name> --resource-group <example_resource_name> --location <LOCATION> --vnet-name <example_resource_name> --subnet <example_resource_name> --private-connection-resource-id <example_resource_id> --group-ids vault --connection-name <example_resource_name>Terraform
# Create a Private Endpoint for an existing Key Vault
resource "azurerm_private_endpoint" "<example_resource_name>" {
name = "<example_resource_name>"
location = "<LOCATION>"
resource_group_name = "<example_resource_name>"
subnet_id = "<example_resource_id>" # Critical: subnet resource ID for the private endpoint NIC
private_service_connection {
name = "<example_resource_name>"
private_connection_resource_id = "<example_resource_id>" # Critical: Key Vault resource ID to connect
subresource_names = ["vault"] # Critical: targets Key Vault subresource to create the connection
}
}NativeIaC
// Create a Private Endpoint for an existing Key Vault
resource pe 'Microsoft.Network/privateEndpoints@2021-08-01' = {
name: '<example_resource_name>'
location: '<LOCATION>'
properties: {
subnet: {
id: '<example_resource_id>' // Critical: subnet resource ID where the private endpoint NIC will be placed
}
privateLinkServiceConnections: [
{
name: '<example_resource_name>'
properties: {
privateLinkServiceId: '<example_resource_id>' // Critical: Key Vault resource ID to connect to
groupIds: [ 'vault' ] // Critical: targets the Key Vault subresource to create the private endpoint connection
}
}
]
}
}Other
1In Azure portal, open your Key Vault
2Go to Networking > Private endpoint connections > + Create
3Basics: select Subscription and Resource group, then Next
4Resource: Service = Microsoft.KeyVault/vaults (your vault is preselected), Subresource = vault, Next
5Configuration: choose Virtual network and Subnet, then Next and Create
6Wait for the connection state to show Approved (auto-approves if you have permission)
Check Code
from prowler.lib.check.models import Check, Check_Report_Azure
from prowler.providers.azure.services.keyvault.keyvault_client import keyvault_client
class keyvault_private_endpoints(Check):
def execute(self) -> Check_Report_Azure:
findings = []
for subscription, key_vaults in keyvault_client.key_vaults.items():
subscription_name = keyvault_client.subscriptions.get(
subscription, subscription
)
for keyvault in key_vaults:
report = Check_Report_Azure(metadata=self.metadata(), resource=keyvault)
report.subscription = subscription
report.status = "FAIL"
report.status_extended = f"Keyvault {keyvault.name} from subscription {subscription_name} ({subscription}) is not using private endpoints."
if (
keyvault.properties
and keyvault.properties.private_endpoint_connections
):
report.status = "PASS"
report.status_extended = f"Keyvault {keyvault.name} from subscription {subscription_name} ({subscription}) is using private endpoints."
findings.append(report)
return findings