packer-cn/builder/azure/common/client/tokenprovider_cli.go

100 lines
2.8 KiB
Go

package client
import (
"context"
"errors"
"fmt"
"github.com/Azure/go-autorest/autorest/adal"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/azure/cli"
)
// for managed identity auth
type cliOAuthTokenProvider struct {
env azure.Environment
say func(string)
tenantID string
}
func NewCliOAuthTokenProvider(env azure.Environment, say func(string), tenantID string) oAuthTokenProvider {
return &cliOAuthTokenProvider{
env: env,
say: say,
tenantID: tenantID,
}
}
func (tp *cliOAuthTokenProvider) getServicePrincipalToken() (*adal.ServicePrincipalToken, error) {
return tp.getServicePrincipalTokenWithResource(tp.env.ResourceManagerEndpoint)
}
func (tp *cliOAuthTokenProvider) getServicePrincipalTokenWithResource(resource string) (*adal.ServicePrincipalToken, error) {
token, err := cli.GetTokenFromCLI(resource)
if err != nil {
tp.say(fmt.Sprintf("unable to get token from azure cli: %v", err))
return nil, err
}
oAuthConfig, err := adal.NewOAuthConfig(resource, tp.tenantID)
if err != nil {
tp.say(fmt.Sprintf("unable to generate OAuth Config: %v", err))
return nil, err
}
adalToken, err := token.ToADALToken()
if err != nil {
tp.say(fmt.Sprintf("unable to get ADAL Token from azure cli token: %v", err))
return nil, err
}
spt, err := adal.NewServicePrincipalTokenFromManualToken(*oAuthConfig, clientIDs[tp.env.Name], resource, adalToken)
if err != nil {
tp.say(fmt.Sprintf("unable to get service principal token from adal token: %v", err))
return nil, err
}
// Custom refresh function to make it possible to use Azure CLI to refresh tokens.
// Inspired by HashiCorps go-azure-helpers: https://github.com/hashicorp/go-azure-helpers/blob/373622ce2effb0cf299051ea019cb657f357a4d8/authentication/auth_method_azure_cli_token.go#L96-L109
var customRefreshFunc adal.TokenRefresh = func(ctx context.Context, resource string) (*adal.Token, error) {
token, err := cli.GetTokenFromCLI(resource)
if err != nil {
tp.say(fmt.Sprintf("token refresh - unable to get token from azure cli: %v", err))
return nil, err
}
adalToken, err := token.ToADALToken()
if err != nil {
tp.say(fmt.Sprintf("token refresh - unable to get ADAL Token from azure cli token: %v", err))
return nil, err
}
return &adalToken, nil
}
spt.SetCustomRefreshFunc(customRefreshFunc)
return spt, nil
}
// getIDsFromAzureCLI returns the TenantID and SubscriptionID from an active Azure CLI login session
func getIDsFromAzureCLI() (string, string, error) {
profilePath, err := cli.ProfilePath()
if err != nil {
return "", "", err
}
profile, err := cli.LoadProfile(profilePath)
if err != nil {
return "", "", err
}
for _, p := range profile.Subscriptions {
if p.IsDefault {
return p.TenantID, p.ID, nil
}
}
return "", "", errors.New("Unable to find default subscription")
}