Skip to content
Lukas-KleinPublic

About

A TUI to easily create policy exemptions for customers in their environment

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

azexempt

A Bubble Tea terminal UI that guides you through creating Azure Policy exemptions with the Azure CLI.

Installation

Download the latest binary for your platform from GitHub Releases.

Homebrew

brew install Lukas-Klein/tap/azexempt

macOS / Linux

OS=$(uname -s | tr '[:upper:]' '[:lower:]')   # darwin / linux
ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')

mkdir -p ~/.local/bin
curl -sL "https://github.com/Lukas-Klein/azexempt/releases/latest/download/azexempt_${OS}_${ARCH}.tar.gz" \
  | tar xz -C ~/.local/bin azexempt
chmod +x ~/.local/bin/azexempt

Windows (PowerShell)

$arch = if ($env:PROCESSOR_ARCHITECTURE -eq "AMD64") { "x86_64" } else { "arm64" }
$zip  = "azexempt_windows_${arch}.zip"
$dest = "$env:LOCALAPPDATA\Programs\azexempt"

Invoke-WebRequest `
  "https://github.com/Lukas-Klein/azexempt/releases/latest/download/$zip" `
  -OutFile "$env:TEMP\$zip"
Expand-Archive -Path "$env:TEMP\$zip" -DestinationPath $dest -Force
Remove-Item "$env:TEMP\$zip"

# Add to PATH for the current user (persistent across sessions)
$path = [Environment]::GetEnvironmentVariable('Path', 'User')
if ($path -notlike "*$dest*") {
  [Environment]::SetEnvironmentVariable('Path', "$path;$dest", 'User')
  $env:Path += ";$dest"
}

Restart your terminal, then run azexempt.

Build from source

Requires Go 1.21 or later:

go install github.com/Lukas-Klein/azexempt@latest

Prerequisites

  • The Azure CLI available on your PATH
  • Permission to list subscriptions, read policy definitions and create exemptions

What it does

  1. Authentication: Ensures you are logged into Azure (az login is started automatically when needed).
  2. Subscription Selection: Retrieves all subscriptions you have access to and lets you pick one.
  3. Assignment Selection: Lists all policy assignments in the selected subscription.
  4. Definition Selection: If the assignment is a Policy Set (Initiative), allows you to exempt the entire assignment or specific definitions within it.
  5. Scope Selection: Choose to apply the exemption at the Subscription level or select a specific Resource Group.
  6. Details: Prompts for a tracking ticket number and requester names.
  7. Expiration: Optionally set an expiration date for the exemption.
  8. Creation: Calls az policy exemption create with the collected data and prints the Azure CLI response.

Usage

# Run directly
go run main.go

# Or build and run
go build -o azexempt main.go
./azexempt

Follow the on-screen instructions. Use ↑/↓ to navigate lists, Space to toggle selections, and Enter to confirm. Press q at any time to quit.

Keyboard Shortcuts

Key Action
↑/↓ or k/j Navigate lists
Enter Confirm selection
Space Toggle selection (in multi-select lists)
Backspace Go back to previous step
q Quit the application
Type characters Search/filter subscriptions
Esc Clear search

Configuration

The CLI supports an optional configuration file to customize behavior. The config file is searched in the following locations (first match wins):

  1. ./config.yaml (current directory)
  2. ./config.yml
  3. ~/.azexempt/config.yaml
  4. ~/.azexempt/config.yml
  5. $XDG_CONFIG_HOME/azexempt/config.yaml (or ~/.config/azexempt/config.yaml)

Legacy azure-exemption-cli config directories are also supported for upgrades.

See config.yaml.example for a sample configuration file.

Blocking Policy Definitions

You can configure a list of policy definitions that cannot be exempted. This is useful for enforcing compliance by preventing exemptions on critical security or governance policies.

blocked_policy_definition_ids:
  - /providers/Microsoft.Authorization/policyDefinitions/e56962a6-4747-49cd-b67b-bf8b01975c4c

How it works:

  • The blocked list uses policy definition IDs (not assignment IDs)
  • A single policy definition can be used by multiple policy assignments across your environment
  • When you block a policy definition, all assignments using that definition will be blocked
  • Blocked assignments appear greyed out with a [-] marker and [blocked] label
  • Attempting to select a blocked assignment shows an error message

Example: If you block the "Inherit a tag from the subscription" policy definition, any policy assignment that uses this definition will be blocked - whether it's a standalone assignment or part of a policy set (initiative).

Finding Policy Definition IDs:

You can find policy definition IDs using the Azure CLI:

# List all policy definitions
az policy definition list --query "[].{name:name, displayName:displayName, id:id}" -o table

# Find a specific policy by display name
az policy definition list --query "[?contains(displayName, 'Inherit a tag')].{displayName:displayName, id:id}" -o table

# Get the definition ID from a policy assignment
az policy assignment show --name <assignment-name> --query "policyDefinitionId" -o tsv

Project Structure

The project follows a standard Go project layout:

  • main.go: Application entry point.
  • /azure: Azure CLI interaction logic and types.
  • /tui: Bubble Tea UI model, views, and update logic.
  • /config: Configuration loading and parsing.

About

A TUI to easily create policy exemptions for customers in their environment

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages