terraform/vendor/github.com/hashicorp/go-azure-helpers/authentication/builder.go

115 lines
3.1 KiB
Go

package authentication
import (
"context"
"fmt"
"log"
)
var (
authenticatedObjectCache = ""
)
// Builder supports all of the possible Authentication values and feature toggles
// required to build a working Config for Authentication purposes.
type Builder struct {
// Core
ClientID string
SubscriptionID string
TenantID string
Environment string
// Auxiliary tenant IDs used for multi tenant auth
SupportsAuxiliaryTenants bool
AuxiliaryTenantIDs []string
// The custom Resource Manager Endpoint which should be used
// only applicable for Azure Stack at this time.
CustomResourceManagerEndpoint string
// Azure CLI Tokens Auth
SupportsAzureCliToken bool
// Managed Service Identity Auth
SupportsManagedServiceIdentity bool
MsiEndpoint string
// Service Principal (Client Cert) Auth
SupportsClientCertAuth bool
ClientCertPath string
ClientCertPassword string
// Service Principal (Client Secret) Auth
SupportsClientSecretAuth bool
ClientSecret string
ClientSecretDocsLink string
}
// Build takes the configuration from the Builder and builds up a validated Config
// for authenticating with Azure
func (b Builder) Build() (*Config, error) {
config := Config{
ClientID: b.ClientID,
SubscriptionID: b.SubscriptionID,
TenantID: b.TenantID,
AuxiliaryTenantIDs: b.AuxiliaryTenantIDs,
Environment: b.Environment,
CustomResourceManagerEndpoint: b.CustomResourceManagerEndpoint,
}
// NOTE: the ordering here is important
// since the Azure CLI Parsing should always be the last thing checked
supportedAuthenticationMethods := []authMethod{
servicePrincipalClientCertificateAuth{},
servicePrincipalClientSecretMultiTenantAuth{},
servicePrincipalClientSecretAuth{},
managedServiceIdentityAuth{},
azureCliTokenAuth{},
}
for _, method := range supportedAuthenticationMethods {
name := method.name()
log.Printf("Testing if %s is applicable for Authentication..", name)
// does not support it via validate?
if !method.isApplicable(b) {
continue
}
log.Printf("Using %s for Authentication", name)
auth, err := method.build(b)
if err != nil {
return nil, err
}
// populate authentication specific fields on the Config
// (e.g. is service principal, fields parsed from the azure cli)
err = auth.populateConfig(&config)
if err != nil {
return nil, err
}
config.authMethod = auth
// Authenticated Object ID Cache
if config.GetAuthenticatedObjectID != nil {
uncachedFunction := config.GetAuthenticatedObjectID
config.GetAuthenticatedObjectID = func(ctx context.Context) (string, error) {
if authenticatedObjectCache == "" {
authenticatedObjectCache, err = uncachedFunction(ctx)
if err != nil {
return "", err
}
log.Printf("authenticated object ID cache miss, populting with: %q", authenticatedObjectCache)
}
return authenticatedObjectCache, nil
}
}
return &config, config.authMethod.validate()
}
return nil, fmt.Errorf("No supported authentication methods were found!")
}