Files
lazysecrets/internal/provider/azure/account_test.go
T
kebandClaude Opus 5.5 3913989cd1
CI / Checks (pull_request) Successful in 24s
PR title / Conventional title (pull_request) Successful in 1s
feat: tenant name and tenant ID on lines of their own
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-11 10:27:19 +02:00

115 lines
3.7 KiB
Go

package azure
import (
"context"
"errors"
"io"
"net/http"
"slices"
"strings"
"testing"
"time"
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
"git.kebcloud.no/keb/lazysecrets/internal/provider"
)
func TestAccount(t *testing.T) {
claims := map[string]any{
"name": "Alice Example", "oid": "11111111-2222-3333-4444-555555555555",
"amr": []any{"pwd", "mfa"},
"wids": []any{"62e90394-69f5-4237-9190-012177145e10", memberRole, "aaaaaaaa-0000-0000-0000-000000000000"},
}
p := &Provider{account: &accountDetails{
account: account{user: "alice@contoso.com", tenant: "t1", tenantName: "Contoso", subscriptions: 3, defaultSub: "platform"},
claims: func() map[string]any { return claims },
}}
a, ok := p.Account()
if !ok {
t.Fatal("no account")
}
got := map[string]string{}
for _, f := range a.Fields {
got[f.Label] = f.Value
}
want := map[string]string{
"name": "Alice Example", "user": "alice@contoso.com", "tenant": "Contoso", "tenant ID": "t1",
"object ID": "11111111-2222-3333-4444-555555555555", "sign-in": "MFA · password",
"roles": "Global Administrator, role aaaaaaaa", "subs": "3 · default platform",
}
for k, v := range want {
if got[k] != v {
t.Errorf("%s = %q, want %q", k, got[k], v)
}
}
if len(got) != len(want) {
t.Errorf("fields %v", got)
}
if a.Copy != claims["oid"] || a.CopyLabel != "object ID" {
t.Errorf("copy %q %q", a.Copy, a.CopyLabel)
}
// Before any token: what az's list says.
claims = nil
a, _ = p.Account()
if len(a.Fields) != 4 || a.Copy != "" {
t.Errorf("without a token: %+v", a)
}
if _, ok := (&Provider{}).Account(); ok {
t.Error("a service principal from AZURE_* has no account details")
}
var _ provider.Accounts = p
}
func TestSignInMethods(t *testing.T) {
for want, amr := range map[string][]any{
"MFA · password": {"pwd", "mfa"},
"MFA · Windows Hello or certificate": {"rsa", "ngcmfa"},
"no MFA · password": {"pwd"},
"": nil,
} {
if got := signInMethods(amr); got != want {
t.Errorf("%v: %q, want %q", amr, got, want)
}
}
}
type staticToken struct{}
func (staticToken) GetToken(context.Context, policy.TokenRequestOptions) (azcore.AccessToken, error) {
return azcore.AccessToken{Token: "tok", ExpiresOn: time.Now().Add(time.Hour)}, nil
}
type graphPages map[string]string // by URL
func (g graphPages) RoundTrip(r *http.Request) (*http.Response, error) {
body, ok := g[r.URL.String()]
if !ok || r.Header.Get("Authorization") != "Bearer tok" {
return &http.Response{StatusCode: 404, Status: "404 Not Found", Body: io.NopCloser(strings.NewReader(`{}`))}, nil
}
return &http.Response{StatusCode: 200, Status: "200 OK", Body: io.NopCloser(strings.NewReader(body))}, nil
}
func TestGroups(t *testing.T) {
next := "https://graph.microsoft.com/v1.0/next"
p := &Provider{
cred: staticToken{},
account: &accountDetails{account: account{user: "alice@contoso.com"}},
graphClient: &http.Client{Transport: graphPages{
graphGroups: `{"value":[{"@odata.type":"#microsoft.graph.group","displayName":"vault readers"},
{"@odata.type":"#microsoft.graph.directoryRole","displayName":"Global Reader"}],"@odata.nextLink":"` + next + `"}`,
next: `{"value":[{"@odata.type":"#microsoft.graph.group","displayName":"Platform team"}]}`,
}},
}
got, err := p.Groups(context.Background())
if err != nil || !slices.Equal(got, []string{"Platform team", "vault readers"}) {
t.Errorf("groups %q, %v", got, err)
}
p.account.cloud = "AzureChinaCloud"
if _, err := p.Groups(context.Background()); !errors.Is(err, provider.ErrUnsupported) {
t.Errorf("other cloud: %v", err)
}
}