Blame vendor/github.com/Azure/go-autorest/autorest/azure/auth/auth.go

Packit 63bb0d
package auth
Packit 63bb0d
Packit 63bb0d
// Copyright 2017 Microsoft Corporation
Packit 63bb0d
//
Packit 63bb0d
//  Licensed under the Apache License, Version 2.0 (the "License");
Packit 63bb0d
//  you may not use this file except in compliance with the License.
Packit 63bb0d
//  You may obtain a copy of the License at
Packit 63bb0d
//
Packit 63bb0d
//      http://www.apache.org/licenses/LICENSE-2.0
Packit 63bb0d
//
Packit 63bb0d
//  Unless required by applicable law or agreed to in writing, software
Packit 63bb0d
//  distributed under the License is distributed on an "AS IS" BASIS,
Packit 63bb0d
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit 63bb0d
//  See the License for the specific language governing permissions and
Packit 63bb0d
//  limitations under the License.
Packit 63bb0d
Packit 63bb0d
import (
Packit 63bb0d
	"bytes"
Packit 63bb0d
	"crypto/rsa"
Packit 63bb0d
	"crypto/x509"
Packit 63bb0d
	"encoding/binary"
Packit 63bb0d
	"encoding/json"
Packit 63bb0d
	"errors"
Packit 63bb0d
	"fmt"
Packit 63bb0d
	"io/ioutil"
Packit 63bb0d
	"log"
Packit 63bb0d
	"os"
Packit 63bb0d
	"strings"
Packit 63bb0d
	"unicode/utf16"
Packit 63bb0d
Packit 63bb0d
	"github.com/Azure/go-autorest/autorest"
Packit 63bb0d
	"github.com/Azure/go-autorest/autorest/adal"
Packit 63bb0d
	"github.com/Azure/go-autorest/autorest/azure"
Packit 63bb0d
	"github.com/Azure/go-autorest/autorest/azure/cli"
Packit 63bb0d
	"github.com/dimchansky/utfbom"
Packit 63bb0d
	"golang.org/x/crypto/pkcs12"
Packit 63bb0d
)
Packit 63bb0d
Packit 63bb0d
// The possible keys in the Values map.
Packit 63bb0d
const (
Packit 63bb0d
	SubscriptionID          = "AZURE_SUBSCRIPTION_ID"
Packit 63bb0d
	TenantID                = "AZURE_TENANT_ID"
Packit 63bb0d
	AuxiliaryTenantIDs      = "AZURE_AUXILIARY_TENANT_IDS"
Packit 63bb0d
	ClientID                = "AZURE_CLIENT_ID"
Packit 63bb0d
	ClientSecret            = "AZURE_CLIENT_SECRET"
Packit 63bb0d
	CertificatePath         = "AZURE_CERTIFICATE_PATH"
Packit 63bb0d
	CertificatePassword     = "AZURE_CERTIFICATE_PASSWORD"
Packit 63bb0d
	Username                = "AZURE_USERNAME"
Packit 63bb0d
	Password                = "AZURE_PASSWORD"
Packit 63bb0d
	EnvironmentName         = "AZURE_ENVIRONMENT"
Packit 63bb0d
	Resource                = "AZURE_AD_RESOURCE"
Packit 63bb0d
	ActiveDirectoryEndpoint = "ActiveDirectoryEndpoint"
Packit 63bb0d
	ResourceManagerEndpoint = "ResourceManagerEndpoint"
Packit 63bb0d
	GraphResourceID         = "GraphResourceID"
Packit 63bb0d
	SQLManagementEndpoint   = "SQLManagementEndpoint"
Packit 63bb0d
	GalleryEndpoint         = "GalleryEndpoint"
Packit 63bb0d
	ManagementEndpoint      = "ManagementEndpoint"
Packit 63bb0d
)
Packit 63bb0d
Packit 63bb0d
// NewAuthorizerFromEnvironment creates an Authorizer configured from environment variables in the order:
Packit 63bb0d
// 1. Client credentials
Packit 63bb0d
// 2. Client certificate
Packit 63bb0d
// 3. Username password
Packit 63bb0d
// 4. MSI
Packit 63bb0d
func NewAuthorizerFromEnvironment() (autorest.Authorizer, error) {
Packit 63bb0d
	settings, err := GetSettingsFromEnvironment()
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return nil, err
Packit 63bb0d
	}
Packit 63bb0d
	return settings.GetAuthorizer()
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// NewAuthorizerFromEnvironmentWithResource creates an Authorizer configured from environment variables in the order:
Packit 63bb0d
// 1. Client credentials
Packit 63bb0d
// 2. Client certificate
Packit 63bb0d
// 3. Username password
Packit 63bb0d
// 4. MSI
Packit 63bb0d
func NewAuthorizerFromEnvironmentWithResource(resource string) (autorest.Authorizer, error) {
Packit 63bb0d
	settings, err := GetSettingsFromEnvironment()
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return nil, err
Packit 63bb0d
	}
Packit 63bb0d
	settings.Values[Resource] = resource
Packit 63bb0d
	return settings.GetAuthorizer()
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// EnvironmentSettings contains the available authentication settings.
Packit 63bb0d
type EnvironmentSettings struct {
Packit 63bb0d
	Values      map[string]string
Packit 63bb0d
	Environment azure.Environment
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// GetSettingsFromEnvironment returns the available authentication settings from the environment.
Packit 63bb0d
func GetSettingsFromEnvironment() (s EnvironmentSettings, err error) {
Packit 63bb0d
	s = EnvironmentSettings{
Packit 63bb0d
		Values: map[string]string{},
Packit 63bb0d
	}
Packit 63bb0d
	s.setValue(SubscriptionID)
Packit 63bb0d
	s.setValue(TenantID)
Packit 63bb0d
	s.setValue(AuxiliaryTenantIDs)
Packit 63bb0d
	s.setValue(ClientID)
Packit 63bb0d
	s.setValue(ClientSecret)
Packit 63bb0d
	s.setValue(CertificatePath)
Packit 63bb0d
	s.setValue(CertificatePassword)
Packit 63bb0d
	s.setValue(Username)
Packit 63bb0d
	s.setValue(Password)
Packit 63bb0d
	s.setValue(EnvironmentName)
Packit 63bb0d
	s.setValue(Resource)
Packit 63bb0d
	if v := s.Values[EnvironmentName]; v == "" {
Packit 63bb0d
		s.Environment = azure.PublicCloud
Packit 63bb0d
	} else {
Packit 63bb0d
		s.Environment, err = azure.EnvironmentFromName(v)
Packit 63bb0d
	}
Packit 63bb0d
	if s.Values[Resource] == "" {
Packit 63bb0d
		s.Values[Resource] = s.Environment.ResourceManagerEndpoint
Packit 63bb0d
	}
Packit 63bb0d
	return
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// GetSubscriptionID returns the available subscription ID or an empty string.
Packit 63bb0d
func (settings EnvironmentSettings) GetSubscriptionID() string {
Packit 63bb0d
	return settings.Values[SubscriptionID]
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// adds the specified environment variable value to the Values map if it exists
Packit 63bb0d
func (settings EnvironmentSettings) setValue(key string) {
Packit 63bb0d
	if v := os.Getenv(key); v != "" {
Packit 63bb0d
		settings.Values[key] = v
Packit 63bb0d
	}
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// helper to return client and tenant IDs
Packit 63bb0d
func (settings EnvironmentSettings) getClientAndTenant() (string, string) {
Packit 63bb0d
	clientID := settings.Values[ClientID]
Packit 63bb0d
	tenantID := settings.Values[TenantID]
Packit 63bb0d
	return clientID, tenantID
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// GetClientCredentials creates a config object from the available client credentials.
Packit 63bb0d
// An error is returned if no client credentials are available.
Packit 63bb0d
func (settings EnvironmentSettings) GetClientCredentials() (ClientCredentialsConfig, error) {
Packit 63bb0d
	secret := settings.Values[ClientSecret]
Packit 63bb0d
	if secret == "" {
Packit 63bb0d
		return ClientCredentialsConfig{}, errors.New("missing client secret")
Packit 63bb0d
	}
Packit 63bb0d
	clientID, tenantID := settings.getClientAndTenant()
Packit 63bb0d
	config := NewClientCredentialsConfig(clientID, secret, tenantID)
Packit 63bb0d
	config.AADEndpoint = settings.Environment.ActiveDirectoryEndpoint
Packit 63bb0d
	config.Resource = settings.Values[Resource]
Packit 63bb0d
	if auxTenants, ok := settings.Values[AuxiliaryTenantIDs]; ok {
Packit 63bb0d
		config.AuxTenants = strings.Split(auxTenants, ";")
Packit 63bb0d
		for i := range config.AuxTenants {
Packit 63bb0d
			config.AuxTenants[i] = strings.TrimSpace(config.AuxTenants[i])
Packit 63bb0d
		}
Packit 63bb0d
	}
Packit 63bb0d
	return config, nil
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// GetClientCertificate creates a config object from the available certificate credentials.
Packit 63bb0d
// An error is returned if no certificate credentials are available.
Packit 63bb0d
func (settings EnvironmentSettings) GetClientCertificate() (ClientCertificateConfig, error) {
Packit 63bb0d
	certPath := settings.Values[CertificatePath]
Packit 63bb0d
	if certPath == "" {
Packit 63bb0d
		return ClientCertificateConfig{}, errors.New("missing certificate path")
Packit 63bb0d
	}
Packit 63bb0d
	certPwd := settings.Values[CertificatePassword]
Packit 63bb0d
	clientID, tenantID := settings.getClientAndTenant()
Packit 63bb0d
	config := NewClientCertificateConfig(certPath, certPwd, clientID, tenantID)
Packit 63bb0d
	config.AADEndpoint = settings.Environment.ActiveDirectoryEndpoint
Packit 63bb0d
	config.Resource = settings.Values[Resource]
Packit 63bb0d
	return config, nil
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// GetUsernamePassword creates a config object from the available username/password credentials.
Packit 63bb0d
// An error is returned if no username/password credentials are available.
Packit 63bb0d
func (settings EnvironmentSettings) GetUsernamePassword() (UsernamePasswordConfig, error) {
Packit 63bb0d
	username := settings.Values[Username]
Packit 63bb0d
	password := settings.Values[Password]
Packit 63bb0d
	if username == "" || password == "" {
Packit 63bb0d
		return UsernamePasswordConfig{}, errors.New("missing username/password")
Packit 63bb0d
	}
Packit 63bb0d
	clientID, tenantID := settings.getClientAndTenant()
Packit 63bb0d
	config := NewUsernamePasswordConfig(username, password, clientID, tenantID)
Packit 63bb0d
	config.AADEndpoint = settings.Environment.ActiveDirectoryEndpoint
Packit 63bb0d
	config.Resource = settings.Values[Resource]
Packit 63bb0d
	return config, nil
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// GetMSI creates a MSI config object from the available client ID.
Packit 63bb0d
func (settings EnvironmentSettings) GetMSI() MSIConfig {
Packit 63bb0d
	config := NewMSIConfig()
Packit 63bb0d
	config.Resource = settings.Values[Resource]
Packit 63bb0d
	config.ClientID = settings.Values[ClientID]
Packit 63bb0d
	return config
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// GetDeviceFlow creates a device-flow config object from the available client and tenant IDs.
Packit 63bb0d
func (settings EnvironmentSettings) GetDeviceFlow() DeviceFlowConfig {
Packit 63bb0d
	clientID, tenantID := settings.getClientAndTenant()
Packit 63bb0d
	config := NewDeviceFlowConfig(clientID, tenantID)
Packit 63bb0d
	config.AADEndpoint = settings.Environment.ActiveDirectoryEndpoint
Packit 63bb0d
	config.Resource = settings.Values[Resource]
Packit 63bb0d
	return config
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// GetAuthorizer creates an Authorizer configured from environment variables in the order:
Packit 63bb0d
// 1. Client credentials
Packit 63bb0d
// 2. Client certificate
Packit 63bb0d
// 3. Username password
Packit 63bb0d
// 4. MSI
Packit 63bb0d
func (settings EnvironmentSettings) GetAuthorizer() (autorest.Authorizer, error) {
Packit 63bb0d
	//1.Client Credentials
Packit 63bb0d
	if c, e := settings.GetClientCredentials(); e == nil {
Packit 63bb0d
		return c.Authorizer()
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	//2. Client Certificate
Packit 63bb0d
	if c, e := settings.GetClientCertificate(); e == nil {
Packit 63bb0d
		return c.Authorizer()
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	//3. Username Password
Packit 63bb0d
	if c, e := settings.GetUsernamePassword(); e == nil {
Packit 63bb0d
		return c.Authorizer()
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	// 4. MSI
Packit 63bb0d
	return settings.GetMSI().Authorizer()
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// NewAuthorizerFromFile creates an Authorizer configured from a configuration file in the following order.
Packit 63bb0d
// 1. Client credentials
Packit 63bb0d
// 2. Client certificate
Packit 63bb0d
func NewAuthorizerFromFile(baseURI string) (autorest.Authorizer, error) {
Packit 63bb0d
	settings, err := GetSettingsFromFile()
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return nil, err
Packit 63bb0d
	}
Packit 63bb0d
	if a, err := settings.ClientCredentialsAuthorizer(baseURI); err == nil {
Packit 63bb0d
		return a, err
Packit 63bb0d
	}
Packit 63bb0d
	if a, err := settings.ClientCertificateAuthorizer(baseURI); err == nil {
Packit 63bb0d
		return a, err
Packit 63bb0d
	}
Packit 63bb0d
	return nil, errors.New("auth file missing client and certificate credentials")
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// NewAuthorizerFromFileWithResource creates an Authorizer configured from a configuration file in the following order.
Packit 63bb0d
// 1. Client credentials
Packit 63bb0d
// 2. Client certificate
Packit 63bb0d
func NewAuthorizerFromFileWithResource(resource string) (autorest.Authorizer, error) {
Packit 63bb0d
	s, err := GetSettingsFromFile()
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return nil, err
Packit 63bb0d
	}
Packit 63bb0d
	if a, err := s.ClientCredentialsAuthorizerWithResource(resource); err == nil {
Packit 63bb0d
		return a, err
Packit 63bb0d
	}
Packit 63bb0d
	if a, err := s.ClientCertificateAuthorizerWithResource(resource); err == nil {
Packit 63bb0d
		return a, err
Packit 63bb0d
	}
Packit 63bb0d
	return nil, errors.New("auth file missing client and certificate credentials")
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// NewAuthorizerFromCLI creates an Authorizer configured from Azure CLI 2.0 for local development scenarios.
Packit 63bb0d
func NewAuthorizerFromCLI() (autorest.Authorizer, error) {
Packit 63bb0d
	settings, err := GetSettingsFromEnvironment()
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return nil, err
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	if settings.Values[Resource] == "" {
Packit 63bb0d
		settings.Values[Resource] = settings.Environment.ResourceManagerEndpoint
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	return NewAuthorizerFromCLIWithResource(settings.Values[Resource])
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// NewAuthorizerFromCLIWithResource creates an Authorizer configured from Azure CLI 2.0 for local development scenarios.
Packit 63bb0d
func NewAuthorizerFromCLIWithResource(resource string) (autorest.Authorizer, error) {
Packit 63bb0d
	token, err := cli.GetTokenFromCLI(resource)
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return nil, err
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	adalToken, err := token.ToADALToken()
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return nil, err
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	return autorest.NewBearerAuthorizer(&adalToken), nil
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// GetSettingsFromFile returns the available authentication settings from an Azure CLI authentication file.
Packit 63bb0d
func GetSettingsFromFile() (FileSettings, error) {
Packit 63bb0d
	s := FileSettings{}
Packit 63bb0d
	fileLocation := os.Getenv("AZURE_AUTH_LOCATION")
Packit 63bb0d
	if fileLocation == "" {
Packit 63bb0d
		return s, errors.New("environment variable AZURE_AUTH_LOCATION is not set")
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	contents, err := ioutil.ReadFile(fileLocation)
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return s, err
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	// Auth file might be encoded
Packit 63bb0d
	decoded, err := decode(contents)
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return s, err
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	authFile := map[string]interface{}{}
Packit 63bb0d
	err = json.Unmarshal(decoded, &authFile)
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return s, err
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	s.Values = map[string]string{}
Packit 63bb0d
	s.setKeyValue(ClientID, authFile["clientId"])
Packit 63bb0d
	s.setKeyValue(ClientSecret, authFile["clientSecret"])
Packit 63bb0d
	s.setKeyValue(CertificatePath, authFile["clientCertificate"])
Packit 63bb0d
	s.setKeyValue(CertificatePassword, authFile["clientCertificatePassword"])
Packit 63bb0d
	s.setKeyValue(SubscriptionID, authFile["subscriptionId"])
Packit 63bb0d
	s.setKeyValue(TenantID, authFile["tenantId"])
Packit 63bb0d
	s.setKeyValue(ActiveDirectoryEndpoint, authFile["activeDirectoryEndpointUrl"])
Packit 63bb0d
	s.setKeyValue(ResourceManagerEndpoint, authFile["resourceManagerEndpointUrl"])
Packit 63bb0d
	s.setKeyValue(GraphResourceID, authFile["activeDirectoryGraphResourceId"])
Packit 63bb0d
	s.setKeyValue(SQLManagementEndpoint, authFile["sqlManagementEndpointUrl"])
Packit 63bb0d
	s.setKeyValue(GalleryEndpoint, authFile["galleryEndpointUrl"])
Packit 63bb0d
	s.setKeyValue(ManagementEndpoint, authFile["managementEndpointUrl"])
Packit 63bb0d
	return s, nil
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// FileSettings contains the available authentication settings.
Packit 63bb0d
type FileSettings struct {
Packit 63bb0d
	Values map[string]string
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// GetSubscriptionID returns the available subscription ID or an empty string.
Packit 63bb0d
func (settings FileSettings) GetSubscriptionID() string {
Packit 63bb0d
	return settings.Values[SubscriptionID]
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// adds the specified value to the Values map if it isn't nil
Packit 63bb0d
func (settings FileSettings) setKeyValue(key string, val interface{}) {
Packit 63bb0d
	if val != nil {
Packit 63bb0d
		settings.Values[key] = val.(string)
Packit 63bb0d
	}
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// returns the specified AAD endpoint or the public cloud endpoint if unspecified
Packit 63bb0d
func (settings FileSettings) getAADEndpoint() string {
Packit 63bb0d
	if v, ok := settings.Values[ActiveDirectoryEndpoint]; ok {
Packit 63bb0d
		return v
Packit 63bb0d
	}
Packit 63bb0d
	return azure.PublicCloud.ActiveDirectoryEndpoint
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// ServicePrincipalTokenFromClientCredentials creates a ServicePrincipalToken from the available client credentials.
Packit 63bb0d
func (settings FileSettings) ServicePrincipalTokenFromClientCredentials(baseURI string) (*adal.ServicePrincipalToken, error) {
Packit 63bb0d
	resource, err := settings.getResourceForToken(baseURI)
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return nil, err
Packit 63bb0d
	}
Packit 63bb0d
	return settings.ServicePrincipalTokenFromClientCredentialsWithResource(resource)
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// ClientCredentialsAuthorizer creates an authorizer from the available client credentials.
Packit 63bb0d
func (settings FileSettings) ClientCredentialsAuthorizer(baseURI string) (autorest.Authorizer, error) {
Packit 63bb0d
	resource, err := settings.getResourceForToken(baseURI)
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return nil, err
Packit 63bb0d
	}
Packit 63bb0d
	return settings.ClientCredentialsAuthorizerWithResource(resource)
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// ServicePrincipalTokenFromClientCredentialsWithResource creates a ServicePrincipalToken
Packit 63bb0d
// from the available client credentials and the specified resource.
Packit 63bb0d
func (settings FileSettings) ServicePrincipalTokenFromClientCredentialsWithResource(resource string) (*adal.ServicePrincipalToken, error) {
Packit 63bb0d
	if _, ok := settings.Values[ClientSecret]; !ok {
Packit 63bb0d
		return nil, errors.New("missing client secret")
Packit 63bb0d
	}
Packit 63bb0d
	config, err := adal.NewOAuthConfig(settings.getAADEndpoint(), settings.Values[TenantID])
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return nil, err
Packit 63bb0d
	}
Packit 63bb0d
	return adal.NewServicePrincipalToken(*config, settings.Values[ClientID], settings.Values[ClientSecret], resource)
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (settings FileSettings) clientCertificateConfigWithResource(resource string) (ClientCertificateConfig, error) {
Packit 63bb0d
	if _, ok := settings.Values[CertificatePath]; !ok {
Packit 63bb0d
		return ClientCertificateConfig{}, errors.New("missing certificate path")
Packit 63bb0d
	}
Packit 63bb0d
	cfg := NewClientCertificateConfig(settings.Values[CertificatePath], settings.Values[CertificatePassword], settings.Values[ClientID], settings.Values[TenantID])
Packit 63bb0d
	cfg.AADEndpoint = settings.getAADEndpoint()
Packit 63bb0d
	cfg.Resource = resource
Packit 63bb0d
	return cfg, nil
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// ClientCredentialsAuthorizerWithResource creates an authorizer from the available client credentials and the specified resource.
Packit 63bb0d
func (settings FileSettings) ClientCredentialsAuthorizerWithResource(resource string) (autorest.Authorizer, error) {
Packit 63bb0d
	spToken, err := settings.ServicePrincipalTokenFromClientCredentialsWithResource(resource)
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return nil, err
Packit 63bb0d
	}
Packit 63bb0d
	return autorest.NewBearerAuthorizer(spToken), nil
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// ServicePrincipalTokenFromClientCertificate creates a ServicePrincipalToken from the available certificate credentials.
Packit 63bb0d
func (settings FileSettings) ServicePrincipalTokenFromClientCertificate(baseURI string) (*adal.ServicePrincipalToken, error) {
Packit 63bb0d
	resource, err := settings.getResourceForToken(baseURI)
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return nil, err
Packit 63bb0d
	}
Packit 63bb0d
	return settings.ServicePrincipalTokenFromClientCertificateWithResource(resource)
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// ClientCertificateAuthorizer creates an authorizer from the available certificate credentials.
Packit 63bb0d
func (settings FileSettings) ClientCertificateAuthorizer(baseURI string) (autorest.Authorizer, error) {
Packit 63bb0d
	resource, err := settings.getResourceForToken(baseURI)
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return nil, err
Packit 63bb0d
	}
Packit 63bb0d
	return settings.ClientCertificateAuthorizerWithResource(resource)
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// ServicePrincipalTokenFromClientCertificateWithResource creates a ServicePrincipalToken from the available certificate credentials.
Packit 63bb0d
func (settings FileSettings) ServicePrincipalTokenFromClientCertificateWithResource(resource string) (*adal.ServicePrincipalToken, error) {
Packit 63bb0d
	cfg, err := settings.clientCertificateConfigWithResource(resource)
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return nil, err
Packit 63bb0d
	}
Packit 63bb0d
	return cfg.ServicePrincipalToken()
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// ClientCertificateAuthorizerWithResource creates an authorizer from the available certificate credentials and the specified resource.
Packit 63bb0d
func (settings FileSettings) ClientCertificateAuthorizerWithResource(resource string) (autorest.Authorizer, error) {
Packit 63bb0d
	cfg, err := settings.clientCertificateConfigWithResource(resource)
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return nil, err
Packit 63bb0d
	}
Packit 63bb0d
	return cfg.Authorizer()
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func decode(b []byte) ([]byte, error) {
Packit 63bb0d
	reader, enc := utfbom.Skip(bytes.NewReader(b))
Packit 63bb0d
Packit 63bb0d
	switch enc {
Packit 63bb0d
	case utfbom.UTF16LittleEndian:
Packit 63bb0d
		u16 := make([]uint16, (len(b)/2)-1)
Packit 63bb0d
		err := binary.Read(reader, binary.LittleEndian, &u16)
Packit 63bb0d
		if err != nil {
Packit 63bb0d
			return nil, err
Packit 63bb0d
		}
Packit 63bb0d
		return []byte(string(utf16.Decode(u16))), nil
Packit 63bb0d
	case utfbom.UTF16BigEndian:
Packit 63bb0d
		u16 := make([]uint16, (len(b)/2)-1)
Packit 63bb0d
		err := binary.Read(reader, binary.BigEndian, &u16)
Packit 63bb0d
		if err != nil {
Packit 63bb0d
			return nil, err
Packit 63bb0d
		}
Packit 63bb0d
		return []byte(string(utf16.Decode(u16))), nil
Packit 63bb0d
	}
Packit 63bb0d
	return ioutil.ReadAll(reader)
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (settings FileSettings) getResourceForToken(baseURI string) (string, error) {
Packit 63bb0d
	// Compare dafault base URI from the SDK to the endpoints from the public cloud
Packit 63bb0d
	// Base URI and token resource are the same string. This func finds the authentication
Packit 63bb0d
	// file field that matches the SDK base URI. The SDK defines the public cloud
Packit 63bb0d
	// endpoint as its default base URI
Packit 63bb0d
	if !strings.HasSuffix(baseURI, "/") {
Packit 63bb0d
		baseURI += "/"
Packit 63bb0d
	}
Packit 63bb0d
	switch baseURI {
Packit 63bb0d
	case azure.PublicCloud.ServiceManagementEndpoint:
Packit 63bb0d
		return settings.Values[ManagementEndpoint], nil
Packit 63bb0d
	case azure.PublicCloud.ResourceManagerEndpoint:
Packit 63bb0d
		return settings.Values[ResourceManagerEndpoint], nil
Packit 63bb0d
	case azure.PublicCloud.ActiveDirectoryEndpoint:
Packit 63bb0d
		return settings.Values[ActiveDirectoryEndpoint], nil
Packit 63bb0d
	case azure.PublicCloud.GalleryEndpoint:
Packit 63bb0d
		return settings.Values[GalleryEndpoint], nil
Packit 63bb0d
	case azure.PublicCloud.GraphEndpoint:
Packit 63bb0d
		return settings.Values[GraphResourceID], nil
Packit 63bb0d
	}
Packit 63bb0d
	return "", fmt.Errorf("auth: base URI not found in endpoints")
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// NewClientCredentialsConfig creates an AuthorizerConfig object configured to obtain an Authorizer through Client Credentials.
Packit 63bb0d
// Defaults to Public Cloud and Resource Manager Endpoint.
Packit 63bb0d
func NewClientCredentialsConfig(clientID string, clientSecret string, tenantID string) ClientCredentialsConfig {
Packit 63bb0d
	return ClientCredentialsConfig{
Packit 63bb0d
		ClientID:     clientID,
Packit 63bb0d
		ClientSecret: clientSecret,
Packit 63bb0d
		TenantID:     tenantID,
Packit 63bb0d
		Resource:     azure.PublicCloud.ResourceManagerEndpoint,
Packit 63bb0d
		AADEndpoint:  azure.PublicCloud.ActiveDirectoryEndpoint,
Packit 63bb0d
	}
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// NewClientCertificateConfig creates a ClientCertificateConfig object configured to obtain an Authorizer through client certificate.
Packit 63bb0d
// Defaults to Public Cloud and Resource Manager Endpoint.
Packit 63bb0d
func NewClientCertificateConfig(certificatePath string, certificatePassword string, clientID string, tenantID string) ClientCertificateConfig {
Packit 63bb0d
	return ClientCertificateConfig{
Packit 63bb0d
		CertificatePath:     certificatePath,
Packit 63bb0d
		CertificatePassword: certificatePassword,
Packit 63bb0d
		ClientID:            clientID,
Packit 63bb0d
		TenantID:            tenantID,
Packit 63bb0d
		Resource:            azure.PublicCloud.ResourceManagerEndpoint,
Packit 63bb0d
		AADEndpoint:         azure.PublicCloud.ActiveDirectoryEndpoint,
Packit 63bb0d
	}
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// NewUsernamePasswordConfig creates an UsernamePasswordConfig object configured to obtain an Authorizer through username and password.
Packit 63bb0d
// Defaults to Public Cloud and Resource Manager Endpoint.
Packit 63bb0d
func NewUsernamePasswordConfig(username string, password string, clientID string, tenantID string) UsernamePasswordConfig {
Packit 63bb0d
	return UsernamePasswordConfig{
Packit 63bb0d
		Username:    username,
Packit 63bb0d
		Password:    password,
Packit 63bb0d
		ClientID:    clientID,
Packit 63bb0d
		TenantID:    tenantID,
Packit 63bb0d
		Resource:    azure.PublicCloud.ResourceManagerEndpoint,
Packit 63bb0d
		AADEndpoint: azure.PublicCloud.ActiveDirectoryEndpoint,
Packit 63bb0d
	}
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// NewMSIConfig creates an MSIConfig object configured to obtain an Authorizer through MSI.
Packit 63bb0d
func NewMSIConfig() MSIConfig {
Packit 63bb0d
	return MSIConfig{
Packit 63bb0d
		Resource: azure.PublicCloud.ResourceManagerEndpoint,
Packit 63bb0d
	}
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// NewDeviceFlowConfig creates a DeviceFlowConfig object configured to obtain an Authorizer through device flow.
Packit 63bb0d
// Defaults to Public Cloud and Resource Manager Endpoint.
Packit 63bb0d
func NewDeviceFlowConfig(clientID string, tenantID string) DeviceFlowConfig {
Packit 63bb0d
	return DeviceFlowConfig{
Packit 63bb0d
		ClientID:    clientID,
Packit 63bb0d
		TenantID:    tenantID,
Packit 63bb0d
		Resource:    azure.PublicCloud.ResourceManagerEndpoint,
Packit 63bb0d
		AADEndpoint: azure.PublicCloud.ActiveDirectoryEndpoint,
Packit 63bb0d
	}
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
//AuthorizerConfig provides an authorizer from the configuration provided.
Packit 63bb0d
type AuthorizerConfig interface {
Packit 63bb0d
	Authorizer() (autorest.Authorizer, error)
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// ClientCredentialsConfig provides the options to get a bearer authorizer from client credentials.
Packit 63bb0d
type ClientCredentialsConfig struct {
Packit 63bb0d
	ClientID     string
Packit 63bb0d
	ClientSecret string
Packit 63bb0d
	TenantID     string
Packit 63bb0d
	AuxTenants   []string
Packit 63bb0d
	AADEndpoint  string
Packit 63bb0d
	Resource     string
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// ServicePrincipalToken creates a ServicePrincipalToken from client credentials.
Packit 63bb0d
func (ccc ClientCredentialsConfig) ServicePrincipalToken() (*adal.ServicePrincipalToken, error) {
Packit 63bb0d
	oauthConfig, err := adal.NewOAuthConfig(ccc.AADEndpoint, ccc.TenantID)
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return nil, err
Packit 63bb0d
	}
Packit 63bb0d
	return adal.NewServicePrincipalToken(*oauthConfig, ccc.ClientID, ccc.ClientSecret, ccc.Resource)
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// MultiTenantServicePrincipalToken creates a MultiTenantServicePrincipalToken from client credentials.
Packit 63bb0d
func (ccc ClientCredentialsConfig) MultiTenantServicePrincipalToken() (*adal.MultiTenantServicePrincipalToken, error) {
Packit 63bb0d
	oauthConfig, err := adal.NewMultiTenantOAuthConfig(ccc.AADEndpoint, ccc.TenantID, ccc.AuxTenants, adal.OAuthOptions{})
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return nil, err
Packit 63bb0d
	}
Packit 63bb0d
	return adal.NewMultiTenantServicePrincipalToken(oauthConfig, ccc.ClientID, ccc.ClientSecret, ccc.Resource)
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// Authorizer gets the authorizer from client credentials.
Packit 63bb0d
func (ccc ClientCredentialsConfig) Authorizer() (autorest.Authorizer, error) {
Packit 63bb0d
	if len(ccc.AuxTenants) == 0 {
Packit 63bb0d
		spToken, err := ccc.ServicePrincipalToken()
Packit 63bb0d
		if err != nil {
Packit 63bb0d
			return nil, fmt.Errorf("failed to get SPT from client credentials: %v", err)
Packit 63bb0d
		}
Packit 63bb0d
		return autorest.NewBearerAuthorizer(spToken), nil
Packit 63bb0d
	}
Packit 63bb0d
	mtSPT, err := ccc.MultiTenantServicePrincipalToken()
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return nil, fmt.Errorf("failed to get multitenant SPT from client credentials: %v", err)
Packit 63bb0d
	}
Packit 63bb0d
	return autorest.NewMultiTenantServicePrincipalTokenAuthorizer(mtSPT), nil
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// ClientCertificateConfig provides the options to get a bearer authorizer from a client certificate.
Packit 63bb0d
type ClientCertificateConfig struct {
Packit 63bb0d
	ClientID            string
Packit 63bb0d
	CertificatePath     string
Packit 63bb0d
	CertificatePassword string
Packit 63bb0d
	TenantID            string
Packit 63bb0d
	AADEndpoint         string
Packit 63bb0d
	Resource            string
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// ServicePrincipalToken creates a ServicePrincipalToken from client certificate.
Packit 63bb0d
func (ccc ClientCertificateConfig) ServicePrincipalToken() (*adal.ServicePrincipalToken, error) {
Packit 63bb0d
	oauthConfig, err := adal.NewOAuthConfig(ccc.AADEndpoint, ccc.TenantID)
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return nil, err
Packit 63bb0d
	}
Packit 63bb0d
	certData, err := ioutil.ReadFile(ccc.CertificatePath)
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return nil, fmt.Errorf("failed to read the certificate file (%s): %v", ccc.CertificatePath, err)
Packit 63bb0d
	}
Packit 63bb0d
	certificate, rsaPrivateKey, err := decodePkcs12(certData, ccc.CertificatePassword)
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return nil, fmt.Errorf("failed to decode pkcs12 certificate while creating spt: %v", err)
Packit 63bb0d
	}
Packit 63bb0d
	return adal.NewServicePrincipalTokenFromCertificate(*oauthConfig, ccc.ClientID, certificate, rsaPrivateKey, ccc.Resource)
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// Authorizer gets an authorizer object from client certificate.
Packit 63bb0d
func (ccc ClientCertificateConfig) Authorizer() (autorest.Authorizer, error) {
Packit 63bb0d
	spToken, err := ccc.ServicePrincipalToken()
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return nil, fmt.Errorf("failed to get oauth token from certificate auth: %v", err)
Packit 63bb0d
	}
Packit 63bb0d
	return autorest.NewBearerAuthorizer(spToken), nil
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// DeviceFlowConfig provides the options to get a bearer authorizer using device flow authentication.
Packit 63bb0d
type DeviceFlowConfig struct {
Packit 63bb0d
	ClientID    string
Packit 63bb0d
	TenantID    string
Packit 63bb0d
	AADEndpoint string
Packit 63bb0d
	Resource    string
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// Authorizer gets the authorizer from device flow.
Packit 63bb0d
func (dfc DeviceFlowConfig) Authorizer() (autorest.Authorizer, error) {
Packit 63bb0d
	spToken, err := dfc.ServicePrincipalToken()
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return nil, fmt.Errorf("failed to get oauth token from device flow: %v", err)
Packit 63bb0d
	}
Packit 63bb0d
	return autorest.NewBearerAuthorizer(spToken), nil
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// ServicePrincipalToken gets the service principal token from device flow.
Packit 63bb0d
func (dfc DeviceFlowConfig) ServicePrincipalToken() (*adal.ServicePrincipalToken, error) {
Packit 63bb0d
	oauthConfig, err := adal.NewOAuthConfig(dfc.AADEndpoint, dfc.TenantID)
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return nil, err
Packit 63bb0d
	}
Packit 63bb0d
	oauthClient := &autorest.Client{}
Packit 63bb0d
	deviceCode, err := adal.InitiateDeviceAuth(oauthClient, *oauthConfig, dfc.ClientID, dfc.Resource)
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return nil, fmt.Errorf("failed to start device auth flow: %s", err)
Packit 63bb0d
	}
Packit 63bb0d
	log.Println(*deviceCode.Message)
Packit 63bb0d
	token, err := adal.WaitForUserCompletion(oauthClient, deviceCode)
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return nil, fmt.Errorf("failed to finish device auth flow: %s", err)
Packit 63bb0d
	}
Packit 63bb0d
	return adal.NewServicePrincipalTokenFromManualToken(*oauthConfig, dfc.ClientID, dfc.Resource, *token)
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func decodePkcs12(pkcs []byte, password string) (*x509.Certificate, *rsa.PrivateKey, error) {
Packit 63bb0d
	privateKey, certificate, err := pkcs12.Decode(pkcs, password)
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return nil, nil, err
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	rsaPrivateKey, isRsaKey := privateKey.(*rsa.PrivateKey)
Packit 63bb0d
	if !isRsaKey {
Packit 63bb0d
		return nil, nil, fmt.Errorf("PKCS#12 certificate must contain an RSA private key")
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	return certificate, rsaPrivateKey, nil
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// UsernamePasswordConfig provides the options to get a bearer authorizer from a username and a password.
Packit 63bb0d
type UsernamePasswordConfig struct {
Packit 63bb0d
	ClientID    string
Packit 63bb0d
	Username    string
Packit 63bb0d
	Password    string
Packit 63bb0d
	TenantID    string
Packit 63bb0d
	AADEndpoint string
Packit 63bb0d
	Resource    string
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// ServicePrincipalToken creates a ServicePrincipalToken from username and password.
Packit 63bb0d
func (ups UsernamePasswordConfig) ServicePrincipalToken() (*adal.ServicePrincipalToken, error) {
Packit 63bb0d
	oauthConfig, err := adal.NewOAuthConfig(ups.AADEndpoint, ups.TenantID)
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return nil, err
Packit 63bb0d
	}
Packit 63bb0d
	return adal.NewServicePrincipalTokenFromUsernamePassword(*oauthConfig, ups.ClientID, ups.Username, ups.Password, ups.Resource)
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// Authorizer gets the authorizer from a username and a password.
Packit 63bb0d
func (ups UsernamePasswordConfig) Authorizer() (autorest.Authorizer, error) {
Packit 63bb0d
	spToken, err := ups.ServicePrincipalToken()
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return nil, fmt.Errorf("failed to get oauth token from username and password auth: %v", err)
Packit 63bb0d
	}
Packit 63bb0d
	return autorest.NewBearerAuthorizer(spToken), nil
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// MSIConfig provides the options to get a bearer authorizer through MSI.
Packit 63bb0d
type MSIConfig struct {
Packit 63bb0d
	Resource string
Packit 63bb0d
	ClientID string
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// Authorizer gets the authorizer from MSI.
Packit 63bb0d
func (mc MSIConfig) Authorizer() (autorest.Authorizer, error) {
Packit 63bb0d
	msiEndpoint, err := adal.GetMSIEndpoint()
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return nil, err
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	var spToken *adal.ServicePrincipalToken
Packit 63bb0d
	if mc.ClientID == "" {
Packit 63bb0d
		spToken, err = adal.NewServicePrincipalTokenFromMSI(msiEndpoint, mc.Resource)
Packit 63bb0d
		if err != nil {
Packit 63bb0d
			return nil, fmt.Errorf("failed to get oauth token from MSI: %v", err)
Packit 63bb0d
		}
Packit 63bb0d
	} else {
Packit 63bb0d
		spToken, err = adal.NewServicePrincipalTokenFromMSIWithUserAssignedID(msiEndpoint, mc.Resource, mc.ClientID)
Packit 63bb0d
		if err != nil {
Packit 63bb0d
			return nil, fmt.Errorf("failed to get oauth token from MSI for user assigned identity: %v", err)
Packit 63bb0d
		}
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	return autorest.NewBearerAuthorizer(spToken), nil
Packit 63bb0d
}