Skip to content
adatum
  • Home
  •  About adatum
  •  Learn Azure Bicep
  •  SCOM Web API
Azure Active Directory

GitHub actions federated identity with Azure AD

  • 24/08/202224/08/2022
  • by Martin Ehrnst

A long-awaited feature for many is the ability to authenticate with Azure in a GitHub workflow. For a long time, this has been an integrated feature in Azure DevOps, and for some time GitHub actions have had the ability to authenticate using Azure Application registrations and secrets. But now, we can use federated credentials which utilize OIDC- This will completely remove the cumbersome task of rotating app secrets.

Configure an Azure Application with federated identity

At my company, I have decided we should look into moving pipelines from Azure DevOps to GitHub. Federated identity is now Generally Available (GA) which means we are allowed to work with a production solution in mind. So how do you set it up? my suggestion is to follow the official guide. Below is a script that will configure an Azure AD application with GitHub authentication enabled. The script assumes you use a branching strategy. However, you can change this to be any of the other entity types, altering the federationSubcject variable.

# creates an appregistration in Azure AD and connects it with a github repo
# use as an example only
[CmdletBinding()]
param (
[Parameter(Mandatory)]
[string]
$gitHubRepoName,
[Parameter(Mandatory)]
[string]
$teamName,
[Parameter(Mandatory)]
[string]
$branchName = "main"
)
$organization = "myorgltd"
$appRegistrationName = "gh-$teamName-action-sp"
$appRegistrationDescription = "Used by $teamName for enabeling GitHub actions with Azure AD OIDC authentication"
$audience = "api://AzureADTokenExchange"
$ghIssuer = "https://token.actions.githubusercontent.com/"
$federationName = "action-$gitHubRepoName"
$federationSubject = "repo:$($organization)/$($gitHubRepoName):ref:refs/heads/$($branchName)"
# check if app exists
$GhAdApp = $null
$GhAdApp = Get-AzADApplication –DisplayName $appRegistrationName
if ($GhAdApp) {
Write-Output "App registration already exist. Adding new credential for specified repo $gitHubRepoName"
$federatedCred = New-AzADAppFederatedCredential –ApplicationObjectId $GhAdApp.Id `
–Audience $audience –Issuer $ghIssuer –Subject $federationSubject `
–Name $federationName –Description "Used to authenticate pipeline in $gitHubRepoName"
}
# if app does not eist
else {
Write-Output "adding new app registration for $teamName with credentials for $gitHubRepoName"
$GhAdApp = New-AzADApplication –DisplayName $appRegistrationName –Description $appRegistrationDescription
$federatedCred = New-AzADAppFederatedCredential –ApplicationObjectId $GhAdApp.Id `
–Audience $audience –Issuer $ghIssuer –Subject $federationSubject `
–Name $federationName –Description "Used to authenticate pipeline in $gitHubRepoName"
}
$credentialObject = [PSCustomObject]@{
ApplicationName = "$($GhAdApp.DisplayName)"
ApplicationObjectId = "$($GhAdApp.Id)"
}
Write-Output $credentialObject | ConvertTo-Json
view raw create-adappgithub.ps1 hosted with ❤ by GitHub

Configure repository secrets in GitHub using PowerShell

As you probably understand, I need to automate this entire process. If our developers are moving from DevOps to Github workflows, it has to be as easy as it can be. No one will move unless they see some benefits, and onboarding is just as easy as the current DevOps setup. I am pretty familiar with Azure as an identity platform, especially with app registrations and enterprise apps. So the above script was done quickly. On the other hand, I am not that familiar with GitHub APIs. I know there’s a CLI, but for various reasons, I need to look into the API, more specifically the repository secrets API. What you can see from the first part of the documentation is that you need to encrypt the secret before you make the put request.

Creates or updates an organization secret with an encrypted value. Encrypt your secret using LibSodium. 

GitHub api docs

Now I was in trouble. Should I write everything in .NET, or is it possible to solve this using PowerShell? For sure I would be better off using PowerShell, at least in the PoC phase. First I tried to load the .NET sodium DLLs in my script, but it did not work, and the approach is not that delightful. Luckily with some search engine work, I found a module that wraps Sodium, created specifically for creating secrets in GitHub. Thanks, Tyler! See my example script below.

# add secrets to repo
import-module PSSodium
$ghToken = "ghp_"
$headers = @{Authorization = "token " + $ghToken}
$secret = "fb4ca569-c690-4391-96d9-928e7a8fd7ff"
$repoName = "myrepo"
$organization = "myorgltd"
Invoke-RestMethod –Method get –Uri "https://api.github.com/repos/$($organization)/$($repoName)/actions/secrets" –Headers $headers
$publicKey = (Invoke-RestMethod –Method get –Uri "https://api.github.com/repos/$($organization)/$($repoName)/actions/secrets/public-key" –Headers $headers)
$encryptedSecret = ConvertTo-SodiumEncryptedString –Text $secret –PublicKey $($publicKey.key)
$secretBody = @"
{
"encrypted_value": "$encryptedSecret",
"key_id": "$($publicKey.key_id)"
}
"@
Invoke-RestMethod –Method Put –Uri "https://api.github.com/repos/$($organization)/$($repoName)/actions/secrets/AZURE_TENANT_ID" –Headers $headers –body $secretBody
view raw create-ghsecret.ps1 hosted with ❤ by GitHub

What about the pipeline?

Next, you need a working pipeline. Lucky for you the documentation is way better when I first looked at this (before GA), so the example works just fine as it is. Anyway, there are a couple of things to point out. Namely the permissions and the setting for login without a subscription ID.

name: 'Federated identity test'
on:
push:
branches:
– main
permissions:
id-token: write
contents: read
jobs:
build-and-publish:
runs-on: ubuntu-latest
steps:
– name: checkout
uses: actions/checkout@main
– name: azure login
uses: azure/login@v1
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
allow-no-subscriptions: true
view raw workflow.yaml hosted with ❤ by GitHub

Summary

I hope this short post on how to configure Azure and GitHub with federated identity helps you, and that it provided some more information than the official documentation does. If anything please reach out. I now have my scripts in place, and can start the full automation and migration from Azure DevOps pipelines.

Share this:

  • LinkedIn
  • Twitter
  • Reddit
Automation

Web API for System Center Operations Manager

  • 05/05/201715/11/2017
  • by Martin Ehrnst

The SCOM web API is updated, see this post

You will always find the latest SCOM Web API release on GitHub

 

System Center Operations Manager (SCOM) is a widely used monitoring platform and one of its advatages is the ability to custom author monitoring through management pack development.
With a ‘cloud first’ approach most systems is able to do information exchange or integration through a web-based API, often reffered to as a REST API. SCOM have many ways to exchange information and the System Center Suite also have an integration platform call System Center Service Provide Foundation (SPF) which you can read more about here

To support a more light weight integration platform i decided to start my first C# project and develop a web-based API for SCOM that supported the daily used “functions”. Thanks to my colleague @RudiMartinsen i managed to create a working solution.

API Endpoints

  • [GET] Agents (Admin privileges required)
    • Get all agents
    • single based on Guid
  • [GET] Alerts
    • Gets all alerts
    • single based on Guid
    • Single based on ComputerName
      • Include ‘closed’ with IncClosed=true
  • [PUT] Alerts
    • Update a single alert with resolution state and/or ticket id
    • Monitor generated alerts will be resett if 255 (closed) is sent as resolution state
  • [GET] WindowComputers
    • Get all partial monitoring object from the Windows Computer class
    • Single based on ComputerName
  • [POST] ComputerMaintenance*
    • Maintenance mode a Windows Computer for a specific # minutes
  • [GET] MonintoringObject/{id}
    • Get a single monitoring object based on ID (Guid)

I have uploaded the source project on GitHub and hopefully our community can continue to develop and introduce new features missing in this release.

 

Installation

There are two versions of the API. One without user impersonation and one where this is available. To install the version with user impersonation enabled. Do the following on a SCOM Management server

  • Download the project or .zip file from GitHub
  • Copy the required .dll from your management server (\Operations Manager\Server\SDK Binaries) to the web api Bin folder
    • Microsoft.EnterpriseManagement.Core.dll
    • Microsoft.EnterpriseManagement.OperationsManager.dll
    • Microsoft.EnterpriseManagement.Runtime.dll
  • Create a new web site and set physical path to where you extracted the files

  • Enable windows authentication (and basic if you want)
  • Set your Application pool to use network service identity

 

Examples

Using powershell here are a few examples on how you can use the API

Get Alerts
#Get all alerts
Invoke-RestMethod -Uri 'http://localhost:64049/Api/alerts' -UseDefaultCredentials

#Get a single alert
Invoke-RestMethod -Uri 'http://localhost:64049/Api/alerts?id=4a6f29e3-f4b5-4883-a3f2-97eb3be50c12' -UseDefaultCredentials

#Get alerts specified with computername
Invoke-RestMethod -Uri 'http://localhost:64049/Api/alerts?ComputerName=COMPUTERNAME.fqdn' -UseDefaultCredentials
Put a computer in to maintenance
PS C:\Users\...> $json = @"
{
    "DisplayName": "COMPUTERNAME.fqdn",
    "Minutes": 10,
    "comment": "I believe this is working"
}
"@

Invoke-RestMethod -Method POST -Uri 'http://localhost:64049/API/ComputerMaintenance' -Body $json -UseDefaultCredentials -ContentType 'Application/json'

Returns

DisplayName           Minutes EndTime                      comment                  
-----------           ------- -------                      -------                  
COMPUTER NAME.fqdn      10 2017-05-05T08:42:56.5938294Z I believe this is working
Get a monitoring object
#Get a monitoring object
Invoke-restmethod -uri 'http://localhost:64049/API/MonitoringObject/cb191c1a-47dc-3c51-3686-9f66dd59f187' -UseDefaultCredentials


displayName : D:
healthState : Success
inMaintenance : False
stateLastModified : 23.03.2017 15.39.23
classes :
path : MyComputerHostingThisDisk.fqdn

 

Limitations*

  • SCOM .dll files will need to copied manually in to the web api application folder as I assume im not allowed to redestribute these.

Share this:

  • LinkedIn
  • Twitter
  • Reddit

Popular blog posts

  • Azure Application registrations, Enterprise Apps, and managed identities
  • SCOM 1801 REST API Interfaces
  • Creating Azure AD Application using Powershell
  • Automate Azure DevOps like a boss
  • Access to Blob storage using Managed Identity in Logic Apps - by Nadeem Ahamed

Categories

Automation Azure Azure Active Directory Azure Bicep Azure DevOps Azure Functions Azure Lighthouse Azure Logic Apps Azure Monitor Azure Policy Community Conferences CSP Monitoring DevOps Guest blogs Infrastructure As Code Microsoft CSP MPAuthoring OMS Operations Manager Podcast Powershell Uncategorised Windows Admin Center Windows Server

Follow Martin Ehrnst

  • Twitter
  • LinkedIn

RSS feed RSS - Posts

RSS feed RSS - Comments

Microsoft Azure MVP

Martin Ehrnst Microsoft Azure MVP
Adatum.no use cookies to ensure that we give you the best experience on our website. If you continue to use this site we will assume that you are happy with it. Cookie Policy
Theme by Colorlib Powered by WordPress