Azure SDK for Go authentication with a service principal
In this tutorial, you 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 a Microsoft Entra tenant, enabling core features such as authentication during sign-on and authorization during resource access. They remove the need to use personal accounts to access Azure resources. You can assign a service principal the exact permissions needed for your app and develop against those permissions, rather than using a personal account, which might have more privileges in your tenant than the app requires. You can also use service principals for apps that are hosted on-premises that need to use Azure resources. The Azure SDK for Go Azure Identity module provides a convenient way to authenticate to Azure with a service principal using environment variables, and 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.18 or above
If you want to use the Azure CLI to run the steps in this article:
Use the Bash environment in Azure Cloud Shell. For more information, see Quickstart for Bash in Azure Cloud Shell.
If you prefer to run CLI reference commands locally, install the Azure CLI. If you're running on Windows or macOS, consider running Azure CLI in a Docker container. For more information, see How to run the Azure CLI in a Docker container.
If you're using a local installation, sign in to the Azure CLI by using the az login command. To finish the authentication process, follow the steps displayed in your terminal. For other sign-in options, see Sign in with the Azure CLI.
When you're prompted, install the Azure CLI extension on first use. For more information about extensions, see Use extensions with the Azure CLI.
Run az version to find the version and dependent libraries that are installed. To upgrade to the latest version, run az upgrade.
If you want to use Azure PowerShell to run the steps in this article:
- If you choose to use Azure PowerShell locally:
- Install the latest version of the Az PowerShell module.
- Connect to your Azure account using the Connect-AzAccount cmdlet.
- If you choose to use Azure Cloud Shell:
- See Overview of Azure Cloud Shell for more information.
- If you choose to use Azure PowerShell locally:
1. Create Azure resources
Before you begin, create a new resource group and key vault instance.
az group create --name go-on-azure --location eastus
az keyvault create --location eastus --name <keyVaultName> --resource-group go-on-azure --enable-rbac-authorization
Replace <keyVaultName>
with a globally unique name.
Note down the id
property from the output of the az keyvault create
command. You'll use it in the next section to define the scope of the authorization for the service principal. The id
value has the following form: /subscriptions/<subscriptionId>/resourceGroups/go-on-azure/providers/Microsoft.KeyVault/vaults/<keyVaultName>
.
2. Create an Azure service principal
Use one of the following techniques to create an Azure service principal and assign it the "Key Vault Secrets Officer" role on the key vault:
- Option 1: Create an Azure service principal with a secret
- Option 2: Create an Azure service principal with a certificate
To learn more Azure service principals, see Service principal object.
Assigning the "Key Vault Secrets Officer" role to the service principal, authorizes it to create, read, update, and delete secrets in the key vault. To learn more about built-in roles for Azure key vault, see Provide access to Key Vault keys, certificates, and secrets with an Azure role-based access control. To learn more about built-in roles in Azure, see Azure built-in roles.
Option 1: Create an Azure service principal with a secret
Run the following commands to create an Azure service principal and assign it the "Key Vault Secrets Officer" role on the key vault.
az ad sp create-for-rbac --name <servicePrincipalName> --role "Key Vault Secrets Officer" --scope <keyVaultId>
Replace <servicePrincipalName>
and <keyVaultId>
with the appropriate values.
Note down the password
, tenant
, and appId
properties from the output. You need them in the next section.
After creation, the service principal password can't be retrieved. If you forget the password, you can reset the service principal credentials.
Option 2: Create an Azure service principal with a certificate
Run the following commands to create an Azure service principal that uses a certificate and assign it the "Key Vault Secrets Officer" role on the key vault.
az ad sp create-for-rbac --name <servicePrincipalName> --create-cert --role "Key Vault Secrets Officer" --scope <keyVaultId>
Replace <servicePrincipalName>
and <keyVaultId>
with the appropriate values.
Note down the fileWithCertAndPrivateKey
, tenantId
, and appId
properties from the output. You need them in the next section.
3. Authenticate to Azure with a service principal
By using DefaultAzureCredential
, you can avoid writing environment-specific code to authenticate to Azure. With DefaultAzureCredential
, you can configure your service principal credentials by defining environment variables.
Choose 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 Microsoft Entra 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 Microsoft Entra tenant |
AZURE_CLIENT_CERTIFICATE_PATH |
Path to a PEM or PKCS12 certificate file including private key. If you followed the steps for the Azure CLI, the file isn't password protected. If you followed the steps for Azure PowerShell, the file is password protected, and you'll also need to set the AZURE_CLIENT_CERTIFICATE_PASSWORD environment variable. |
AZURE_CLIENT_CERTIFICATE_PASSWORD |
The password you entered when you created the service principal. Only needed if you followed the steps for Azure PowerShell. |
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 a resource client
After you set the environment variables, you can use DefaultAzureCredential
in the Azure Identity module to authenticate a resource client. The following code shows how to get an instance of DefaultAzureCredential
.
cred, err := azidentity.NewDefaultAzureCredential(nil)
if err != nil {
log.Fatalf("failed to obtain a credential: %v", err)
}
4. Create a key vault secret with Go
Use the following code sample to verify that your service principal authenticates to Azure and has the appropriate permissions to the key vault.
Create a new directory called
go-on-azure
in your home directory.mkdir ~/go-on-azure
Change to the
go-on-azure
directory.cd ~/go-on-azure
Run
go mod init
to create thego.mod
file.go mod init go-on-azure
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/security/keyvault/azsecrets"
Create a file named
main.go
and add the following code.package main import ( "context" "fmt" "log" "os" "github.com/Azure/azure-sdk-for-go/sdk/azidentity" "github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets" ) func createSecret(name, value string) { keyVaultName := os.Getenv("KEY_VAULT_NAME") keyVaultUrl := fmt.Sprintf("https://%s.vault.azure.net/", keyVaultName) cred, err := azidentity.NewDefaultAzureCredential(nil) if err != nil { log.Fatalf("failed to obtain a credential: %v", err) } client, err := azsecrets.NewClient(keyVaultUrl, cred, nil) if err != nil { log.Fatalf("failed to create a client: %v", err) } params := azsecrets.SetSecretParameters{Value: &value} resp, err := client.SetSecret(context.TODO(), name, params, nil) if err != nil { log.Fatalf("failed to create a secret: %v", err) } fmt.Printf("Name: %s, Value: %s\n", *resp.ID, *resp.Value) } func main() { createSecret("ExamplePassword", "hVFkk965BuUv") }
Create an environment variable named
KEY_VAULT_NAME
. Set the environment variable's value to the name of the Azure Key Vault created previously.export KEY_VAULT_NAME=<keyVaultName>
Replace
<keyVaultName>
with the name of your Azure Key Vault instance.Run the
go run
command to create the new key vault secret.go run main.go
On success, the output is similar to the following:
Name: https://<keyVaultName>.vault.azure.net/secrets/ExamplePassword/1e697f71d0014761a65641226f2f057b, Value: hVFkk965BuUv
5. Clean up resources
If you no longer want to use the Azure resources you created in this article, it's a good practice to delete them. Deleting unused resources helps you avoid incurring ongoing charges and keeps your subscription uncluttered. The easiest way to delete the resources you used in this tutorial is to delete the resource group.
az group delete --name go-on-azure --yes
The --yes
argument tells the command not to ask for confirmation.
The preceding command performs a soft delete on the key vault in the resource group. To permanently remove it from your subscription, enter the following command:
az keyvault purge --name <keyVaultName> --no-wait
Replace <keyVaultName>
with the name of your key vault.
Finally, you should remove the app registration and service principal.
az ad app delete --id <servicePrincipalAppId>
Replace <servicePrincipalAppId>
with the App ID of your service principal.