github.com/Azure/go-autorest/autorest/azure/auth@v0.5.12/auth_test.go (about)

     1  // Copyright 2017 Microsoft Corporation
     2  //
     3  //  Licensed under the Apache License, Version 2.0 (the "License");
     4  //  you may not use this file except in compliance with the License.
     5  //  You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  //  Unless required by applicable law or agreed to in writing, software
    10  //  distributed under the License is distributed on an "AS IS" BASIS,
    11  //  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  //  See the License for the specific language governing permissions and
    13  //  limitations under the License.
    14  
    15  package auth
    16  
    17  import (
    18  	"os"
    19  	"path/filepath"
    20  	"reflect"
    21  	"testing"
    22  
    23  	"github.com/Azure/go-autorest/autorest"
    24  	"github.com/Azure/go-autorest/autorest/azure"
    25  )
    26  
    27  var (
    28  	expectedEnvironment = EnvironmentSettings{
    29  		Values: map[string]string{
    30  			SubscriptionID:      "sub-abc-123",
    31  			TenantID:            "tenant-abc-123",
    32  			ClientID:            "client-abc-123",
    33  			ClientSecret:        "client-secret-123",
    34  			CertificatePath:     "~/some/path/cert.pfx",
    35  			CertificatePassword: "certificate-password",
    36  			Username:            "user-name-abc",
    37  			Password:            "user-password-123",
    38  			Resource:            "my-resource",
    39  		},
    40  		Environment: azure.PublicCloud,
    41  	}
    42  	expectedFile = FileSettings{
    43  		Values: map[string]string{
    44  			ClientID:                "client-id-123",
    45  			ClientSecret:            "client-secret-456",
    46  			SubscriptionID:          "sub-id-789",
    47  			TenantID:                "tenant-id-123",
    48  			ActiveDirectoryEndpoint: "https://login.microsoftonline.com",
    49  			ResourceManagerEndpoint: "https://management.azure.com/",
    50  			GraphResourceID:         "https://graph.windows.net/",
    51  			SQLManagementEndpoint:   "https://management.core.windows.net:8443/",
    52  			GalleryEndpoint:         "https://gallery.azure.com/",
    53  			ManagementEndpoint:      "https://management.core.windows.net/",
    54  		},
    55  	}
    56  )
    57  
    58  func setDefaultEnv() {
    59  	os.Setenv(SubscriptionID, expectedEnvironment.Values[SubscriptionID])
    60  	os.Setenv(TenantID, expectedEnvironment.Values[TenantID])
    61  	os.Setenv(ClientID, expectedEnvironment.Values[ClientID])
    62  	os.Setenv(ClientSecret, expectedEnvironment.Values[ClientSecret])
    63  	os.Setenv(CertificatePath, expectedEnvironment.Values[CertificatePath])
    64  	os.Setenv(CertificatePassword, expectedEnvironment.Values[CertificatePassword])
    65  	os.Setenv(Username, expectedEnvironment.Values[Username])
    66  	os.Setenv(Password, expectedEnvironment.Values[Password])
    67  	os.Setenv(Resource, expectedEnvironment.Values[Resource])
    68  }
    69  
    70  func TestGetSettingsFromEnvironment(t *testing.T) {
    71  	setDefaultEnv()
    72  	settings, err := GetSettingsFromEnvironment()
    73  	if err != nil {
    74  		t.Logf("failed to get settings: %v", err)
    75  		t.Fail()
    76  	}
    77  	if !reflect.DeepEqual(expectedEnvironment, settings) {
    78  		t.Logf("expected %v, got %v", expectedEnvironment, settings)
    79  		t.Fail()
    80  	}
    81  	if settings.GetSubscriptionID() != expectedEnvironment.Values[SubscriptionID] {
    82  		t.Log("settings.GetSubscriptionID() return value didn't match")
    83  		t.Fail()
    84  	}
    85  }
    86  
    87  func TestGetSettingsFromEnvironmentBadEnvironmentName(t *testing.T) {
    88  	os.Setenv(EnvironmentName, "badenvironment")
    89  	defer func() {
    90  		// must undo this value else other tests will fail
    91  		os.Setenv(EnvironmentName, "")
    92  	}()
    93  	_, err := GetSettingsFromEnvironment()
    94  	if err == nil {
    95  		t.Log("unexpected nil error")
    96  		t.Fail()
    97  	}
    98  }
    99  
   100  func TestEnvGetClientCertificate(t *testing.T) {
   101  	setDefaultEnv()
   102  	settings, err := GetSettingsFromEnvironment()
   103  	if err != nil {
   104  		t.Logf("failed to get settings: %v", err)
   105  		t.Fail()
   106  	}
   107  	cfg, err := settings.GetClientCertificate()
   108  	if err != nil {
   109  		t.Logf("failed to get config for client cert: %v", err)
   110  		t.Fail()
   111  	}
   112  	if cfg.CertificatePath != expectedEnvironment.Values[CertificatePath] {
   113  		t.Log("bad certificate path")
   114  		t.Fail()
   115  	}
   116  	if cfg.CertificatePassword != expectedEnvironment.Values[CertificatePassword] {
   117  		t.Log("bad certificate password")
   118  		t.Fail()
   119  	}
   120  	// should fail as the certificate doesn't exist
   121  	_, err = cfg.Authorizer()
   122  	if err == nil {
   123  		t.Log("unexpected nil error")
   124  		t.Fail()
   125  	}
   126  }
   127  
   128  func TestEnvGetUsernamePassword(t *testing.T) {
   129  	setDefaultEnv()
   130  	settings, err := GetSettingsFromEnvironment()
   131  	if err != nil {
   132  		t.Logf("failed to get settings: %v", err)
   133  		t.Fail()
   134  	}
   135  	cfg, err := settings.GetUsernamePassword()
   136  	if err != nil {
   137  		t.Logf("failed to get config for username/password: %v", err)
   138  		t.Fail()
   139  	}
   140  	_, err = cfg.Authorizer()
   141  	if err != nil {
   142  		t.Logf("failed to get authorizer for username/password: %v", err)
   143  		t.Fail()
   144  	}
   145  }
   146  
   147  func TestEnvGetMSI(t *testing.T) {
   148  	setDefaultEnv()
   149  	settings, err := GetSettingsFromEnvironment()
   150  	if err != nil {
   151  		t.Logf("failed to get settings: %v", err)
   152  		t.Fail()
   153  	}
   154  	cfg := settings.GetMSI()
   155  	if cfg.Resource == "" {
   156  		t.Fatal("unexpected empty resource")
   157  	}
   158  }
   159  
   160  func TestEnvGetDeviceFlow(t *testing.T) {
   161  	setDefaultEnv()
   162  	settings, err := GetSettingsFromEnvironment()
   163  	if err != nil {
   164  		t.Logf("failed to get settings: %v", err)
   165  		t.Fail()
   166  	}
   167  	cfg := settings.GetDeviceFlow()
   168  	// TODO mock device flow?
   169  	if cfg.ClientID != expectedEnvironment.Values[ClientID] {
   170  		t.Log("bad client ID")
   171  		t.Fail()
   172  	}
   173  	if cfg.TenantID != expectedEnvironment.Values[TenantID] {
   174  		t.Log("bad tenant ID")
   175  		t.Fail()
   176  	}
   177  }
   178  
   179  func TestGetSettingsFromFile(t *testing.T) {
   180  	os.Setenv("AZURE_AUTH_LOCATION", "./testdata/credsutf16le.json")
   181  	settings, err := GetSettingsFromFile()
   182  	if err != nil {
   183  		t.Logf("failed to load config file: %v", err)
   184  		t.Fail()
   185  	}
   186  	if !reflect.DeepEqual(expectedFile, settings) {
   187  		t.Logf("expected %v, got %v", expectedFile, settings)
   188  		t.Fail()
   189  	}
   190  	if settings.GetSubscriptionID() != expectedFile.Values[SubscriptionID] {
   191  		t.Log("settings.GetSubscriptionID() return value didn't match")
   192  		t.Fail()
   193  	}
   194  }
   195  
   196  func TestNewAuthorizerFromFile(t *testing.T) {
   197  	os.Setenv("AZURE_AUTH_LOCATION", "./testdata/credsutf16le.json")
   198  	authorizer, err := NewAuthorizerFromFile("https://management.azure.com")
   199  	if err != nil || authorizer == nil {
   200  		t.Logf("NewAuthorizerFromFile failed, got error %v", err)
   201  		t.Fail()
   202  	}
   203  }
   204  
   205  func TestNewAuthorizerFromFileWithResource(t *testing.T) {
   206  	os.Setenv("AZURE_AUTH_LOCATION", "./testdata/credsutf16le.json")
   207  	authorizer, err := NewAuthorizerFromFileWithResource("https://my.vault.azure.net")
   208  	if err != nil || authorizer == nil {
   209  		t.Logf("NewAuthorizerFromFileWithResource failed, got error %v", err)
   210  		t.Fail()
   211  	}
   212  }
   213  
   214  func TestNewAuthorizerFromEnvironment(t *testing.T) {
   215  	setDefaultEnv()
   216  	authorizer, err := NewAuthorizerFromEnvironment()
   217  
   218  	if err != nil || authorizer == nil {
   219  		t.Logf("NewAuthorizerFromEnvironment failed, got error %v", err)
   220  		t.Fail()
   221  	}
   222  }
   223  
   224  func TestNewAuthorizerFromEnvironmentWithResource(t *testing.T) {
   225  	setDefaultEnv()
   226  	authorizer, err := NewAuthorizerFromEnvironmentWithResource("https://my.vault.azure.net")
   227  
   228  	if err != nil || authorizer == nil {
   229  		t.Logf("NewAuthorizerFromEnvironmentWithResource failed, got error %v", err)
   230  		t.Fail()
   231  	}
   232  }
   233  
   234  func TestDecodeAndUnmarshal(t *testing.T) {
   235  	tests := []string{
   236  		"credsutf8.json",
   237  		"credsutf16le.json",
   238  		"credsutf16be.json",
   239  	}
   240  	for _, test := range tests {
   241  		os.Setenv("AZURE_AUTH_LOCATION", filepath.Join("./testdata/", test))
   242  		settings, err := GetSettingsFromFile()
   243  		if err != nil {
   244  			t.Logf("error reading file '%s': %s", test, err)
   245  			t.Fail()
   246  		}
   247  		if !reflect.DeepEqual(expectedFile, settings) {
   248  			t.Logf("unmarshaled map expected %v, got %v", expectedFile, settings)
   249  			t.Fail()
   250  		}
   251  	}
   252  }
   253  
   254  func TestFileClientCertificateAuthorizer(t *testing.T) {
   255  	os.Setenv("AZURE_AUTH_LOCATION", "./testdata/credsutf8.json")
   256  	settings, err := GetSettingsFromFile()
   257  	if err != nil {
   258  		t.Logf("failed to load file settings: %v", err)
   259  		t.Fail()
   260  	}
   261  	// add certificate settings
   262  	settings.Values[CertificatePath] = "~/fake/path/cert.pfx"
   263  	settings.Values[CertificatePassword] = "fake-password"
   264  	_, err = settings.ClientCertificateAuthorizer("https://management.azure.com")
   265  	if err == nil {
   266  		t.Log("unexpected nil error")
   267  		t.Fail()
   268  	}
   269  }
   270  
   271  func TestFileGetAuthorizerClientCert(t *testing.T) {
   272  	t.Setenv("AZURE_AUTH_LOCATION", "./testdata/credsutf8.json")
   273  	settings, err := GetSettingsFromFile()
   274  	if err != nil {
   275  		t.Logf("failed to load file settings: %v", err)
   276  		t.Fail()
   277  	}
   278  	// add certificate settings
   279  	settings.Values[CertificatePath] = "~/fake/path/cert.pfx"
   280  	settings.Values[CertificatePassword] = "fake-password"
   281  	auth, err := settings.GetAuthorizer("https://management.azure.com")
   282  	if err != nil {
   283  		t.Logf("failed to get authorizer: %v", err)
   284  		t.Fail()
   285  	}
   286  	if _, ok := auth.(*autorest.BearerAuthorizer); !ok {
   287  		t.Fatalf("unexpected authorizer type %T", auth)
   288  	}
   289  }
   290  
   291  func TestMultitenantClientCredentials(t *testing.T) {
   292  	setDefaultEnv()
   293  	os.Setenv(AuxiliaryTenantIDs, "aux-tenant-1;aux-tenant-2;aux-tenant3")
   294  	defer func() {
   295  		os.Setenv(AuxiliaryTenantIDs, "")
   296  	}()
   297  	settings, err := GetSettingsFromEnvironment()
   298  	if err != nil {
   299  		t.Fatalf("failed to get settings from environment: %v", err)
   300  	}
   301  	if settings.Values[AuxiliaryTenantIDs] == "" {
   302  		t.Fatal("auxiliary tenant IDs are missing in settings")
   303  	}
   304  	ccc, err := settings.GetClientCredentials()
   305  	if err != nil {
   306  		t.Fatalf("failed to get client credentials config: %v", err)
   307  	}
   308  	if len(ccc.AuxTenants) == 0 {
   309  		t.Fatal("auxiliary tenant IDs are missing in config")
   310  	}
   311  	expected := []string{"aux-tenant-1", "aux-tenant-2", "aux-tenant3"}
   312  	if !reflect.DeepEqual(ccc.AuxTenants, expected) {
   313  		t.Fatalf("expected auxiliary tenants '%s', got '%s'", expected, ccc.AuxTenants)
   314  	}
   315  	a, err := ccc.Authorizer()
   316  	if err != nil {
   317  		t.Fatalf("failed to create authorizer: %v", err)
   318  	}
   319  	if _, ok := a.(autorest.MultiTenantServicePrincipalTokenAuthorizer); !ok {
   320  		t.Fatal("authorizer doesn't implement MultiTenantServicePrincipalTokenAuthorizer")
   321  	}
   322  }