Skip to content

Commit

Permalink
feat: use the Azure CLI as an auth method (Azure#238)
Browse files Browse the repository at this point in the history
This PR allows a user to authenticate using the Azure CLI 2.0 for development purposes.

Signed-off-by: Matthew Fisher <matt.fisher@microsoft.com>
  • Loading branch information
Matthew Fisher authored and Justin Hackett committed Mar 14, 2019
1 parent 37d0930 commit 3a34dfc
Show file tree
Hide file tree
Showing 72 changed files with 7,799 additions and 1,477 deletions.
50 changes: 30 additions & 20 deletions Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ type authArgs struct {
func addAuthFlags(authArgs *authArgs, f *flag.FlagSet) {
f.StringVar(&authArgs.RawAzureEnvironment, "azure-env", "AzurePublicCloud", "the target Azure cloud")
f.StringVarP(&authArgs.rawSubscriptionID, "subscription-id", "s", "", "azure subscription id (required)")
f.StringVar(&authArgs.AuthMethod, "auth-method", "client_secret", "auth method (default:`client_secret`, `device`, `client_certificate`)")
f.StringVar(&authArgs.AuthMethod, "auth-method", "client_secret", "auth method (default:`client_secret`, `cli`, `client_certificate`, `device`)")
f.StringVar(&authArgs.rawClientID, "client-id", "", "client id (used with --auth-method=[client_secret|client_certificate])")
f.StringVar(&authArgs.ClientSecret, "client-secret", "", "client secret (used with --auth-mode=client_secret)")
f.StringVar(&authArgs.CertificatePath, "certificate-path", "", "path to client certificate (used with --auth-method=client_certificate)")
Expand Down Expand Up @@ -199,6 +199,8 @@ func (authArgs *authArgs) getClient() (armhelpers.AKSEngineClient, error) {
return nil, err
}
switch authArgs.AuthMethod {
case "cli":
client, err = armhelpers.NewAzureClientWithCLI(env, authArgs.SubscriptionID.String())
case "device":
client, err = armhelpers.NewAzureClientWithDeviceAuth(env, authArgs.SubscriptionID.String())
case "client_secret":
Expand Down
61 changes: 40 additions & 21 deletions pkg/armhelpers/azureclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/adal"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/azure/cli"
"github.com/Azure/go-autorest/autorest/to"
homedir "github.com/mitchellh/go-homedir"
"github.com/pkg/errors"
Expand Down Expand Up @@ -70,6 +71,26 @@ type AzureClient struct {
servicePrincipalsClient graphrbac.ServicePrincipalsClient
}

// NewAzureClientWithCLI creates an AzureClient configured from Azure CLI 2.0 for local development scenarios.
func NewAzureClientWithCLI(env azure.Environment, subscriptionID string) (*AzureClient, error) {
_, tenantID, err := getOAuthConfig(env, subscriptionID)
if err != nil {
return nil, err
}

token, err := cli.GetTokenFromCLI(env.ResourceManagerEndpoint)
if err != nil {
return nil, err
}

adalToken, err := token.ToADALToken()
if err != nil {
return nil, err
}

return getClient(env, subscriptionID, tenantID, autorest.NewBearerAuthorizer(&adalToken), autorest.NewBearerAuthorizer(&adalToken)), nil
}

// NewAzureClientWithDeviceAuth returns an AzureClient by having a user complete a device authentication flow
func NewAzureClientWithDeviceAuth(env azure.Environment, subscriptionID string) (*AzureClient, error) {
oauthConfig, tenantID, err := getOAuthConfig(env, subscriptionID)
Expand Down Expand Up @@ -107,7 +128,7 @@ func NewAzureClientWithDeviceAuth(env azure.Environment, subscriptionID string)
}
graphSpt.Refresh()

return getClient(env, subscriptionID, tenantID, armSpt, graphSpt), nil
return getClient(env, subscriptionID, tenantID, autorest.NewBearerAuthorizer(armSpt), autorest.NewBearerAuthorizer(graphSpt)), nil
}
}

Expand Down Expand Up @@ -139,7 +160,7 @@ func NewAzureClientWithDeviceAuth(env azure.Environment, subscriptionID string)
}
graphSpt.Refresh()

return getClient(env, subscriptionID, tenantID, armSpt, graphSpt), nil
return getClient(env, subscriptionID, tenantID, autorest.NewBearerAuthorizer(armSpt), autorest.NewBearerAuthorizer(graphSpt)), nil
}

// NewAzureClientWithClientSecret returns an AzureClient via client_id and client_secret
Expand All @@ -159,7 +180,7 @@ func NewAzureClientWithClientSecret(env azure.Environment, subscriptionID, clien
}
graphSpt.Refresh()

return getClient(env, subscriptionID, tenantID, armSpt, graphSpt), nil
return getClient(env, subscriptionID, tenantID, autorest.NewBearerAuthorizer(armSpt), autorest.NewBearerAuthorizer(graphSpt)), nil
}

// NewAzureClientWithClientSecretExternalTenant returns an AzureClient via client_id and client_secret from a tenant
Expand All @@ -179,7 +200,7 @@ func NewAzureClientWithClientSecretExternalTenant(env azure.Environment, subscri
}
graphSpt.Refresh()

return getClient(env, subscriptionID, tenantID, armSpt, graphSpt), nil
return getClient(env, subscriptionID, tenantID, autorest.NewBearerAuthorizer(armSpt), autorest.NewBearerAuthorizer(graphSpt)), nil
}

// NewAzureClientWithClientCertificateFile returns an AzureClient via client_id and jwt certificate assertion
Expand Down Expand Up @@ -246,7 +267,7 @@ func newAzureClientWithCertificate(env azure.Environment, oauthConfig *adal.OAut
}
graphSpt.Refresh()

return getClient(env, subscriptionID, tenantID, armSpt, graphSpt), nil
return getClient(env, subscriptionID, tenantID, autorest.NewBearerAuthorizer(armSpt), autorest.NewBearerAuthorizer(graphSpt)), nil
}

func tokenCallback(path string) func(t adal.Token) error {
Expand Down Expand Up @@ -303,7 +324,7 @@ func getAcsEngineClientID(envName string) string {
}
}

func getClient(env azure.Environment, subscriptionID, tenantID string, armSpt *adal.ServicePrincipalToken, graphSpt *adal.ServicePrincipalToken) *AzureClient {
func getClient(env azure.Environment, subscriptionID, tenantID string, armAuthorizer autorest.Authorizer, graphAuthorizer autorest.Authorizer) *AzureClient {
c := &AzureClient{
environment: env,
subscriptionID: subscriptionID,
Expand All @@ -326,20 +347,19 @@ func getClient(env azure.Environment, subscriptionID, tenantID string, armSpt *a
servicePrincipalsClient: graphrbac.NewServicePrincipalsClientWithBaseURI(env.GraphEndpoint, tenantID),
}

authorizer := autorest.NewBearerAuthorizer(armSpt)
c.authorizationClient.Authorizer = authorizer
c.deploymentsClient.Authorizer = authorizer
c.deploymentOperationsClient.Authorizer = authorizer
c.msiClient.Authorizer = authorizer
c.resourcesClient.Authorizer = authorizer
c.storageAccountsClient.Authorizer = authorizer
c.interfacesClient.Authorizer = authorizer
c.groupsClient.Authorizer = authorizer
c.providersClient.Authorizer = authorizer
c.virtualMachinesClient.Authorizer = authorizer
c.virtualMachineScaleSetsClient.Authorizer = authorizer
c.virtualMachineScaleSetVMsClient.Authorizer = authorizer
c.disksClient.Authorizer = authorizer
c.authorizationClient.Authorizer = armAuthorizer
c.deploymentsClient.Authorizer = armAuthorizer
c.deploymentOperationsClient.Authorizer = armAuthorizer
c.msiClient.Authorizer = armAuthorizer
c.resourcesClient.Authorizer = armAuthorizer
c.storageAccountsClient.Authorizer = armAuthorizer
c.interfacesClient.Authorizer = armAuthorizer
c.groupsClient.Authorizer = armAuthorizer
c.providersClient.Authorizer = armAuthorizer
c.virtualMachinesClient.Authorizer = armAuthorizer
c.virtualMachineScaleSetsClient.Authorizer = armAuthorizer
c.virtualMachineScaleSetVMsClient.Authorizer = armAuthorizer
c.disksClient.Authorizer = armAuthorizer

c.deploymentsClient.PollingDelay = time.Second * 5
c.resourcesClient.PollingDelay = time.Second * 5
Expand All @@ -359,7 +379,6 @@ func getClient(env azure.Environment, subscriptionID, tenantID string, armSpt *a
c.virtualMachineScaleSetVMsClient.PollingDuration = DefaultARMOperationTimeout
c.virtualMachinesClient.PollingDuration = DefaultARMOperationTimeout

graphAuthorizer := autorest.NewBearerAuthorizer(graphSpt)
c.applicationsClient.Authorizer = graphAuthorizer
c.servicePrincipalsClient.Authorizer = graphAuthorizer

Expand Down
79 changes: 79 additions & 0 deletions vendor/github.com/Azure/go-autorest/autorest/azure/cli/profile.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 3a34dfc

Please sign in to comment.