Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor various public surface area #13495

Merged
merged 5 commits into from
Nov 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions sdk/azidentity/aad_identity_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ func (c *aadIdentityClient) createDeviceCodeNumberRequest(ctx context.Context, t
// clientSecret: Gets the client secret that was generated for the App Registration used to authenticate the client.
// redirectURI: The redirect URI that was used to request the authorization code. Must be the same URI that is configured for the App Registration.
// scopes: The scopes required for the token
func (c *aadIdentityClient) authenticateInteractiveBrowser(ctx context.Context, tenantID string, clientID string, clientSecret *string, redirectURI *string, scopes []string) (*azcore.AccessToken, error) {
func (c *aadIdentityClient) authenticateInteractiveBrowser(ctx context.Context, tenantID string, clientID string, clientSecret string, redirectURI string, scopes []string) (*azcore.AccessToken, error) {
cfg, err := authCodeReceiver(c.authorityHost, tenantID, clientID, redirectURI, scopes)
if err != nil {
return nil, err
Expand All @@ -396,7 +396,7 @@ func (c *aadIdentityClient) authenticateInteractiveBrowser(ctx context.Context,
// clientSecret: Gets the client secret that was generated for the App Registration used to authenticate the client.
// redirectURI: The redirect URI that was used to request the authorization code. Must be the same URI that is configured for the App Registration.
// scopes: The scopes required for the token
func (c *aadIdentityClient) authenticateAuthCode(ctx context.Context, tenantID string, clientID string, authCode string, clientSecret *string, redirectURI string, scopes []string) (*azcore.AccessToken, error) {
func (c *aadIdentityClient) authenticateAuthCode(ctx context.Context, tenantID string, clientID string, authCode string, clientSecret string, redirectURI string, scopes []string) (*azcore.AccessToken, error) {
req, err := c.createAuthorizationCodeAuthRequest(ctx, tenantID, clientID, authCode, clientSecret, redirectURI, scopes)
if err != nil {
return nil, err
Expand All @@ -415,12 +415,12 @@ func (c *aadIdentityClient) authenticateAuthCode(ctx context.Context, tenantID s
}

// createAuthorizationCodeAuthRequest creates a request for an Access Token for authorization_code grant types.
func (c *aadIdentityClient) createAuthorizationCodeAuthRequest(ctx context.Context, tenantID string, clientID string, authCode string, clientSecret *string, redirectURI string, scopes []string) (*azcore.Request, error) {
func (c *aadIdentityClient) createAuthorizationCodeAuthRequest(ctx context.Context, tenantID string, clientID string, authCode string, clientSecret string, redirectURI string, scopes []string) (*azcore.Request, error) {
data := url.Values{}
data.Set(qpGrantType, "authorization_code")
data.Set(qpClientID, clientID)
if clientSecret != nil {
data.Set(qpClientSecret, *clientSecret) // only for web apps
if clientSecret != "" {
data.Set(qpClientSecret, clientSecret) // only for web apps
}
data.Set(qpRedirectURI, redirectURI)
data.Set(qpScope, strings.Join(scopes, " "))
Expand Down
39 changes: 22 additions & 17 deletions sdk/azidentity/authorization_code_credential.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,46 +10,51 @@ import (
)

// AuthorizationCodeCredentialOptions contain optional parameters that can be used to configure the AuthorizationCodeCredential.
// Call DefaultAuthorizationCodeCredentialOptions() to create an instance populated with default values.
type AuthorizationCodeCredentialOptions struct {
// Gets the client secret that was generated for the App Registration used to authenticate the client.
ClientSecret *string
// The host of the Azure Active Directory authority. The default is https://login.microsoft.com
ClientSecret string
// The host of the Azure Active Directory authority. The default is AzurePublicCloud.
// Leave empty to allow overriding the value from the AZURE_AUTHORITY_HOST environment variable.
AuthorityHost string
// HTTPClient sets the transport for making HTTP requests
// Leave this as nil to use the default HTTP transport
HTTPClient azcore.Transport
// Retry configures the built-in retry policy behavior
Retry *azcore.RetryOptions
Retry azcore.RetryOptions
// Telemetry configures the built-in telemetry policy behavior
Telemetry azcore.TelemetryOptions
}

// DefaultAuthorizationCodeCredentialOptions returns an instance of AuthorizationCodeCredentialOptions initialized with default values.
func DefaultAuthorizationCodeCredentialOptions() AuthorizationCodeCredentialOptions {
return AuthorizationCodeCredentialOptions{
Retry: azcore.DefaultRetryOptions(),
Telemetry: azcore.DefaultTelemetryOptions(),
}
}

// AuthorizationCodeCredential enables authentication to Azure Active Directory using an authorization code
// that was obtained through the authorization code flow, described in more detail in the Azure Active Directory
// documentation: https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow.
type AuthorizationCodeCredential struct {
client *aadIdentityClient
tenantID string // Gets the Azure Active Directory tenant (directory) ID of the service principal
clientID string // Gets the client (application) ID of the service principal
authCode string // The authorization code received from the authorization code flow. The authorization code must not have been used to obtain another token.
clientSecret *string // Gets the client secret that was generated for the App Registration used to authenticate the client.
redirectURI string // The redirect URI that was used to request the authorization code. Must be the same URI that is configured for the App Registration.
}

// DefaultAuthorizationCodeCredentialOptions returns an instance of AuthorizationCodeCredentialOptions initialized with default values.
func DefaultAuthorizationCodeCredentialOptions() AuthorizationCodeCredentialOptions {
return AuthorizationCodeCredentialOptions{}
tenantID string // Gets the Azure Active Directory tenant (directory) ID of the service principal
clientID string // Gets the client (application) ID of the service principal
authCode string // The authorization code received from the authorization code flow. The authorization code must not have been used to obtain another token.
clientSecret string // Gets the client secret that was generated for the App Registration used to authenticate the client.
redirectURI string // The redirect URI that was used to request the authorization code. Must be the same URI that is configured for the App Registration.
}

// NewAuthorizationCodeCredential constructs a new AuthorizationCodeCredential with the details needed to authenticate against Azure Active Directory with an authorization code.
// tenantID: The Azure Active Directory tenant (directory) ID of the service principal.
// clientID: The client (application) ID of the service principal.
// authCode: The authorization code received from the authorization code flow. The authorization code must not have been used to obtain another token.
// redirectURI: The redirect URI that was used to request the authorization code. Must be the same URI that is configured for the App Registration.
// redirectURL: The redirect URL that was used to request the authorization code. Must be the same URL that is configured for the App Registration.
// options: Manage the configuration of the requests sent to Azure Active Directory, they can also include a client secret for web app authentication.
func NewAuthorizationCodeCredential(tenantID string, clientID string, authCode string, redirectURI string, options *AuthorizationCodeCredentialOptions) (*AuthorizationCodeCredential, error) {
func NewAuthorizationCodeCredential(tenantID string, clientID string, authCode string, redirectURL string, options *AuthorizationCodeCredentialOptions) (*AuthorizationCodeCredential, error) {
if !validTenantID(tenantID) {
return nil, &CredentialUnavailableError{CredentialType: "Authorization Code Credential", Message: tenantIDValidationErr}
return nil, &CredentialUnavailableError{credentialType: "Authorization Code Credential", message: tenantIDValidationErr}
}
if options == nil {
temp := DefaultAuthorizationCodeCredentialOptions()
Expand All @@ -63,7 +68,7 @@ func NewAuthorizationCodeCredential(tenantID string, clientID string, authCode s
if err != nil {
return nil, err
}
return &AuthorizationCodeCredential{tenantID: tenantID, clientID: clientID, authCode: authCode, clientSecret: options.ClientSecret, redirectURI: redirectURI, client: c}, nil
return &AuthorizationCodeCredential{tenantID: tenantID, clientID: clientID, authCode: authCode, clientSecret: options.ClientSecret, redirectURI: redirectURL, client: c}, nil
}

// GetToken obtains a token from Azure Active Directory, using the specified authorization code to authenticate.
Expand Down
13 changes: 5 additions & 8 deletions sdk/azidentity/authorization_code_credential_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,7 @@ func TestAuthorizationCodeCredential_GetTokenSuccess(t *testing.T) {
defer close()
srv.AppendResponse(mock.WithBody([]byte(accessTokenRespSuccess)))
options := DefaultAuthorizationCodeCredentialOptions()
s := secret
options.ClientSecret = &s
options.ClientSecret = secret
options.AuthorityHost = srv.URL()
options.HTTPClient = srv
cred, err := NewAuthorizationCodeCredential(tenantID, clientID, testAuthCode, testRedirectURI, &options)
Expand All @@ -99,8 +98,7 @@ func TestAuthorizationCodeCredential_GetTokenInvalidCredentials(t *testing.T) {
defer close()
srv.SetResponse(mock.WithBody([]byte(accessTokenRespError)), mock.WithStatusCode(http.StatusUnauthorized))
options := DefaultAuthorizationCodeCredentialOptions()
s := secret
options.ClientSecret = &s
options.ClientSecret = secret
options.AuthorityHost = srv.URL()
options.HTTPClient = srv
cred, err := NewAuthorizationCodeCredential(tenantID, clientID, testAuthCode, testRedirectURI, &options)
Expand Down Expand Up @@ -134,8 +132,8 @@ func TestAuthorizationCodeCredential_GetTokenInvalidCredentials(t *testing.T) {
if len(respError.CorrelationID) == 0 {
t.Fatalf("Did not receive a CorrelationID")
}
if len(respError.URI) == 0 {
t.Fatalf("Did not receive an error URI")
if len(respError.URL) == 0 {
t.Fatalf("Did not receive an error URL")
}
if respError.Response == nil {
t.Fatalf("Did not receive an error response")
Expand All @@ -149,8 +147,7 @@ func TestAuthorizationCodeCredential_GetTokenUnexpectedJSON(t *testing.T) {
defer close()
srv.AppendResponse(mock.WithBody([]byte(accessTokenRespMalformed)))
options := DefaultAuthorizationCodeCredentialOptions()
s := secret
options.ClientSecret = &s
options.ClientSecret = secret
options.AuthorityHost = srv.URL()
options.HTTPClient = srv
cred, err := NewAuthorizationCodeCredential(tenantID, clientID, testRedirectURI, testRedirectURI, &options)
Expand Down
13 changes: 7 additions & 6 deletions sdk/azidentity/azidentity.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ type AADAuthenticationFailedError struct {
Timestamp string `json:"timestamp"`
TraceID string `json:"trace_id"`
CorrelationID string `json:"correlation_id"`
URI string `json:"error_uri"`
URL string `json:"error_uri"`
Response *azcore.Response
}

Expand Down Expand Up @@ -101,13 +101,13 @@ func newAADAuthenticationFailedError(resp *azcore.Response) error {
// create a credential do not exist or are unavailable.
type CredentialUnavailableError struct {
// CredentialType holds the name of the credential that is unavailable
CredentialType string
credentialType string
// Message contains the reason why the credential is unavailable
Message string
message string
}

func (e *CredentialUnavailableError) Error() string {
return e.CredentialType + ": " + e.Message
return e.credentialType + ": " + e.message
}

// NonRetriable indicates that this error should not be retried.
Expand All @@ -124,7 +124,7 @@ type pipelineOptions struct {
HTTPClient azcore.Transport

// Retry configures the built-in retry policy behavior
Retry *azcore.RetryOptions
Retry azcore.RetryOptions

// Telemetry configures the built-in telemetry policy behavior
Telemetry azcore.TelemetryOptions
Expand All @@ -134,6 +134,7 @@ type pipelineOptions struct {
func setAuthorityHost(authorityHost string) (string, error) {
if authorityHost == "" {
authorityHost = AzurePublicCloud
// NOTE: we only allow overriding the authority host if no host was specified
if envAuthorityHost := os.Getenv("AZURE_AUTHORITY_HOST"); envAuthorityHost != "" {
authorityHost = envAuthorityHost
}
Expand All @@ -153,7 +154,7 @@ func newDefaultPipeline(o pipelineOptions) azcore.Pipeline {
return azcore.NewPipeline(
o.HTTPClient,
azcore.NewTelemetryPolicy(&o.Telemetry),
azcore.NewRetryPolicy(o.Retry),
azcore.NewRetryPolicy(&o.Retry),
azcore.NewLogPolicy(nil))
}

Expand Down
34 changes: 18 additions & 16 deletions sdk/azidentity/azidentity_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ func Test_AuthorityHost_Parse(t *testing.T) {

func Test_SetEnvAuthorityHost(t *testing.T) {
err := os.Setenv("AZURE_AUTHORITY_HOST", envHostString)
defer func() {
// Unset that host environment variable to avoid other tests failed.
err = os.Unsetenv("AZURE_AUTHORITY_HOST")
if err != nil {
t.Fatalf("Unexpected error when unset environment variable: %v", err)
}
}()
if err != nil {
t.Fatalf("Unexpected error when initializing environment variables: %v", err)
}
Expand All @@ -31,34 +38,29 @@ func Test_SetEnvAuthorityHost(t *testing.T) {
t.Fatal(err)
}
if authorityHost != envHostString {
t.Fatalf("Unexpected error when get host from environment vairable: %v", err)
}

// Unset that host environment vairable to avoid other tests failed.
err = os.Unsetenv("AZURE_AUTHORITY_HOST")
if err != nil {
t.Fatalf("Unexpected error when unset environment vairable: %v", err)
t.Fatalf("Unexpected error when get host from environment variable: %v", err)
}
}

func Test_CustomAuthorityHost(t *testing.T) {
err := os.Setenv("AZURE_AUTHORITY_HOST", envHostString)
defer func() {
// Unset that host environment variable to avoid other tests failed.
err = os.Unsetenv("AZURE_AUTHORITY_HOST")
if err != nil {
t.Fatalf("Unexpected error when unset environment variable: %v", err)
}
}()
if err != nil {
t.Fatalf("Unexpected error when initializing environment variables: %v", err)
}

authorityHost, err := setAuthorityHost(customHostString)
if err != nil {
t.Fatal(err)
}
// ensure env var doesn't override explicit value
if authorityHost != customHostString {
t.Fatalf("Unexpected error when get host from environment vairable: %v", err)
}

// Unset that host environment vairable to avoid other tests failed.
err = os.Unsetenv("AZURE_AUTHORITY_HOST")
if err != nil {
t.Fatalf("Unexpected error when unset environment vairable: %v", err)
t.Fatalf("Unexpected host when get host from environment variable: %v", authorityHost)
}
}

Expand All @@ -68,7 +70,7 @@ func Test_DefaultAuthorityHost(t *testing.T) {
t.Fatal(err)
}
if authorityHost != AzurePublicCloud {
t.Fatalf("Unexpected error when set default AuthorityHost: %v", err)
t.Fatalf("Unexpected host when set default AuthorityHost: %v", authorityHost)
}
}

Expand Down
11 changes: 9 additions & 2 deletions sdk/azidentity/azure_cli_credential.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,16 @@ import (
type AzureCLITokenProvider func(ctx context.Context, resource string) ([]byte, error)

// AzureCLICredentialOptions contains options used to configure the AzureCLICredential
// Call DefaultAzureCLICredentialOptions() to create an instance populated with default values.
type AzureCLICredentialOptions struct {
TokenProvider AzureCLITokenProvider
}

// DefaultAzureCLICredentialOptions returns an instance of AzureCLICredentialOptions initialized with default values.
func DefaultAzureCLICredentialOptions() AzureCLICredentialOptions {
return AzureCLICredentialOptions{TokenProvider: defaultTokenProvider()}
}

// AzureCLICredential enables authentication to Azure Active Directory using the Azure CLI command "az account get-access-token".
type AzureCLICredential struct {
tokenProvider AzureCLITokenProvider
Expand All @@ -35,7 +41,8 @@ type AzureCLICredential struct {
// options: configure the management of the requests sent to Azure Active Directory.
func NewAzureCLICredential(options *AzureCLICredentialOptions) (*AzureCLICredential, error) {
if options == nil {
options = &AzureCLICredentialOptions{TokenProvider: defaultTokenProvider()}
def := DefaultAzureCLICredentialOptions()
options = &def
}
return &AzureCLICredential{
tokenProvider: options.TokenProvider,
Expand Down Expand Up @@ -122,7 +129,7 @@ func defaultTokenProvider() func(ctx context.Context, resource string) ([]byte,

output, err := cliCmd.Output()
if err != nil {
return nil, &CredentialUnavailableError{CredentialType: "Azure CLI Credential", Message: stderr.String()}
return nil, &CredentialUnavailableError{credentialType: "Azure CLI Credential", message: stderr.String()}
}

return output, nil
Expand Down
12 changes: 9 additions & 3 deletions sdk/azidentity/azure_cli_credential_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ var (
)

func TestAzureCLICredential_GetTokenSuccess(t *testing.T) {
cred, err := NewAzureCLICredential(&AzureCLICredentialOptions{TokenProvider: mockCLITokenProviderSuccess})
options := DefaultAzureCLICredentialOptions()
options.TokenProvider = mockCLITokenProviderSuccess
cred, err := NewAzureCLICredential(&options)
if err != nil {
t.Fatalf("Unable to create credential. Received: %v", err)
}
Expand All @@ -44,7 +46,9 @@ func TestAzureCLICredential_GetTokenSuccess(t *testing.T) {
}

func TestAzureCLICredential_GetTokenInvalidToken(t *testing.T) {
cred, err := NewAzureCLICredential(&AzureCLICredentialOptions{TokenProvider: mockCLITokenProviderFailure})
options := DefaultAzureCLICredentialOptions()
options.TokenProvider = mockCLITokenProviderFailure
cred, err := NewAzureCLICredential(&options)
if err != nil {
t.Fatalf("Unable to create credential. Received: %v", err)
}
Expand All @@ -58,7 +62,9 @@ func TestBearerPolicy_AzureCLICredential(t *testing.T) {
srv, close := mock.NewTLSServer()
defer close()
srv.AppendResponse(mock.WithStatusCode(http.StatusOK))
cred, err := NewAzureCLICredential(&AzureCLICredentialOptions{TokenProvider: mockCLITokenProviderSuccess})
options := DefaultAzureCLICredentialOptions()
options.TokenProvider = mockCLITokenProviderSuccess
cred, err := NewAzureCLICredential(&options)
if err != nil {
t.Fatalf("Did not expect an error but received: %v", err)
}
Expand Down
Loading