Skip to main content

3 posts tagged with "github"

View All Tags

Keep your Azure Costs low by removing dev resources from resource groups on a schedule.

· 2 min read

I have a Visual Studio subscription that gives me £40.00 of Azure Credit each month to experiment in Azure. I find it relatively easy to spend this if I'm not careful about deleting resources after I've spun them up. Fortunately, I can use a GitHub Actions workflow on a schedule to save me when I forget.

I usually associate a set of resource groups with a repository in GitHub. I have a couple of options, I could delete the resource groups themselves or I could delete the resources in the resource groups. In this example, I've chosen just to delete the resources.

To do this, I use complete mode with an empty ARM template:

{    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",    "contentVersion": "1.0.0.0",    "resources": [    ]}

The GitHub Action then looks as follows:

name: destroy
on:  schedule:    - cron: "0 0 * * *"  # add workflow dispatch to be able to run trigger the workflow manually  workflow_dispatch:
jobs:
  destroy:    runs-on: ubuntu-latest    steps:        - name: Azure Login      uses: azure/login@v1      with:        creds: ${{ secrets.AZURE_CREDENTIALS }}
    - uses: actions/checkout@v2
    - name: Destroy      id: deploy-acr      uses: azure/CLI@v1      with:        azcliversion: 2.23.0        inlineScript: |          az deployment group create --name destroy --resource-group NAME_OF_YOUR_RESOURCE_GROUP --template-file .github/workflows/empty.json --mode Complete

Check out the the following repo for a working example: https://github.com/jamiemccrindle/bicep-app-service-container

How to rotate your AZURE_CREDENTIALS in GitHub with Terraform

· 3 min read

If you're deploying your Azure infrastructure from GitHub, you'll need Azure service principal credentials stored as secret variables. You may also want to rotate those credentials. This entry describes how you can use Terraform in your GitHub actions to configure and rotate your Azure service principal credentials.

In a previous post, I describe how to safely rotate credentials using Terraform. This post builds on that by showing you how to create client secrets for your Azure service principals and store them as secrets in GitHub.

First off, we'll create a Terraform module that will manage the secret rotation in Azure and GitHub. This stores everything you need to be able to deploy from GitHub to Azure, including information about the credentials, service principal, tenant and subscription.

It stores them both as an AZURE_CREDENTIALS json block that matches the output of az ad sp create-for-rbac --sdk-auth which is useful for the Azure Login GitHub Action under the variable AZURE_CREDENTIALS as well as broken out into ARM_CLIENT_ID, ARM_TENANT_ID, ARM_SUBSCRIPTION_ID and ARM_CLIENT_SECRET which is useful for running Terraform in GitHub Actions.

The format of the sdk-auth that the Azure Login GitHub Action requires is as follows:

{  "clientId": "APPLICATION_ID",  "clientSecret": "CLIENT_SECRET",  "subscriptionId": "SUBSCRIPTION_ID",  "tenantId": "TENANT_ID",  "activeDirectoryEndpointUrl": "https://login.microsoftonline.com",  "resourceManagerEndpointUrl": "https://management.azure.com/",  "activeDirectoryGraphResourceId": "https://graph.windows.net/",  "sqlManagementEndpointUrl": "https://management.core.windows.net:8443/",  "galleryEndpointUrl": "https://gallery.azure.com/",  "managementEndpointUrl": "https://management.core.windows.net/"}

The following files will create a Terraform module that will allow you to safely rotate secrets in Azure and store the currently active secret in GitHub secrets for use in GitHub Actions:

provider.tf

provider "azurerm" {  features {}}

variables.tf

variable "subscription_id" { type = string }variable "tenant_id" { type = string }variable "repository" { type = string }variable "application_id" { type = string }variable "application_object_id" { type = string }variable "date" { type = string }

main.tf

locals {  date        = tonumber(var.date)  odd_keeper  = floor((local.date + 1) / 2)  even_keeper = floor(local.date / 2)  use_even    = local.date % 2 == 0}
resource "random_uuid" "odd" {}
resource "azuread_application_password" "odd" {  application_object_id = var.application_object_id  description           = "odd"  value                 = random_password.odd.result  end_date_relative     = "1440h"  key_id                = random_uuid.odd.result}
resource "random_password" "odd" {  keepers = {    "date" = local.odd_keeper  }  length  = 64}
resource "random_uuid" "even" {}
resource "azuread_application_password" "even" {  application_object_id = var.application_object_id  description           = "even"  value                 = random_password.even.result  end_date_relative     = "1440h"  key_id                = random_uuid.even.result}
resource "random_password" "even" {  keepers = {    "date" = local.even_keeper  }  length  = 64}
resource "github_actions_secret" "terraform" {  repository      = var.repository  secret_name     = "AZURE_CREDENTIALS"  plaintext_value = <<-EOT{  "clientId": "${var.application_id}",  "clientSecret": "${local.use_even ? random_password.even.result : random_password.odd.result}",  "subscriptionId": "${var.subscription_id}",  "tenantId": "${var.tenant_id}",  "activeDirectoryEndpointUrl": "https://login.microsoftonline.com",  "resourceManagerEndpointUrl": "https://management.azure.com/",  "activeDirectoryGraphResourceId": "https://graph.windows.net/",  "sqlManagementEndpointUrl": "https://management.core.windows.net:8443/",  "galleryEndpointUrl": "https://gallery.azure.com/",  "managementEndpointUrl": "https://management.core.windows.net/"}EOT}
resource "github_actions_secret" "arm_client_id" {  repository = var.repository  secret_name = "ARM_CLIENT_ID"  plaintext_value = var.application_id}
resource "github_actions_secret" "arm_client_secret" {  repository = var.repository  secret_name = "ARM_CLIENT_SECRET"  plaintext_value = local.use_even ? random_password.even.result : random_password.odd.result}
resource "github_actions_secret" "arm_subscription_id" {  repository = var.repository  secret_name = "ARM_SUBSCRIPTION_ID"  plaintext_value = var.subscription_id}
resource "github_actions_secret" "arm_tenant_id" {  repository = var.repository  secret_name = "ARM_TENANT_ID"  plaintext_value = var.tenant_id}

Using the module#

module "example_github_azure" {  source                = "LOCATION_OF_MODULE"  subscription_id       = AZURE_SUBSCRIPTION_ID  tenant_id             = AZURE_TENANT_ID  repository            = GITHUB_REPO_NAME  application_id        = AZURE_APPLICATION_ID  application_object_id = AZURE_APPLICATION_OBJECT_ID  date                  = var.date}

To see it in action, have a look at this repository https://github.com/jamiemccrindle/azure-rotate-service-principal-github-secrets

Install a specific version of Terraform in a Github Action using apt

· One min read

The standard way to install Terraform on ubuntu is via apt but the instructions typically don't show how to select a specific version. Most examples of how to install a specific version of terraform in a GitHub action just pull the binary directly.

This is how you can install a specific version of Terraform for use in a GitHub action using apt:

name: install-terraform-example
on:  push:    branches:      - main
jobs:
  install-terraform:    runs-on: ubuntu-latest    steps:    - run: |        curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -        sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"        sudo apt-get update        sudo apt-get install terraform=0.14.10