Table of Contents

PowerShell module Devdeer.Caf

PowerShell Gallery Version

A PowerShell module that lets you handle Azure in a convenient but still secure way.

Introduction

This collection of functions for PowerShell is a result of our (DEVDEERs) interpretation on how one should access Azure on a daily base. So in order to understand what these functions are doing is important to understand some core principles first.

Principle 1: Do not use the Azure Portal

This first principle is heavily underrated. A lot of influential material out there (including Microsoft Learn) is showcasing certain activities using the Portal. This is a bad idea for several reasons.

  • The portal tends to "lie" to a user because it uses caching a lot. You often find yourself in a situation where you constantly refresh the page until you see the desired result (or not because something really failed).
  • You need to access the portal using you personal account. This means that you pretty often need to use MFA and login confirmation which distracts you a lot usually.
  • The steps you take in the portal are not repeatable. You need to guide other through it or make notes to remember it yourself.
  • The portal hides a lot from you. It is in our opinion more a shiny window which sometimes looks really cool but if you want to dig deeper you get lost pretty fast.

This list is not even complete but we think that it already shows why using the portal on a daily base is not a good idea.

Principle 2: Do not use permanent privileged user accounts

This principle is easy to understand and hard to do. The idea is that you don't privilege your user account to a level where you are able to perform actions which might change resources or obtain sensitive data by accident.

Principle 3: Use Privileged Identity Management (PIM)

In direct contradiction to Principle 2 you often need to interact with Azure using your user account. Whenever this is necessary you should have PIM activated in Azure so that you

  1. Get the elevated rights only temporary.
  2. Need approval from a co-worker for that.
  3. Have this privilege escalation being logged.

Over the years we've encountered many setups at customer tenants where this was done by using 2 accounts for administrative users. This is a really bad idea brought over from on-premise environments where it is a good idea. Being forced to select just a different password set in a browser or posh-session does not help at all. Those sessions are still being cached by default and there is nothing like a sudo-like process start which makes the admin-user-concept so useful in operating systems.

Principle 4: Use service principals for operations

Whenever you are deploying something in Azure, changing the settings of a resource (which you should do as a deployment) or export some backups and stuff like this you should not perform those actions with your personal account but using a service principal instead. In fact, most of these operations should not even started by you imperatively but should be executed by a process, service, API, pipeline or whatever.

The problem

As good and understandable as these principles might be. We experienced that the majority of admins and devs are not adhering to them because its hard to do so or the company forces them to do but then people either run away or hate their interaction with Azure.

Principle 4 and 2 combined for instance force you to somehow know which service principle to use and where to retrieve the password from. Then, in order to just download a file from a storage account, you find yourself doing 2 minutes of sp-login to finally execute this one command. Also this leaves your Azure context of your shell logged in as this service principal which either is restricting you in other sessions or - even worst - let you now have privileged rights.

Even using PIM is not straightforward. Usually you login to the portal and perform your request and then you need to re-login in your posh session and in the browser-sessions in other windows for this action to take effect. When you wait for approvals your usually find yourself refreshing your browser until you can see your new role.

The solution

Well, first of all: there is no solution for this! What we offer with Devdeer.Caf is convenient, efficient but still secure ways to interact with Azure. Those things only can happen if you are willing to follow a lot of conventions (tenant design, naming, ...). Luckily those conventions are defined by a high authority. Microsoft released the Cloud Adoption Framework aka CAF a while ago. Part of it are recommendations for

  • Structuring your tenant.
  • Setting up networking.
  • Naming your resources.
  • Using infrastructure as code (IaC).

and many more.

What we try to achieve with Devdeer.Caf is to provide tooling based on these ideas making it easier to follow them.

Disclaimer

We need to interpret a lot out of the statements in the CAF. Very rarely Microsoft says something like "You should do it exactly like this..." or "Don't do this at all!". Thats why the functions provided by us are opinionated. We do not guarantee the functionality or provide support for any of them! Because of the nature of PowerShell you can download and inspect our code at any time.

Why PowerShell?

You can run PowerShell on any platform (Linux and MacOS can use PowerShell Core) whereas bash scripts are not easily ran on a Windows machine. That's why!

Functions

Function Description Needs PIM
Approve-CafPimRole Approves a PIM Role assignment request for a single user.
Clear-CafAllSqlFirewallRules Removes all custom firewall rules currently added to the SQL server given with regard to resource group locks.
Clear-CafPolicyAssets Deletes all policies defined in the BICEP files under the current path.
Deploy-CafJumphost Deploys a Jumphost virtual machine to an Azure subscription.
Deploy-CafPolicyAssets Deploys all BICEP files under the current path considering them to define resources from the provider 'Microsoft.Authorization/*'
Get-CafContext Retrieves the combined .azcontext-based settings that are valid in the current directory.
Get-CafExpiringKeyVaultSecrets Retrieves all Key Vault secrets that are expiring within a specified number of days.
Initialize-CafAdoServiceConnections Initializes Azure DevOps service connections for all projects defined in the .azcontext file.
Initialize-CafAdoToAcrServiceConnection Initializes an Azure DevOps service connection to an Azure Container Registry.
Initialize-CafAdoToARMServiceConnection Creates a service connection from Azure DevOps to Azure Resource Manager.
Initialize-CafBicep Initializes the DEVDEER Bicep modules for a project.
Initialize-CafBudget Creates a budget resource for a single Azure subscription.
Initialize-CafBudgets Creates budget resources for all Azure subscriptions in the tenant.
Initialize-CafCsp Initializes the tenant to be associated with a Cloud Solution Provider. ✔️
Initialize-CafDeploymentSpGroup Initializes the security group AZ-CAF-DeployPrincipals for deployment service principals. ✔️
Initialize-CafServicePrincipals Initializes the default service principals in all management groups and subscriptions of the tenant. ✔️
Initialize-CafSubscription Initializes the subscription management resources for a single subscription. ✔️
Initialize-CafSubscriptions Initializes the subscription management resources in all subscriptions of the tenant. ✔️
Initialize-CafTenant Initializes the whole tenant by performing all CAF setup actions in sequence. ✔️
New-CafDeployment Deploys Azure resources by using a Bicep file within an automatically created service principal context.
New-CafSqlFirewallRule Adds a firewall rule to an Azure SQL Server for the current public IP.
Remove-CafJumphost Removes a Jumphost virtual machine and its associated OS disk.
Remove-CafLocks Removes locks from the resource group with the given name.
Remove-CafStaleRoleAssignments Deletes leftover role assignments for already deleted service principals.
Restore-CafLocks Restores all given locks to the specified resource group.
Set-CafServicePrincipal Creates or updates a service principal and stores the credentials in a Key Vault. ✔️
Show-CafNamingConvention Builds all the naming conventions from the context file and displays them in a table.
Show-CafSubscriptionsCost Displays cost information for all Azure subscriptions in the current tenant.
Start-CafPimGroup Assigns the user to a PIM group.
Start-CafPimRole Activates the user's PIM Role assignment.
Start-CafScoped Executes a command or script file in a new PowerShell session authenticated with a service principal.
Stop-CafPimGroup Deactivates the user's assignment to a PIM group.
Stop-CafPimRole Deactivates the user's PIM Role assignment.
Use-CafContext Ensures that the current PowerShell context for Azure is aligned with Get-CafContext.
Use-CafServicePrincipal Sets the context for a service principal using credentials stored in an Azure Key Vault.