Chart Reference: azure-base
Detailed reference for every file in the charts/azure-base/ chart. Each template is shown alongside the real Crossplane CRD it renders.
Chart Structure
charts/azure-base/
├── Chart.yaml
├── values.yaml # Defaults (dev-friendly)
├── values-dev.yaml
├── values-staging.yaml
├── values-prod.yaml
└── templates/
├── _helpers.tpl # Name generation, labels, tags
├── resource-group.yaml # azure.upbound.io/v1beta1 ResourceGroup
├── vnet.yaml # network.azure.upbound.io/v1beta1 VirtualNetwork
├── subnets.yaml # network.azure.upbound.io/v1beta1 Subnet (loops)
├── nsg.yaml # network.azure.upbound.io/v1beta1 SecurityGroup + Association
├── storage.yaml # storage.azure.upbound.io/v1beta1 Account + Container
└── keyvault.yaml # keyvault.azure.upbound.io/v1beta1 Vault_helpers.tpl — Naming and Labeling
Name generation
Every resource name follows {project}-{environment}-{suffix}:
{{- define "azure-base.name" -}}
{{- printf "%s-%s-%s" .ctx.Values.project .ctx.Values.environment .suffix -}}
{{- end -}}Usage in templates:
metadata:
name: {{ include "azure-base.name" (dict "ctx" . "suffix" "vnet") }}
# Renders: myapp-dev-vnetThis naming scheme is critical because Crossplane *Ref fields reference resources by metadata.name. As long as the naming helper is consistent, all cross-resource references resolve correctly.
Labels
Applied to every Kubernetes object (visible in kubectl get but not in Azure):
app.kubernetes.io/managed-by: helm
app.kubernetes.io/part-of: myapp
crossplane.io/environment: dev
crossplane.io/owner: platform-teamTags
Applied to every Azure resource (visible in Azure portal and cost management):
project: myapp
environment: dev
owner: platform-team
managed-by: crossplaneresource-group.yaml
CRD: azure.upbound.io/v1beta1 ResourceGroupProvider: provider-family-azureAzure docs: Resource Group is a container for Azure resources.
apiVersion: azure.upbound.io/v1beta1
kind: ResourceGroup
metadata:
name: myapp-dev-rg
spec:
forProvider:
location: eastus
tags:
project: myapp
environment: dev
providerConfigRef:
name: defaultConfigurable values:
| Value | Path | Default |
|---|---|---|
| Location | location | eastus |
| Enable/disable | resourceGroup.enabled | true |
Every other resource in this chart references the Resource Group via resourceGroupNameRef.
vnet.yaml
CRD: network.azure.upbound.io/v1beta1 VirtualNetworkProvider: provider-azure-network
apiVersion: network.azure.upbound.io/v1beta1
kind: VirtualNetwork
metadata:
name: myapp-dev-vnet
spec:
forProvider:
location: eastus
resourceGroupNameRef:
name: myapp-dev-rg # Crossplane resolves this at runtime
addressSpace:
- "10.0.0.0/16"
providerConfigRef:
name: defaultConfigurable values:
| Value | Path | Default |
|---|---|---|
| Address space | network.vnet.addressSpace | 10.0.0.0/16 |
| Enable/disable | network.enabled | true |
Key CRD fields from the provider:
| Field | Type | Required | Description |
|---|---|---|---|
location | string | Yes | Azure region |
resourceGroupName | string | Yes | RG name (or use *Ref) |
addressSpace | string[] | Yes | CIDR blocks for the VNet |
bgpCommunity | string | No | BGP community value |
ddosProtectionPlan | object | No | DDoS protection configuration |
encryption | object | No | Network encryption settings |
subnets.yaml
CRD: network.azure.upbound.io/v1beta1 SubnetProvider: provider-azure-network
This template loops over network.subnets in values, generating one Subnet MR per entry.
{{- range $subnetName, $subnet := .Values.network.subnets }}
apiVersion: network.azure.upbound.io/v1beta1
kind: Subnet
metadata:
name: myapp-dev-subnet-{{ $subnetName }} # e.g., myapp-dev-subnet-app
spec:
forProvider:
resourceGroupNameRef:
name: myapp-dev-rg
virtualNetworkNameRef:
name: myapp-dev-vnet
addressPrefixes:
- "10.0.1.0/24"
serviceEndpoints:
- "Microsoft.Storage"
- "Microsoft.KeyVault"
{{- end }}Configurable values:
| Value | Path | Default |
|---|---|---|
| App subnet CIDR | network.subnets.app.addressPrefix | 10.0.1.0/24 |
| Data subnet CIDR | network.subnets.data.addressPrefix | 10.0.2.0/24 |
| Service endpoints | network.subnets.<name>.serviceEndpoints | [Microsoft.Storage] |
Key CRD fields:
| Field | Type | Required | Description |
|---|---|---|---|
addressPrefixes | string[] | Yes | CIDR blocks for the subnet |
virtualNetworkName | string | Yes | Parent VNet (or use *Ref) |
serviceEndpoints | string[] | No | Azure service endpoints to enable |
delegation | object[] | No | Service delegations (e.g., for App Service) |
privateEndpointNetworkPolicies | string | No | Enabled or Disabled |
nsg.yaml
CRD: network.azure.upbound.io/v1beta1 SecurityGroup + SubnetNetworkSecurityGroupAssociationProvider: provider-azure-network
This template renders two resources:
- SecurityGroup — the NSG with inline security rules
- SubnetNetworkSecurityGroupAssociation — binds the NSG to the app subnet
# 1. The NSG
apiVersion: network.azure.upbound.io/v1beta1
kind: SecurityGroup
metadata:
name: myapp-dev-nsg
spec:
forProvider:
location: eastus
resourceGroupNameRef:
name: myapp-dev-rg
securityRule:
- name: AllowHTTPS
priority: 100
direction: Inbound
access: Allow
protocol: "Tcp"
sourcePortRange: "*"
destinationPortRange: "443"
sourceAddressPrefix: "*"
destinationAddressPrefix: "10.0.1.0/24"
---
# 2. The association
apiVersion: network.azure.upbound.io/v1beta1
kind: SubnetNetworkSecurityGroupAssociation
metadata:
name: myapp-dev-nsg-assoc-app
spec:
forProvider:
subnetIdRef:
name: myapp-dev-subnet-app
networkSecurityGroupIdRef:
name: myapp-dev-nsgConfigurable values:
| Value | Path | Default |
|---|---|---|
| Security rules | nsg.rules[] | AllowHTTPS + AllowHTTP + DenyAll |
| Enable/disable | nsg.enabled | true |
Security rule structure:
nsg:
rules:
- name: AllowHTTPS # Rule name
priority: 100 # 100-4096, lower = higher priority
direction: Inbound # Inbound or Outbound
access: Allow # Allow or Deny
protocol: Tcp # Tcp, Udp, Icmp, or *
sourcePortRange: "*"
destinationPortRange: "443"
sourceAddressPrefix: "*"
destinationAddressPrefix: "10.0.1.0/24"storage.yaml
CRD: storage.azure.upbound.io/v1beta1 Account + ContainerProvider: provider-azure-storage
Renders a Storage Account and loops over storage.containers[] for blob containers.
# Storage Account
apiVersion: storage.azure.upbound.io/v1beta1
kind: Account
metadata:
name: myapp-dev-sa
spec:
forProvider:
location: eastus
resourceGroupNameRef:
name: myapp-dev-rg
accountTier: Standard
accountReplicationType: LRS
accountKind: StorageV2
httpsTrafficOnlyEnabled: true
minTlsVersion: TLS1_2
networkRules:
- defaultAction: Deny
bypass:
- AzureServices# One Container per entry in storage.containers[]
apiVersion: storage.azure.upbound.io/v1beta1
kind: Container
metadata:
name: myapp-dev-container-data
spec:
forProvider:
containerAccessType: private
storageAccountNameRef:
name: myapp-dev-saConfigurable values:
| Value | Path | Default |
|---|---|---|
| Account tier | storage.accountTier | Standard |
| Replication | storage.accountReplicationType | LRS |
| Kind | storage.accountKind | StorageV2 |
| HTTPS only | storage.httpsOnly | true |
| Min TLS | storage.minTlsVersion | TLS1_2 |
| Containers | storage.containers[] | [{name: data}, {name: logs}] |
Key Account CRD fields:
| Field | Type | Description |
|---|---|---|
accountTier | string | Standard or Premium |
accountReplicationType | string | LRS, ZRS, GRS, RAGRS, GZRS, RAGZRS |
accountKind | string | StorageV2, BlobStorage, BlockBlobStorage, FileStorage |
networkRules | object[] | Firewall rules, VNet rules, bypass settings |
blobProperties | object | Versioning, soft delete, change feed |
keyvault.yaml
CRD: keyvault.azure.upbound.io/v1beta1 VaultProvider: provider-azure-keyvault
apiVersion: keyvault.azure.upbound.io/v1beta1
kind: Vault
metadata:
name: myapp-dev-kv
spec:
forProvider:
location: eastus
resourceGroupNameRef:
name: myapp-dev-rg
tenantId: "your-tenant-id"
skuName: standard
enableRbacAuthorization: true
purgeProtectionEnabled: false
softDeleteRetentionDays: 7Configurable values:
| Value | Path | Default |
|---|---|---|
| SKU | keyvault.skuName | standard |
| RBAC auth | keyvault.enableRbacAuthorization | true |
| Purge protection | keyvault.purgeProtectionEnabled | false |
| Soft delete days | keyvault.softDeleteRetentionDays | 7 |
| Public access | keyvault.publicNetworkAccessEnabled | true |
| Tenant ID | keyvault.tenantId | Must be overridden |
Key Vault CRD fields:
| Field | Type | Description |
|---|---|---|
tenantId | string | Azure AD tenant ID (required) |
skuName | string | standard or premium (HSM-backed keys require premium) |
enableRbacAuthorization | bool | Use Azure RBAC instead of access policies |
purgeProtectionEnabled | bool | Prevents permanent deletion (cannot be disabled once on) |
softDeleteRetentionDays | int | 7-90 days |
networkAcls | object[] | Firewall rules and VNet integration |
Dependency Map
Arrows show *Ref dependencies. Crossplane resolves these at runtime — resources that depend on others will retry until the dependency becomes READY: True.