Skip to content
Ask the community about this page

Create an Azure PowerShell package

Timextender Orchestration & Data Quality 23.3+Timextender Data Platform 26.3+cloud

An Azure PowerShell package runs a PowerShell script with the Az module inside an Azure context that the package sets up for you. Use it for the Azure housekeeping that has no purpose-built package type — tagging resources after a load, checking a storage account, calling an Azure API that nothing else covers.

Azure PowerShell or PowerShell?

Searching the picker for PowerShell returns two types. Azure PowerShell — this page — authenticates to Azure for you from a data provider and hands the script an Azure context. PowerShell runs a plain script with no credential and no Azure involvement.

If your script does not touch Azure, use the plain type: it needs no data provider.

What the package gives your script

Two variables, supplied from what you select in the editor:

Variable Contains
$subscriptionId The id of the selected subscription
$resourceGroupName The name of the selected resource group

And, more importantly, authentication. The engine signs in using the data provider's service principal before your script runs, so the script starts already connected.

The script must not sign in itself

Because authentication is generated for you, a script that authenticates is rejected — not at run time, but in the editor, before you can save:

Remove the 'Connect-AzAccount' command — authentication is generated automatically from the selected data provider.

Five commands are blocked, matched case-insensitively:

Connect-AzAccount, Disconnect-AzAccount, az account, az login, az logout

These are the only blocked commands. exit, break and return are all valid, including a final exit 0. See How success and failure are decided.

Before you start

  • An Azure App Registration data provider in the workspace
  • The service principal able to enumerate resource groups in the subscription. Resource group is required and selection-only, so without that permission the package cannot be completed — see Troubleshooting.
  • The principal needs whatever rights the script uses, which is usually more than reading

Steps

Screenshots stop at the subscription

The images are real but end where our test environment does: no service principal available to us can enumerate resource groups, so the resource-group selection, the save and the package list have no screenshot yet. The prose comes from the product's own field help and validation. See PACKAGE-DOCS-STATUS.md in this repository.

1. Create the package

Orchestration → Packages → Create, then Azure PowerShell from the Azure area.

Azure PowerShell in the picker

The editor opens with the selection chain collapsed — Subscription and Resource group read Select a data provider first until a provider is chosen.

A new Azure PowerShell package

2. Name it and choose the data provider

The Azure App Registration data provider whose service principal authenticates against Azure.

The data provider list

3. Choose the subscription

The Azure subscription the script runs against, loaded for the selected data provider. Its id is available in the script as $subscriptionId.

The subscription list

4. Choose the resource group

The resource group within the subscription, loaded for the selected subscription. Its name is available in the script as $resourceGroupName.

Both this list and the subscription list have a refresh button, for anything created in Azure after the page loaded.

5. Write the script

The PowerShell (Az) commands to execute. Authentication, $subscriptionId and $resourceGroupName are provided automatically.

The completed Definition tab

The editor is a full code editor, and Insert Parameter is available for global parameters.

If the script contains a sign-in command, saving is blocked with the error quoted above:

A forbidden command blocking Save

6. Save

The package saves as a Draft. Publish it to make it runnable on a schedule.

Examples

Tag a resource group after a load

$tags = @{ LastLoad = (Get-Date -Format 'yyyy-MM-dd') }
Set-AzResourceGroup -Name $resourceGroupName -Tag $tags | Out-Null

Write-Output "Tagged $resourceGroupName"

Fail the package when something is not as expected

$account = Get-AzStorageAccount -ResourceGroupName $resourceGroupName -Name "salesextracts"

if (-not $account) {
    throw "Storage account 'salesextracts' not found in $resourceGroupName"
}

Write-Output "Storage account present"

Either throw or exit 1 fails the package.

Act on every VM in the resource group

$vms = Get-AzVM -ResourceGroupName $resourceGroupName

foreach ($vm in $vms) {
    Write-Output "Found VM: $($vm.Name)"
}

For starting and stopping VMs on a schedule, prefer Azure Virtual Machine Start/Stop — a purpose-built type beats a script.

Best practices

Use the supplied variables rather than hard-coding a subscription or resource group. The package already knows both, and a hard-coded id survives promotion to another environment looking correct and being wrong.

Fail loudly. Use throw, or end with a non-zero exit code. A script that swallows its error reports success.

Write one confirmation line on the happy path. Standard output goes to the execution log, and a silent success tells you nothing later.

Reach for a purpose-built type when one exists. Scaling, pausing and starting resources have their own package types with validation and no script to maintain.

Give the principal the rights the script needs, and no more. Listing resources and changing them are different grants.

Troubleshooting

"No Resource Groups found under these credentials." The service principal cannot enumerate resource groups. Grant it subscription-level Reader, or at minimum Microsoft.Resources/subscriptions/resourceGroups/read — a SQL-scoped role alone returns an empty list. Because the field only accepts a selection, an empty list means the package cannot be saved at all.

Save is blocked and mentions a command. The script contains one of the blocked sign-in commands — Connect-AzAccount, Disconnect-AzAccount, az login, az logout or az account. Delete it; Timextender signs in for you using the data provider you selected. The log names the exact command that has to go.

The package fails within seconds saying there are no statements to run. The script is blank, or contains only comments — including the pre-filled example template a new package starts with. Saving with the untouched template shows "Please enter a script".

The script fails with an authorisation error from Azure. Authentication succeeded; authorisation did not. The principal can reach Azure but lacks the right for what the script does.

It worked last month and now fails immediately. The client secret on the data provider has expired. Credentials are read from the provider at run time, so fixing it there fixes every package that uses it.

How success and failure are decided

Three rules govern whether an Azure PowerShell package passes:

  • A non-zero exit code fails the package. A script that ends exit 1 is reported as failed.
  • Writing to the error stream fails the package, even if the script then completes its work and ends with exit 0. A recoverable error logged with Write-Error still fails the run.
  • A script with no executable statements fails immediately. Blank, or only comments.

exit, break and return are all valid in a script — in a loop, in a function, or as a final exit 0.

When a package fails, the execution log names the reason.

Reference

Fields

Field Required Notes
Execution connection No Defaults to Timextender Cloud
Data provider Yes Azure App Registration
Subscription Yes Fetched for the provider; refresh button
Resource group Yes Fetched for the subscription; refresh button; selection-only
Script Yes Comments count as content; only blank blocks saving

Four required fields. Validation: Please select a data provider, Please select a subscription, Please select a resource group, Please enter a script, and the forbidden-command message.

What is stored

ExecConnectionId, DataProviderId, SubscriptionId, ResourceGroupName and the script. Credentials are not stored on the package — they are read from the data provider at run time.

Subscription and resource group are selection-only — neither accepts a typed value. If your service principal cannot enumerate resource groups, the package cannot be created.

Discussed in the community

Looking for related questions…

Didn't find your answer? Ask the community about this page — questions are answered by Timextender experts, partners and other users.