title | description | ms.date | ms.topic | ms.custom |
---|---|---|---|---|
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 a secret or a certificate. |
05/17/2024 |
how-to |
devx-track-go, devx-track-azurepowershell |
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.
[!INCLUDE azure-subscription.md]
-
Go installed: Version 1.18 or above
-
If you want to use the Azure CLI to run the steps in this article:
[!INCLUDE Azure CLI prerequisites no header]
-
If you want to use Azure PowerShell to run the steps in this article:
[!INCLUDE Azure PowerShell prerequisites no header]
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>
.
New-AzResourceGroup -Name go-on-azure -Location eastus
New-AzKeyVault -ResourceGroupName go-on-azure -Name <keyVaultName> -Location eastus -EnableRbacAuthorization
Replace <keyVaultName>
with a globally unique name.
Note down the Resource ID
property from the output of the New-AzKeyVault
command. You'll use it in the next section to define the scope of the authorization for the service principal. The Resource ID
value has the following form:/subscriptions/<subscriptionId>/resourceGroups/go-on-azure/providers/Microsoft.KeyVault/vaults/<keyVaultName>
.
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.
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.
# Create an Azure service principal
$sp = New-AzADServicePrincipal -DisplayName '<servicePrincipalName>' -Role 'Key Vault Secrets Officer' -Scope <keyVaultId>
# Export the password for the service principal
$sp.PasswordCredentials.SecretText
# Export the service principal App ID
$sp.AppId
# Get the Tenant ID
(Get-AzTenant).Id
Replace <servicePrincipalName>
, and <keyVaultId>
with the appropriate value.
Note down the Password, App ID, and Tenant ID. You need them in the next section.
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.
$certParams = @{
CertStoreLocation = "Cert:\CurrentUser\My"
Subject = "CN=<servicePrincipalName>"
KeySpec = 'KeyExchange'
}
$cert = New-SelfSignedCertificate @certParams
$keyValue = [System.Convert]::ToBase64String($cert.GetRawCertData())
$spCertParams = @{
CertValue = $keyValue
EndDate = $cert.NotAfter
StartDate = $cert.NotBefore
DisplayName = '<servicePrincipalName>'
}
$sp = New-AzADServicePrincipal @spCertParams
$pftPwd = Read-Host -Prompt 'Enter pft password' -AsSecureString
$cert | Export-PfxCertificate -FilePath '<servicePrincipalName>.pfx' -Password $pftPwd
# assign role permissions to the service principal
$roleAssignmentParams = @{
ObjectId = $sp.id
RoleDefinitionName = 'Key Vault Secrets Officer'
Scope = '<keyVaultId>'
}
New-AzRoleAssignment @roleAssignmentParams
# Export the service principal App ID
$sp.AppId
# Get the Tenant ID
(Get-AzTenant).Id
Replace <servicePrincipalName>
and <keyVaultId>
with the appropriate value.
Note down the App ID, Tenant ID, and the password you entered. You need them in the next section. You also need the full path of the certificate file, which you can find in the output of the Export_PfxCertificate
cmdlet.
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
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>"
$env:AZURE_TENANT_ID="<active_directory_tenant_id>"
$env:AZURE_CLIENT_ID="<service_principal_appid>"
$env:AZURE_CLIENT_SECRET="<service_principal_password>"
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>"
$env:AZURE_TENANT_ID="<active_directory_tenant_id>"
$env:AZURE_CLIENT_ID="<service_principal_appid>"
$env:AZURE_CLIENT_CERTIFICATE_PATH="<azure_client_certificate_path>"
$env:AZURE_CLIENT_CERTIFICATE_PASSWORD="<azure_client_certificate_password>"
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)
}
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.$env: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
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.
Remove-AzResourceGroup -Name go-on-azure -Force
The -Force
argument tells the cmdlet 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:
Remove-AzKeyVault -Name '<keyVaultName>' -Location eastus -InRemovedState -Force
Replace <keyVaultName>
with the name of your key vault.
Finally, you should remove the app registration and service principal.
Remove-AzADApplication -DisplayName <servicePrincipalName>
Replace <servicePrincipalName>
with the name you used for your service principal.
[!div class="nextstepaction"] Learn more about using the Azure SDK for Go