pkg/armhelpers/tenantid.go (41 lines of code) (raw):
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
package armhelpers
import (
"context"
"net/http"
"regexp"
subscriptions "github.com/Azure/azure-sdk-for-go/profile/p20200901/resourcemanager/resources/armsubscriptions"
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/arm"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/fake"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
)
// GetTenantID figures out the AAD tenant ID of the subscription by making an
// unauthenticated request to the Get Subscription Details endpoint and parses
// the value from WWW-Authenticate header.
func GetTenantID(subscriptionID string, cloud cloud.Configuration) (string, error) {
const hdrKey = "WWW-Authenticate"
log.Debugf("Resolving tenantID for subscriptionID: %s", subscriptionID)
c, _ := subscriptions.NewClient(&fake.TokenCredential{}, &arm.ClientOptions{
ClientOptions: azcore.ClientOptions{
Cloud: cloud,
},
})
// we expect this request to fail (err != nil), but we are only interested
// in headers, so surface the error if the Response is not present (i.e.
// network error etc)
_, err := c.Get(context.Background(), subscriptionID, nil)
var responseErr *azcore.ResponseError
errors.As(err, &responseErr)
if responseErr.RawResponse == nil {
return "", errors.Wrap(err, "Request failed")
}
// Expecting 401 StatusUnauthorized here, just read the header
if responseErr.StatusCode != http.StatusUnauthorized {
return "", errors.Errorf("Unexpected response from Get Subscription: %v", responseErr.StatusCode)
}
hdr := responseErr.RawResponse.Header.Get(hdrKey)
if hdr == "" {
return "", errors.Errorf("Header %v not found in Get Subscription response", hdrKey)
}
// Example value for hdr:
// Bearer authorization_uri="https://login.windows.net/996fe9d1-6171-40aa-945b-4c64b63bf655", error="invalid_token", error_description="The authentication failed because of missing 'Authorization' header."
r := regexp.MustCompile(`authorization_uri=".*/([0-9a-f\-]+)"`)
m := r.FindStringSubmatch(hdr)
if m == nil {
return "", errors.Errorf("Could not find the tenant ID in header: %s %q", hdrKey, hdr)
}
return m[1], nil
}