Azure SDK for Go authentication with a service principal

In this tutorial, you'll use the Azure SDK for Go to authenticate to Azure with an Azure service principal using either a secret or a certificate.

Azure service principals define the access policy and permissions in an Azure AD tenant. Enabling core features such as authentication during sign-on and authorization during resource access. Removing the need to use personal accounts to access Azure resources. The Azure SDK for Go's Azure Identity module provides a convenient way to authenticate with Azure using a service principal using environment variables, a secret, or a certificate

Follow this tutorial to create and authenticate with the Azure SDK for Go using a service principal.

Prerequisites

  • Azure subscription: If you don't have an Azure subscription, create a free account before you begin.
  • Go installed: Version 1.16 or above

1. Create an Azure resource group

Before you begin, create a new resource group in Azure.

az group create --name go-on-azure --location eastus

Take note of the Id from the output, you'll use it for the scope of the service account.

2. Create an Azure service principal

Use one of the following techniques to create an Azure service principal:

To learn more Azure service principals, see Service principal object.

Option 1: Create an Azure service principal with a secret

Run the following commands to create an Azure service principal.

az ad sp create-for-rbac --name `<servicePrincipalName>` --role Contributor --scope <resourceGroupId>

Replace <servicePrincipalName> and <resourceGroupId> with the appropriate values.

Make sure you copy the password value - it can't be retrieved. If you forget the password, reset the service principal credentials.

Option 2: Create an Azure service principal with a certificate

az ad sp create-for-rbac --name <servicePrincipal> --create-cert --role Contributor --scope <resourceGroupId>

Replace <servicePrincipalName> and <resourceGroupId> with the appropriate values.

3. Authenticate to Azure with a service principal

By using the DefaultAzureCredential, you can avoid writing environment-specific code to authenticate to Azure.

Use the DefaultAzureCredential to configure your service principal credentials by defining environment variables.

Choosing one of the following options to configure your service principal credentials:

To learn more about the DefaultAzureCredential, check out Azure authentication with the Azure SDK for Go

Option 1: Authenticate with a secret

Define the following environment variables:

Variable name Value
AZURE_CLIENT_ID Application ID of an Azure service principal
AZURE_TENANT_ID ID of the application's Azure AD tenant
AZURE_CLIENT_SECRET Password of the Azure service principal
export AZURE_TENANT_ID="<active_directory_tenant_id"
export AZURE_CLIENT_ID="<service_principal_appid>"
export AZURE_CLIENT_SECRET="<service_principal_password>"

Option 2: Authenticate with a certificate

Variable name Value
AZURE_CLIENT_ID Application ID of an Azure service principal
AZURE_TENANT_ID ID of the application's Azure AD tenant
AZURE_CLIENT_CERTIFICATE_PATH Path to a certificate file including private key (without password protection)
export AZURE_TENANT_ID="<active_directory_tenant_id"
export AZURE_CLIENT_ID="<service_principal_appid>"
export AZURE_CLIENT_CERTIFICATE_PATH="<azure_client_certificate_path>"

Use DefaultAzureCredential to authenticate ResourceClient

Use the NewDefaultAzureCredential function of the Azure Identity module to authenticate a ResourceClient.

cred, err := azidentity.NewDefaultAzureCredential(nil)
if err != nil {
  // handle error
}

client := armresources.NewResourcesClient(armcore.NewDefaultConnection(cred, nil), "<subscriptionId>")

Replace <subscriptionId> with the subscription ID of the subscription you want to authenticate with.

Key points:

4. Create a resource group tag (sample)

Use the following code sample to verify that your service principal authenticates to Azure and has the appropriate permissions to the resource group.

  1. Create a new directory called go-on-azure in your home directory.

    mkidr ~/go-on-azure
    
  2. Change to the go-on-azure directory.

    cd ~/go-on-azure
    
  3. Run go mod init to create the go.mod file.

    go mod init go-on-azure
    
  4. Run go get to install the required Go modules.

    go get "github.com/Azure/azure-sdk-for-go/sdk/azidentity"
    go get "github.com/Azure/azure-sdk-for-go/sdk/resources/armresources"
    go get "github.com/Azure/azure-sdk-for-go/sdk/azcore"
    go get "github.com/Azure/azure-sdk-for-go/sdk/armcore"
    
  5. Create a file named main.go and add the following code.

     package main
    
     // Import key modules.
     import (
     "context"
     	"log"
    
     	"github.com/Azure/azure-sdk-for-go/sdk/armcore"
     	"github.com/Azure/azure-sdk-for-go/sdk/azcore"
     	"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
     	"github.com/Azure/azure-sdk-for-go/sdk/resources/armresources"
     )
    
     // Define key global variables.
     var (
     	ctx               = context.Background()
     	subscriptionId    = "<subscriptionId>"
     	resourceGroupName = "go-on-azure" // !! IMPORTANT: Change this to a unique name in your subscription.
     )
    
     func addResourceGroupTag(ctx, connection *armcore.Connection) (armresources.ResourceGroupResponse, error) {
     	rgClient := armresources.NewResourceGroupsClient(connection, subscriptionId)
    
     	update := armresources.ResourceGroupPatchable{
     		Tags: map[string]*string{
     			"new": to.StringPtr("tag"),
     		},
     	}
     	return rgClient.Update(ctx, resourceGroupName, update, nil)
     }
    
     // Define the standard 'main' function for an app that is called from the command line.
     func main() {
    
     	// Create a credentials object.
     	cred, err := azidentity.NewDefaultAzureCredential(nil)
     	if err != nil {
     		log.Fatalf("Failed to configure credential: %+v", err)
     	}
    
     	// Establish a connection with the Azure subscription.
     	conn := armcore.NewDefaultConnection(cred, &armcore.ConnectionOptions{
     		Logging: azcore.LogOptions{
     			IncludeBody: true,
     		},
     	})
    
     	// Call your function to add a tag to your new resource group.
     	updatedRG, err := addResourceGroupTag(ctx, conn)
     	if err != nil {
     		log.Fatalf("Update of resource group failed: %+v", err)
     	}
     	log.Printf("Resource Group %s updated", *updatedRG.ResourceGroup.ID)
    
     }
    

    Replace <subscriptionId> with the subscription ID of the subscription you want to authenticate with.

  6. Run the go run command to add the tag to your resource group.

     go run main.go
    
  7. Verify the tag was added.

     az group show --resource-group go-on-azure --query 'tags'
    

Next steps