After successfully configuring and setting up Azure and Terraform in GitHub Actions, I embarked on a Proof of Concept (POC) to automate PowerShell scripts (Azure az module) using GitHub Actions. I meticulously automated all the job steps using PowerShell, with a primary focus on utilizing credentials to establish a secure connection to the Microsoft Azure cloud and perform the necessary configuration and setup.
For authentication to Azure, I have securely added credentials in GitHub Actions secrets and variables, ensuring seamless and secure access to Azure resources.
To authenticate to Azure using the PowerShell Az module, I'm utilizing Azure Service Principal information. I've stored the sensitive credentials, including AZURE_SUBSCRIPTION_ID, AZURE_TENANT_ID, AZURE_CLIENT_ID, and AZURE_CLIENT_SECRET, as secrets in GitHub Actions. By inputting these values into the secrets, I can securely leverage the same credentials to authenticate and perform Azure management tasks using PowerShell scripts.
Complete series on DevOps - GitHub Actions
Part 1: Create GitHub repository and branches using Terraform
Part 2 Terraform modules using a github.com repository as a source
Part 3 Automating and Planning Azure Resources with Terraform and GitHub Actions
Part 4 GitHub Actions deploy azure resources with Terraform backend
Part 4.1 GitHub Actions deploy azure resources with PowerShell
Part 4.2 GitHub Actions manage Microsoft Azure Cloud with az CLI
Download this Azure management with PowerShell and Github Actions.zip here or it is also available on github.com.
When code is pushed to GitHub, the Actions workflow is triggered, initiating the automation process. The workflow executes the specified PowerShell commands or scripts, automating the environment as configured. This seamless integration enables efficient and consistent management of Azure resources, streamlining tasks and workflows.
# Push the code to github git add . ; git commit -m "PowerShell Credentials" ; git push origin --force
Below is my complete GitHub Actions workflow YAML file. In the PowerShell task's inline script, I've created variables from secrets using the ${{ secrets.<id> }} syntax. These variables correspond to my Azure Service Principal ID, Secret and subscription/Tenant IDs.
I utilize these variables to create credentials PowerShell object, which authenticate my connection to Azure, connect it and enables the execution of subsequent commands. Additionally, I have the option to run or execute a PowerShell (.ps1) file, providing flexibility in my automation workflow.
# Name of the action that will trigger name: PowerShell # Trigger on push event to the repository on: push: # Define jobs to run jobs: powershell: name: Run PowerShell Workflow runs-on: ubuntu-latest # Specify the OS for the runner # Use bash as the default shell for the steps defaults: run: shell: bash # List of steps to execute steps: # Step 1: Checkout the repository to the runner - name: Checkout Repository uses: actions/checkout@v3 # Step 3: Run PowerShell script with Azure commands - name: Run Azure PowerShell Script uses: azure/powershell@v1 with: inlineScript: | # Authenticate using service principal credentials $clientId = "${{ secrets.AZURE_CLIENT_ID }}" $tenantId = "${{ secrets.AZURE_TENANT_ID }}" $clientSecret = "${{ secrets.AZURE_CLIENT_SECRET }}" $subscriptionId = "${{ secrets.AZURE_SUBSCRIPTION_ID }}" # Log in using Service Principal credentials Connect-AzAccount -ServicePrincipal -TenantId $tenantId -Credential (New-Object System.Management.Automation.PSCredential($clientId, (ConvertTo-SecureString $clientSecret -AsPlainText -Force))) -SubscriptionId $subscriptionId # Example: List resource groups in Azure Get-AzResourceGroup -Name Dev # Specify the PowerShell Core version to use azPSVersion: "latest" # Step 4: (Optional) Run a PowerShell script file instead of inline script # - name: Run PowerShell Script from File # uses: azure/powershell@v1 # with: # scriptPath: ./scripts/deploy.ps1 # Path to the PowerShell script # azPSVersion: "latest"
This auto triggered and successfully completed workflow after pushing code to GitHub.
Here is the screenshot of the GitHub Actions workflow successful output.
Below is the complete text output from GitHub Action of executed workflow PowerShell Job.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
Run azure/powershell@v1 with: inlineScript: # Authenticate using service principal credentials $clientId = "***" $tenantId = "***" $clientSecret = "***" $subscriptionId = "***" # Log in using Service Principal credentials Connect-AzAccount -ServicePrincipal -TenantId $tenantId -Credential (New-Object System.Management.Automation.PSCredential($clientId, (ConvertTo-SecureString $clientSecret -AsPlainText -Force))) -SubscriptionId $subscriptionId # Example: List resource groups in Azure Get-AzResourceGroup -Name Dev azPSVersion: latest errorActionPreference: Stop failOnStandardError: false githubToken: *** Validating inputs Module Az latest installed from hostedAgentFolder Initializing Az Module /usr/bin/pwsh -NoLogo -NoProfile -NonInteractive -Command Test-Path (Join-Path /usr/share az_*) /usr/bin/pwsh -NoLogo -NoProfile -NonInteractive -Command $env:PSModulePath /home/runner/.local/share/powershell/Modules:/usr/local/share/powershell/Modules:/opt/microsoft/powershell/7/Modules /usr/bin/pwsh -NoLogo -NoProfile -NonInteractive -Command try { $ErrorActionPreference = "Stop" $WarningPreference = "SilentlyContinue" $output = @{} $data = Get-Module -Name Az -ListAvailable | Sort-Object Version -Descending | Select-Object -First 1 $output['AzVersion'] = $data.Version.ToString() $output['Success'] = "true" } catch { $output['Error'] = $_.exception.Message } return ConvertTo-Json $output True { "AzVersion": "12.1.0", "Success": "true" } /usr/bin/pwsh -NoLogo -NoProfile -NonInteractive -Command $env:PSModulePath /usr/share:/home/runner/.local/share/powershell/Modules:/usr/local/share/powershell/Modules:/opt/microsoft/powershell/7/Modules Initializing Az Module Complete Running Az PowerShell Script /usr/bin/pwsh -NoLogo -NoProfile -NonInteractive -Command /home/runner/work/_temp/0cc34a53-1b9a-48d0-a951-4d1686df31c5.ps1 WARNING: The provided service principal secret or certifcate password will be included in the 'keystore.cache' file found in the user profile ( /home/runner/.Azure ). Please ensure that this directory has appropriate protections. Subscription name Tenant ----------------- ------ Sponsership-by-Microsoft *** ResourceGroupName : dev Location : eastus ProvisioningState : Succeeded Tags : {} TagsTable : ResourceId : /subscriptions/***/resourc eGroups/dev ManagedBy : WARNING: You're using Az version 12.1.0. The latest version of Az is 12.3.0. Upgrade your Az modules using the following commands: Update-PSResource Az -WhatIf -- Simulate updating your Az modules. Update-PSResource Az -- Update your Az modules. Script execution Complete |
Useful Articles
Terraform clone virtual machine template in VMware vSphere vCenter from CSV file
Terraform error retrieving storage account failure responding to request StatusCode 404 StorageAccountNotFound The storage account was not found
Terraform testing local variables and output csv file without resource Part 1
Terraform testing variable map object values without resource configuration part 2
Terraform foreach module output to show only required results
Terraform deploy create A Private DNS Record in Microsoft Azure from list of objects
Terraform clone virtual machine template in VMware vSphere vCenter Dynamic Content Part 2
Terraform variable precedence and priority
Terraform filter map and list object with if condition in for_each loop examples
Terraform Azure function app with private endpoint and storage account
Terraform module Azure function app with private endpoint and storage account
Terraform passing different credentials to different subscriptions with provider alias
Terraform Azure provider alias passing credentials and configuration in module resources
Terraform Azure provider passing multiple alias environment and credentials in child module
Terraform variable multiple validation advanced blocks example
Terraform variable type list with for_each for loop examples
Terraform convert single string to list or set
Terraform workspaces with example
Terraform map of object for loop with if condition example
Terraform for_each for loop list of object without count example
Terraform using for loop in attribute value without for_each