Skip to content

Getting started

By the end of this you will have one Azure identity resolution feeding two service clients.

go get gitlab.com/phpboyscout/go/azureclient

1. Build a source

package main

import (
    "context"
    "fmt"

    "gitlab.com/phpboyscout/go/azureclient"
)

func main() {
    src := azureclient.Ambient()

    fmt.Println("source built; nothing resolved yet")

    cred, err := src.AzureCredential(context.Background())
    if err != nil {
        panic(err)
    }

    fmt.Printf("resolved: %T\n", cred)
}

Ambient returns immediately and performs no I/O. DefaultAzureCredential is constructed on the first AzureCredential call — which is what lets you build a source in a constructor with no context to hand.

2. Point it at a tenant

In a multi-tenant setting the chain needs telling which directory to authenticate against:

src := azureclient.Ambient(azureclient.WithTenantID("00000000-0000-0000-0000-000000000000"))

For anything the option does not cover, WithCredentialOptions passes azidentity.DefaultAzureCredentialOptions straight through.

3. Inject a credential you already have

If your process resolves Azure identity for its own reasons — a workload identity, a specific client secret — inject it rather than resolving twice:

cred, err := azidentity.NewClientSecretCredential(tenant, clientID, secret, nil)
if err != nil {
    return err
}

src, err := azureclient.FromCredential(cred)

That rung validates immediately and returns any error there and then, because there is nothing to defer.

Pass it a nil credential and it refuses:

no Azure credential supplied; pass one to FromCredential, or use Ambient to resolve the identity chain

4. Failures are not remembered

Ask when the chain cannot resolve, and you get an error. Fix the environment, ask again, and it succeeds — no restart, no cached failure. That behaviour comes from go/clientlifecycle, the state machine every provider module here shares.

Next