github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/provider/azure/credentials.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package azure 5 6 import ( 7 "github.com/Azure/go-autorest/autorest" 8 "github.com/juju/errors" 9 "github.com/juju/utils" 10 "github.com/juju/utils/clock" 11 12 "github.com/juju/juju/cloud" 13 "github.com/juju/juju/environs" 14 "github.com/juju/juju/provider/azure/internal/azureauth" 15 ) 16 17 const ( 18 credAttrAppId = "application-id" 19 credAttrSubscriptionId = "subscription-id" 20 credAttrTenantId = "tenant-id" 21 credAttrAppPassword = "application-password" 22 23 // clientCredentialsAuthType is the auth-type for the 24 // "client credentials" OAuth flow, which requires a 25 // service principal with a password. 26 clientCredentialsAuthType cloud.AuthType = "service-principal-secret" 27 28 // deviceCodeAuthType is the auth-type for the interactive 29 // "device code" OAuth flow. 30 deviceCodeAuthType cloud.AuthType = "interactive" 31 ) 32 33 // environPoviderCredentials is an implementation of 34 // environs.ProviderCredentials for the Azure Resource 35 // Manager cloud provider. 36 type environProviderCredentials struct { 37 sender autorest.Sender 38 requestInspector autorest.PrepareDecorator 39 interactiveCreateServicePrincipal azureauth.InteractiveCreateServicePrincipalFunc 40 } 41 42 // CredentialSchemas is part of the environs.ProviderCredentials interface. 43 func (environProviderCredentials) CredentialSchemas() map[cloud.AuthType]cloud.CredentialSchema { 44 return map[cloud.AuthType]cloud.CredentialSchema{ 45 // deviceCodeAuthType is the interactive device-code oauth 46 // flow. This is only supported on the client side; it will 47 // be used to generate a service principal, and transformed 48 // into clientCredentialsAuthType. 49 deviceCodeAuthType: {{ 50 credAttrSubscriptionId, cloud.CredentialAttr{Description: "Azure subscription ID"}, 51 }}, 52 53 // clientCredentialsAuthType is the "client credentials" 54 // oauth flow, which requires a service principal with a 55 // password. 56 clientCredentialsAuthType: { 57 { 58 credAttrAppId, cloud.CredentialAttr{Description: "Azure Active Directory application ID"}, 59 }, { 60 credAttrSubscriptionId, cloud.CredentialAttr{Description: "Azure subscription ID"}, 61 }, { 62 credAttrAppPassword, cloud.CredentialAttr{ 63 Description: "Azure Active Directory application password", 64 Hidden: true, 65 }, 66 }, 67 }, 68 } 69 } 70 71 // DetectCredentials is part of the environs.ProviderCredentials interface. 72 func (environProviderCredentials) DetectCredentials() (*cloud.CloudCredential, error) { 73 return nil, errors.NotFoundf("credentials") 74 } 75 76 // FinalizeCredential is part of the environs.ProviderCredentials interface. 77 func (c environProviderCredentials) FinalizeCredential( 78 ctx environs.FinalizeCredentialContext, 79 args environs.FinalizeCredentialParams, 80 ) (*cloud.Credential, error) { 81 switch authType := args.Credential.AuthType(); authType { 82 case deviceCodeAuthType: 83 subscriptionId := args.Credential.Attributes()[credAttrSubscriptionId] 84 applicationId, password, err := c.interactiveCreateServicePrincipal( 85 ctx.GetStderr(), 86 c.sender, 87 c.requestInspector, 88 args.CloudEndpoint, 89 args.CloudIdentityEndpoint, 90 subscriptionId, 91 clock.WallClock, 92 utils.NewUUID, 93 ) 94 if err != nil { 95 return nil, errors.Trace(err) 96 } 97 out := cloud.NewCredential(clientCredentialsAuthType, map[string]string{ 98 credAttrSubscriptionId: subscriptionId, 99 credAttrAppId: applicationId, 100 credAttrAppPassword: password, 101 }) 102 out.Label = args.Credential.Label 103 return &out, nil 104 105 case clientCredentialsAuthType: 106 return &args.Credential, nil 107 default: 108 return nil, errors.NotSupportedf("%q auth-type", authType) 109 } 110 }