...

Source file src/github.com/cli/go-gh/v2/pkg/auth/auth_test.go

Documentation: github.com/cli/go-gh/v2/pkg/auth

     1  package auth
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/cli/go-gh/v2/pkg/config"
     7  	"github.com/stretchr/testify/assert"
     8  	"github.com/stretchr/testify/require"
     9  )
    10  
    11  func TestTokenForHost(t *testing.T) {
    12  	tests := []struct {
    13  		name                  string
    14  		host                  string
    15  		githubToken           string
    16  		githubEnterpriseToken string
    17  		ghToken               string
    18  		ghEnterpriseToken     string
    19  		config                *config.Config
    20  		wantToken             string
    21  		wantSource            string
    22  	}{
    23  		{
    24  			name:       "given there is no env token and no config token, when we get the token for github.com, then it returns the empty string and default source",
    25  			host:       "github.com",
    26  			config:     testNoHostsConfig(),
    27  			wantToken:  "",
    28  			wantSource: defaultSource,
    29  		},
    30  		{
    31  			name:       "given there is no env token and no config token, when we get the token for an enterprise server host, then it returns the empty string and default source",
    32  			host:       "enterprise.com",
    33  			config:     testNoHostsConfig(),
    34  			wantToken:  "",
    35  			wantSource: defaultSource,
    36  		},
    37  		{
    38  			name:        "given GH_TOKEN and GITHUB_TOKEN and a config token are set, when we get the token for github.com, then it returns GH_TOKEN as the priority",
    39  			host:        "github.com",
    40  			ghToken:     "GH_TOKEN",
    41  			githubToken: "GITHUB_TOKEN",
    42  			config:      testHostsConfig(),
    43  			wantToken:   "GH_TOKEN",
    44  			wantSource:  ghToken,
    45  		},
    46  		{
    47  			name:        "given GITHUB_TOKEN and a config token are set, when we get the token for github.com, then it returns GITHUB_TOKEN as the priority",
    48  			host:        "github.com",
    49  			githubToken: "GITHUB_TOKEN",
    50  			config:      testHostsConfig(),
    51  			wantToken:   "GITHUB_TOKEN",
    52  			wantSource:  githubToken,
    53  		},
    54  		{
    55  			name:       "given a config token is set for github.com, when we get the token, then it returns that token and oauth_token source",
    56  			host:       "github.com",
    57  			config:     testHostsConfig(),
    58  			wantToken:  "xxxxxxxxxxxxxxxxxxxx",
    59  			wantSource: oauthToken,
    60  		},
    61  		{
    62  			name:        "given GH_TOKEN and GITHUB_TOKEN and a config token are set, when we get the token for any subdomain of ghe.com, then it returns GH_TOKEN as the priority",
    63  			host:        "tenant.ghe.com",
    64  			ghToken:     "GH_TOKEN",
    65  			githubToken: "GITHUB_TOKEN",
    66  			config:      testHostsConfig(),
    67  			wantToken:   "GH_TOKEN",
    68  			wantSource:  ghToken,
    69  		},
    70  		{
    71  			name:        "given GITHUB_TOKEN and a config token are set, when we get the token for any subdomain of ghe.com, then it returns GITHUB_TOKEN as the priority",
    72  			host:        "tenant.ghe.com",
    73  			githubToken: "GITHUB_TOKEN",
    74  			config:      testHostsConfig(),
    75  			wantToken:   "GITHUB_TOKEN",
    76  			wantSource:  githubToken,
    77  		},
    78  		{
    79  			name:       "given a config token is set for a subdomain of ghe.com, when we get the token for that subdomain, then it returns that token and oauth_token source",
    80  			host:       "tenant.ghe.com",
    81  			config:     testHostsConfig(),
    82  			wantToken:  "zzzzzzzzzzzzzzzzzzzz",
    83  			wantSource: oauthToken,
    84  		},
    85  		{
    86  			name:        "given GH_TOKEN and GITHUB_TOKEN and a config token are set, when we get the token for github.localhost, then it returns GH_TOKEN as the priority",
    87  			host:        "github.localhost",
    88  			ghToken:     "GH_TOKEN",
    89  			githubToken: "GITHUB_TOKEN",
    90  			config:      testHostsConfig(),
    91  			wantToken:   "GH_TOKEN",
    92  			wantSource:  ghToken,
    93  		},
    94  		{
    95  			name:        "given GITHUB_TOKEN and a config token are set, when we get the token for any subdomain of github.localhost, then it returns GITHUB_TOKEN as the priority",
    96  			host:        "github.localhost",
    97  			githubToken: "GITHUB_TOKEN",
    98  			config:      testHostsConfig(),
    99  			wantToken:   "GITHUB_TOKEN",
   100  			wantSource:  githubToken,
   101  		},
   102  		{
   103  			name:                  "given GH_ENTERPRISE_TOKEN and GITHUB_ENTERPRISE_TOKEN and a config token are set, when we get the token for an enterprise server host, then it returns GH_ENTERPRISE_TOKEN as the priority",
   104  			host:                  "enterprise.com",
   105  			ghEnterpriseToken:     "GH_ENTERPRISE_TOKEN",
   106  			githubEnterpriseToken: "GITHUB_ENTERPRISE_TOKEN",
   107  			config:                testHostsConfig(),
   108  			wantToken:             "GH_ENTERPRISE_TOKEN",
   109  			wantSource:            ghEnterpriseToken,
   110  		},
   111  		{
   112  			name:                  "given GITHUB_ENTERPRISE_TOKEN and a config token are set, when we get the token for an enterprise server host, then it returns GITHUB_ENTERPRISE_TOKEN as the priority",
   113  			host:                  "enterprise.com",
   114  			githubEnterpriseToken: "GITHUB_ENTERPRISE_TOKEN",
   115  			config:                testHostsConfig(),
   116  			wantToken:             "GITHUB_ENTERPRISE_TOKEN",
   117  			wantSource:            githubEnterpriseToken,
   118  		},
   119  		{
   120  			name:       "given a config token is set for an enterprise server host, when we get the token for that host, then it returns that token and oauth_token source",
   121  			host:       "enterprise.com",
   122  			config:     testHostsConfig(),
   123  			wantToken:  "yyyyyyyyyyyyyyyyyyyy",
   124  			wantSource: oauthToken,
   125  		},
   126  		{
   127  			name:        "given GH_TOKEN or GITHUB_TOKEN are set, when I get the token for any host not owned by GitHub, we do not get those tokens",
   128  			host:        "unknown.com",
   129  			config:      testNoHostsConfig(),
   130  			ghToken:     "GH_TOKEN",
   131  			githubToken: "GITHUB_TOKEN",
   132  			wantToken:   "",
   133  			wantSource:  defaultSource,
   134  		},
   135  	}
   136  
   137  	for _, tt := range tests {
   138  		t.Run(tt.name, func(t *testing.T) {
   139  			t.Setenv("GITHUB_TOKEN", tt.githubToken)
   140  			t.Setenv("GITHUB_ENTERPRISE_TOKEN", tt.githubEnterpriseToken)
   141  			t.Setenv("GH_TOKEN", tt.ghToken)
   142  			t.Setenv("GH_ENTERPRISE_TOKEN", tt.ghEnterpriseToken)
   143  			token, source := tokenForHost(tt.config, tt.host)
   144  			require.Equal(t, tt.wantToken, token, "Expected token for \"%s\" to be \"%s\", got \"%s\"", tt.host, tt.wantToken, token)
   145  			require.Equal(t, tt.wantSource, source, "Expected source for \"%s\" to be \"%s\", got \"%s\"", tt.host, tt.wantSource, source)
   146  		})
   147  	}
   148  }
   149  
   150  func TestDefaultHost(t *testing.T) {
   151  	tests := []struct {
   152  		name         string
   153  		config       *config.Config
   154  		ghHost       string
   155  		wantHost     string
   156  		wantSource   string
   157  		wantNotFound bool
   158  	}{
   159  		{
   160  			name:       "GH_HOST if set",
   161  			config:     testHostsConfig(),
   162  			ghHost:     "test.com",
   163  			wantHost:   "test.com",
   164  			wantSource: "GH_HOST",
   165  		},
   166  		{
   167  			name:       "authenticated host if only one",
   168  			config:     testSingleHostConfig(),
   169  			wantHost:   "enterprise.com",
   170  			wantSource: "hosts",
   171  		},
   172  		{
   173  			name:         "default host if more than one authenticated host",
   174  			config:       testHostsConfig(),
   175  			wantHost:     "github.com",
   176  			wantSource:   "default",
   177  			wantNotFound: true,
   178  		},
   179  		{
   180  			name:         "default host if no authenticated host",
   181  			config:       testNoHostsConfig(),
   182  			wantHost:     "github.com",
   183  			wantSource:   "default",
   184  			wantNotFound: true,
   185  		},
   186  	}
   187  
   188  	for _, tt := range tests {
   189  		t.Run(tt.name, func(t *testing.T) {
   190  			if tt.ghHost != "" {
   191  				t.Setenv("GH_HOST", tt.ghHost)
   192  			}
   193  			host, source := defaultHost(tt.config)
   194  			assert.Equal(t, tt.wantHost, host)
   195  			assert.Equal(t, tt.wantSource, source)
   196  		})
   197  	}
   198  }
   199  
   200  func TestKnownHosts(t *testing.T) {
   201  	tests := []struct {
   202  		name      string
   203  		config    *config.Config
   204  		ghHost    string
   205  		ghToken   string
   206  		wantHosts []string
   207  	}{
   208  		{
   209  			name:      "no known hosts",
   210  			config:    testNoHostsConfig(),
   211  			wantHosts: []string{},
   212  		},
   213  		{
   214  			name:      "includes GH_HOST",
   215  			config:    testNoHostsConfig(),
   216  			ghHost:    "test.com",
   217  			wantHosts: []string{"test.com"},
   218  		},
   219  		{
   220  			name:      "includes authenticated hosts",
   221  			config:    testHostsConfig(),
   222  			wantHosts: []string{"github.com", "enterprise.com", "tenant.ghe.com"},
   223  		},
   224  		{
   225  			name:      "includes default host if environment auth token",
   226  			config:    testNoHostsConfig(),
   227  			ghToken:   "TOKEN",
   228  			wantHosts: []string{"github.com"},
   229  		},
   230  		{
   231  			name:      "deduplicates hosts",
   232  			config:    testHostsConfig(),
   233  			ghHost:    "test.com",
   234  			ghToken:   "TOKEN",
   235  			wantHosts: []string{"test.com", "github.com", "enterprise.com", "tenant.ghe.com"},
   236  		},
   237  	}
   238  
   239  	for _, tt := range tests {
   240  		t.Run(tt.name, func(t *testing.T) {
   241  			if tt.ghHost != "" {
   242  				t.Setenv("GH_HOST", tt.ghHost)
   243  			}
   244  			if tt.ghToken != "" {
   245  				t.Setenv("GH_TOKEN", tt.ghToken)
   246  			}
   247  			hosts := knownHosts(tt.config)
   248  			assert.Equal(t, tt.wantHosts, hosts)
   249  		})
   250  	}
   251  }
   252  
   253  func TestIsEnterprise(t *testing.T) {
   254  	tests := []struct {
   255  		name    string
   256  		host    string
   257  		wantOut bool
   258  	}{
   259  		{
   260  			name:    "github",
   261  			host:    "github.com",
   262  			wantOut: false,
   263  		},
   264  		{
   265  			name:    "github API",
   266  			host:    "api.github.com",
   267  			wantOut: false,
   268  		},
   269  		{
   270  			name:    "localhost",
   271  			host:    "github.localhost",
   272  			wantOut: false,
   273  		},
   274  		{
   275  			name:    "localhost API",
   276  			host:    "api.github.localhost",
   277  			wantOut: false,
   278  		},
   279  		{
   280  			name:    "enterprise",
   281  			host:    "mygithub.com",
   282  			wantOut: true,
   283  		},
   284  		{
   285  			name:    "tenant",
   286  			host:    "tenant.ghe.com",
   287  			wantOut: false,
   288  		},
   289  		{
   290  			name:    "tenant API",
   291  			host:    "api.tenant.ghe.com",
   292  			wantOut: false,
   293  		},
   294  	}
   295  
   296  	for _, tt := range tests {
   297  		t.Run(tt.name, func(t *testing.T) {
   298  			out := IsEnterprise(tt.host)
   299  			assert.Equal(t, tt.wantOut, out)
   300  		})
   301  	}
   302  }
   303  
   304  func TestIsTenancy(t *testing.T) {
   305  	tests := []struct {
   306  		name    string
   307  		host    string
   308  		wantOut bool
   309  	}{
   310  		{
   311  			name:    "github",
   312  			host:    "github.com",
   313  			wantOut: false,
   314  		},
   315  		{
   316  			name:    "github API",
   317  			host:    "api.github.com",
   318  			wantOut: false,
   319  		},
   320  		{
   321  			name:    "localhost",
   322  			host:    "github.localhost",
   323  			wantOut: false,
   324  		},
   325  		{
   326  			name:    "localhost API",
   327  			host:    "api.github.localhost",
   328  			wantOut: false,
   329  		},
   330  		{
   331  			name:    "enterprise",
   332  			host:    "mygithub.com",
   333  			wantOut: false,
   334  		},
   335  		{
   336  			name:    "tenant",
   337  			host:    "tenant.ghe.com",
   338  			wantOut: true,
   339  		},
   340  		{
   341  			name:    "tenant API",
   342  			host:    "api.tenant.ghe.com",
   343  			wantOut: true,
   344  		},
   345  	}
   346  
   347  	for _, tt := range tests {
   348  		t.Run(tt.name, func(t *testing.T) {
   349  			out := IsTenancy(tt.host)
   350  			assert.Equal(t, tt.wantOut, out)
   351  		})
   352  	}
   353  }
   354  
   355  func TestNormalizeHostname(t *testing.T) {
   356  	tests := []struct {
   357  		name     string
   358  		host     string
   359  		wantHost string
   360  	}{
   361  		{
   362  			name:     "github domain",
   363  			host:     "test.github.com",
   364  			wantHost: "github.com",
   365  		},
   366  		{
   367  			name:     "capitalized",
   368  			host:     "GitHub.com",
   369  			wantHost: "github.com",
   370  		},
   371  		{
   372  			name:     "localhost domain",
   373  			host:     "test.github.localhost",
   374  			wantHost: "github.localhost",
   375  		},
   376  		{
   377  			name:     "enterprise domain",
   378  			host:     "mygithub.com",
   379  			wantHost: "mygithub.com",
   380  		},
   381  		{
   382  			name:     "bare tenant",
   383  			host:     "tenant.ghe.com",
   384  			wantHost: "tenant.ghe.com",
   385  		},
   386  		{
   387  			name:     "subdomained tenant",
   388  			host:     "api.tenant.ghe.com",
   389  			wantHost: "tenant.ghe.com",
   390  		},
   391  	}
   392  
   393  	for _, tt := range tests {
   394  		t.Run(tt.name, func(t *testing.T) {
   395  			normalized := NormalizeHostname(tt.host)
   396  			assert.Equal(t, tt.wantHost, normalized)
   397  		})
   398  	}
   399  }
   400  
   401  func testNoHostsConfig() *config.Config {
   402  	var data = ``
   403  	return config.ReadFromString(data)
   404  }
   405  
   406  func testSingleHostConfig() *config.Config {
   407  	var data = `
   408  hosts:
   409    enterprise.com:
   410      user: user2
   411      oauth_token: yyyyyyyyyyyyyyyyyyyy
   412      git_protocol: https
   413  `
   414  	return config.ReadFromString(data)
   415  }
   416  
   417  func testHostsConfig() *config.Config {
   418  	var data = `
   419  hosts:
   420    github.com:
   421      user: user1
   422      oauth_token: xxxxxxxxxxxxxxxxxxxx
   423      git_protocol: ssh
   424    enterprise.com:
   425      user: user2
   426      oauth_token: yyyyyyyyyyyyyyyyyyyy
   427      git_protocol: https
   428    tenant.ghe.com:
   429      user: user3
   430      oauth_token: zzzzzzzzzzzzzzzzzzzz
   431      git_protocol: https
   432  `
   433  	return config.ReadFromString(data)
   434  }
   435  

View as plain text