Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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
2 changes: 1 addition & 1 deletion .github/workflows/golangci-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.22.1'
go-version: '1.25.9'
cache: false

- name: Run Linter
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '^1.22.0'
go-version: '1.25.9'

- name: Import GPG key
id: import_gpg
Expand Down
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,22 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/). This proj

[Unreleased] - yyyy-mm-dd

## [0.3.34] - 2026-04-16

### Fixed

- Fixed `kion_custom_account` validation failing for `start_datecode` when using a computed value (e.g., `formatdate()`) (#143)
- Replaced `GetOk()` with `GetRawConfig()` in `CustomizeDiff` validation, as `GetOk()` returns false for unknown/computed values during the plan phase
- Fixed `kion_azure_policy` example in `examples/resources/kion_azure_policy/resource.tf` which produced a 400 from the Azure Policy Definition API (`Could not find member 'if' on object of type 'PolicyDefinitionProperties'`)
- The example's `policy` JSON now wraps the rule in a `policyRule` object and includes the parameter schema inside the policy JSON, matching what Azure expects in the `properties` body
- The example's top-level Terraform `parameters` attribute now uses the runtime-value format (`{ "paramName": { "value": ... } }`) instead of re-declaring the parameter schema

### Security

- Bumped `google.golang.org/grpc` from v1.61.1 to v1.79.3 to address GHSA-p77j-4mvh-x3m3 / CVE-2026-33186 (thanks @enel1221, #146)
- Bumped Go release line from 1.22 to 1.25 (toolchain pinned to go1.25.9) to address Go stdlib CVE-2025-68121 (thanks @enel1221, #146)
- Pinned `release.yml` and `golangci-lint.yml` workflows to Go 1.25.9 so CI builds use the patched toolchain

## [0.3.33] - 2026-03-26

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This Makefile is an easy way to run common operations.

VERSION=0.3.33
VERSION=0.3.34

TEST?=$$(go list ./... | grep -v 'vendor')
HOSTNAME=github.com
Expand Down
277 changes: 164 additions & 113 deletions docs/resources/azure_policy.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,40 +13,60 @@ description: |-
## Example Usage

```terraform
# NOTE: The `policy` attribute is sent directly as the `properties` body of the
# Azure Policy Definition API. That means the Azure Policy rule (`if` / `then`)
# MUST be nested inside a `policyRule` object, and any parameter schema
# definitions belong inside the policy JSON's own `parameters` block.
#
# The top-level Terraform `parameters` attribute is for RUNTIME parameter
# values that Kion passes when the policy is assigned. Its shape is:
# { "paramName": { "value": <value> } }
# NOT the full parameter schema (type / metadata / defaultValue) — that
# schema lives inside the `policy` JSON only.

# Example 1: Require tag on resources
resource "kion_azure_policy" "require_tags" {
name = "Require Environment Tag"
description = "Requires resources to have an environment tag"

policy = <<EOF
policy = <<-EOF
{
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Resources/subscriptions/resourceGroups"
},
{
"field": "tags['environment']",
"exists": "false"
}
]
"displayName": "Require Environment Tag",
"mode": "All",
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Resources/subscriptions/resourceGroups"
},
{
"field": "tags[parameters('tagName')]",
"exists": "false"
}
]
},
"then": {
"effect": "deny"
}
},
"then": {
"effect": "deny"
"parameters": {
"tagName": {
"type": "String",
"metadata": {
"displayName": "Tag Name",
"description": "Name of the tag to enforce"
},
"defaultValue": "environment"
}
}
}
EOF

parameters = <<EOF
parameters = <<-EOF
{
"tagName": {
"type": "String",
"metadata": {
"displayName": "Tag Name",
"description": "Name of the tag to enforce"
},
"defaultValue": "environment"
"value": "environment"
}
}
EOF
Expand All @@ -59,37 +79,50 @@ resource "kion_azure_policy" "allowed_vms" {
name = "Allowed VM SKUs"
description = "Restricts VM deployments to specific SKUs"

policy = <<EOF
policy = <<-EOF
{
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Compute/virtualMachines"
},
{
"not": {
"field": "Microsoft.Compute/virtualMachines/sku.name",
"in": "[parameters('allowedSkus')]"
"displayName": "Allowed VM SKUs",
"mode": "All",
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Compute/virtualMachines"
},
{
"not": {
"field": "Microsoft.Compute/virtualMachines/sku.name",
"in": "[parameters('allowedSkus')]"
}
}
}
]
]
},
"then": {
"effect": "deny"
}
},
"then": {
"effect": "deny"
"parameters": {
"allowedSkus": {
"type": "Array",
"metadata": {
"displayName": "Allowed VM SKUs",
"description": "List of allowed VM SKUs"
},
"defaultValue": [
"Standard_D2s_v3",
"Standard_D4s_v3",
"Standard_D8s_v3"
]
}
}
}
EOF

parameters = <<EOF
parameters = <<-EOF
{
"allowedSkus": {
"type": "Array",
"metadata": {
"displayName": "Allowed VM SKUs",
"description": "List of allowed VM SKUs"
},
"defaultValue": [
"value": [
"Standard_D2s_v3",
"Standard_D4s_v3",
"Standard_D8s_v3"
Expand All @@ -101,41 +134,45 @@ EOF
owner_user_groups { id = 2 }
}

# Example 3: Enforce Storage Account Encryption
# Example 3: Enforce Storage Account Encryption (no runtime parameters)
resource "kion_azure_policy" "storage_encryption" {
name = "Storage Encryption Requirements"
description = "Enforces encryption settings on storage accounts"

policy = <<EOF
policy = <<-EOF
{
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Storage/storageAccounts"
},
{
"not": {
"allOf": [
{
"field": "Microsoft.Storage/storageAccounts/supportsHttpsTrafficOnly",
"equals": "true"
},
{
"field": "Microsoft.Storage/storageAccounts/minimumTlsVersion",
"equals": "TLS1_2"
},
{
"field": "Microsoft.Storage/storageAccounts/encryption.services.blob.enabled",
"equals": "true"
}
]
"displayName": "Storage Encryption Requirements",
"mode": "All",
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Storage/storageAccounts"
},
{
"not": {
"allOf": [
{
"field": "Microsoft.Storage/storageAccounts/supportsHttpsTrafficOnly",
"equals": "true"
},
{
"field": "Microsoft.Storage/storageAccounts/minimumTlsVersion",
"equals": "TLS1_2"
},
{
"field": "Microsoft.Storage/storageAccounts/encryption.services.blob.enabled",
"equals": "true"
}
]
}
}
}
]
},
"then": {
"effect": "deny"
]
},
"then": {
"effect": "deny"
}
}
}
EOF
Expand All @@ -149,55 +186,69 @@ resource "kion_azure_policy" "nsg_rules" {
name = "NSG Security Requirements"
description = "Enforces security rules on Network Security Groups"

policy = <<EOF
policy = <<-EOF
{
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Network/networkSecurityGroups/securityRules"
},
{
"anyOf": [
{
"allOf": [
{
"field": "Microsoft.Network/networkSecurityGroups/securityRules/access",
"equals": "Allow"
},
{
"field": "Microsoft.Network/networkSecurityGroups/securityRules/direction",
"equals": "Inbound"
},
{
"field": "Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefix",
"equals": "*"
}
]
},
{
"field": "Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRange",
"in": "[parameters('restrictedPorts')]"
}
]
}
]
"displayName": "NSG Security Requirements",
"mode": "All",
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Network/networkSecurityGroups/securityRules"
},
{
"anyOf": [
{
"allOf": [
{
"field": "Microsoft.Network/networkSecurityGroups/securityRules/access",
"equals": "Allow"
},
{
"field": "Microsoft.Network/networkSecurityGroups/securityRules/direction",
"equals": "Inbound"
},
{
"field": "Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefix",
"equals": "*"
}
]
},
{
"field": "Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRange",
"in": "[parameters('restrictedPorts')]"
}
]
}
]
},
"then": {
"effect": "deny"
}
},
"then": {
"effect": "deny"
"parameters": {
"restrictedPorts": {
"type": "Array",
"metadata": {
"displayName": "Restricted Ports",
"description": "Ports that should not be exposed"
},
"defaultValue": [
"22",
"3389",
"161",
"162"
]
}
}
}
EOF

parameters = <<EOF
parameters = <<-EOF
{
"restrictedPorts": {
"type": "Array",
"metadata": {
"displayName": "Restricted Ports",
"description": "Ports that should not be exposed"
},
"defaultValue": [
"value": [
"22",
"3389",
"161",
Expand Down
Loading
Loading