github.com/argoproj/argo-cd/v2@v2.10.5/util/settings/accounts_test.go (about)

     1  package settings
     2  
     3  import (
     4  	"context"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/stretchr/testify/assert"
     9  	"google.golang.org/grpc/codes"
    10  	"google.golang.org/grpc/status"
    11  	v1 "k8s.io/api/core/v1"
    12  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    13  
    14  	"github.com/argoproj/argo-cd/v2/common"
    15  )
    16  
    17  func TestGetAccounts_NoAccountsConfigured(t *testing.T) {
    18  	_, settingsManager := fixtures(nil)
    19  	accounts, err := settingsManager.GetAccounts()
    20  	assert.NoError(t, err)
    21  
    22  	adminAccount, ok := accounts[common.ArgoCDAdminUsername]
    23  	assert.True(t, ok)
    24  	assert.EqualValues(t, adminAccount.Capabilities, []AccountCapability{AccountCapabilityLogin})
    25  }
    26  
    27  func TestGetAccounts_HasConfiguredAccounts(t *testing.T) {
    28  	_, settingsManager := fixtures(map[string]string{"accounts.test": "apiKey"}, func(secret *v1.Secret) {
    29  		secret.Data["accounts.test.tokens"] = []byte(`[{"id":"123","iat":1583789194,"exp":1583789194}]`)
    30  	})
    31  	accounts, err := settingsManager.GetAccounts()
    32  	assert.NoError(t, err)
    33  
    34  	acc, ok := accounts["test"]
    35  	assert.True(t, ok)
    36  	assert.ElementsMatch(t, []AccountCapability{AccountCapabilityApiKey}, acc.Capabilities)
    37  	assert.ElementsMatch(t, []Token{{ID: "123", IssuedAt: 1583789194, ExpiresAt: 1583789194}}, acc.Tokens)
    38  	assert.True(t, acc.Enabled)
    39  }
    40  
    41  func TestGetAccounts_DisableAccount(t *testing.T) {
    42  	_, settingsManager := fixtures(map[string]string{
    43  		"accounts.test":         "apiKey",
    44  		"accounts.test.enabled": "false",
    45  	})
    46  	accounts, err := settingsManager.GetAccounts()
    47  	assert.NoError(t, err)
    48  
    49  	acc, ok := accounts["test"]
    50  	assert.True(t, ok)
    51  	assert.False(t, acc.Enabled)
    52  }
    53  
    54  func TestGetAccount(t *testing.T) {
    55  	_, settingsManager := fixtures(map[string]string{
    56  		"accounts.test": "apiKey",
    57  	})
    58  
    59  	t.Run("ExistingUserName", func(t *testing.T) {
    60  		_, err := settingsManager.GetAccount("test")
    61  
    62  		assert.NoError(t, err)
    63  	})
    64  
    65  	t.Run("IncorrectName", func(t *testing.T) {
    66  		_, err := settingsManager.GetAccount("incorrect-name")
    67  
    68  		assert.Error(t, err)
    69  		assert.Equal(t, status.Code(err), codes.NotFound)
    70  	})
    71  }
    72  
    73  func TestGetAccount_WithInvalidToken(t *testing.T) {
    74  	_, settingsManager := fixtures(map[string]string{
    75  		"accounts.user1":       "apiKey",
    76  		"accounts.invaliduser": "apiKey",
    77  		"accounts.user2":       "apiKey",
    78  	},
    79  		func(secret *v1.Secret) {
    80  			secret.Data["accounts.user1.tokens"] = []byte(`[{"id":"1","iat":158378932,"exp":1583789194}]`)
    81  		},
    82  		func(secret *v1.Secret) {
    83  			secret.Data["accounts.invaliduser.tokens"] = []byte("Invalid token")
    84  		},
    85  		func(secret *v1.Secret) {
    86  			secret.Data["accounts.user2.tokens"] = []byte(`[{"id":"2","iat":1583789194,"exp":1583784545}]`)
    87  		},
    88  	)
    89  
    90  	_, err := settingsManager.GetAccounts()
    91  	assert.NoError(t, err)
    92  }
    93  
    94  func TestGetAdminAccount(t *testing.T) {
    95  	mTime := time.Now().Format(time.RFC3339)
    96  	_, settingsManager := fixtures(nil, func(secret *v1.Secret) {
    97  		secret.Data["admin.password"] = []byte("admin-password")
    98  		secret.Data["admin.passwordMtime"] = []byte(mTime)
    99  	})
   100  
   101  	acc, err := settingsManager.GetAccount(common.ArgoCDAdminUsername)
   102  	assert.NoError(t, err)
   103  
   104  	assert.Equal(t, "admin-password", acc.PasswordHash)
   105  	assert.Equal(t, mTime, acc.FormatPasswordMtime())
   106  }
   107  
   108  func TestFormatPasswordMtime_SuccessfullyFormatted(t *testing.T) {
   109  	mTime := time.Now()
   110  	acc := Account{PasswordMtime: &mTime}
   111  	assert.Equal(t, mTime.Format(time.RFC3339), acc.FormatPasswordMtime())
   112  }
   113  
   114  func TestFormatPasswordMtime_NoMtime(t *testing.T) {
   115  	acc := Account{}
   116  	assert.Equal(t, "", acc.FormatPasswordMtime())
   117  }
   118  
   119  func TestHasCapability(t *testing.T) {
   120  	acc := Account{Capabilities: []AccountCapability{AccountCapabilityApiKey}}
   121  	assert.True(t, acc.HasCapability(AccountCapabilityApiKey))
   122  	assert.False(t, acc.HasCapability(AccountCapabilityLogin))
   123  }
   124  
   125  func TestFormatCapabilities(t *testing.T) {
   126  	acc := Account{Capabilities: []AccountCapability{AccountCapabilityLogin, AccountCapabilityApiKey}}
   127  	assert.Equal(t, "login,apiKey", acc.FormatCapabilities())
   128  }
   129  
   130  func TestTokenIndex_TokenExists(t *testing.T) {
   131  	acc := Account{Tokens: []Token{{ID: "123"}, {ID: "456"}}}
   132  	index := acc.TokenIndex("456")
   133  	assert.Equal(t, 1, index)
   134  }
   135  
   136  func TestTokenIndex_TokenDoesNotExist(t *testing.T) {
   137  	acc := Account{Tokens: []Token{{ID: "123"}}}
   138  	index := acc.TokenIndex("456")
   139  	assert.Equal(t, -1, index)
   140  }
   141  
   142  func TestAddAccount_AccountAdded(t *testing.T) {
   143  	clientset, settingsManager := fixtures(nil)
   144  	mTime := time.Now()
   145  	addedAccount := Account{
   146  		Tokens:        []Token{{ID: "123"}},
   147  		Capabilities:  []AccountCapability{AccountCapabilityLogin},
   148  		Enabled:       false,
   149  		PasswordHash:  "hash",
   150  		PasswordMtime: &mTime,
   151  	}
   152  	err := settingsManager.AddAccount("test", addedAccount)
   153  	assert.NoError(t, err)
   154  
   155  	cm, err := clientset.CoreV1().ConfigMaps("default").Get(context.Background(), common.ArgoCDConfigMapName, metav1.GetOptions{})
   156  	assert.NoError(t, err)
   157  
   158  	assert.Equal(t, cm.Data["accounts.test"], "login")
   159  	assert.Equal(t, cm.Data["accounts.test.enabled"], "false")
   160  
   161  	secret, err := clientset.CoreV1().Secrets("default").Get(context.Background(), common.ArgoCDSecretName, metav1.GetOptions{})
   162  	assert.NoError(t, err)
   163  
   164  	assert.Equal(t, "hash", string(secret.Data["accounts.test.password"]))
   165  	assert.Equal(t, mTime.Format(time.RFC3339), string(secret.Data["accounts.test.passwordMtime"]))
   166  	assert.Equal(t, `[{"id":"123","iat":0}]`, string(secret.Data["accounts.test.tokens"]))
   167  }
   168  
   169  func TestAddAccount_AlreadyExists(t *testing.T) {
   170  	_, settingsManager := fixtures(map[string]string{"accounts.test": "login"})
   171  	err := settingsManager.AddAccount("test", Account{})
   172  	assert.Error(t, err)
   173  }
   174  
   175  func TestAddAccount_CannotAddAdmin(t *testing.T) {
   176  	_, settingsManager := fixtures(nil)
   177  	err := settingsManager.AddAccount("admin", Account{})
   178  	assert.Error(t, err)
   179  }
   180  
   181  func TestUpdateAccount_SuccessfullyUpdated(t *testing.T) {
   182  	clientset, settingsManager := fixtures(map[string]string{"accounts.test": "login"})
   183  	mTime := time.Now()
   184  
   185  	err := settingsManager.UpdateAccount("test", func(account *Account) error {
   186  		account.Tokens = []Token{{ID: "123"}}
   187  		account.Capabilities = []AccountCapability{AccountCapabilityLogin}
   188  		account.Enabled = false
   189  		account.PasswordHash = "hash"
   190  		account.PasswordMtime = &mTime
   191  		return nil
   192  	})
   193  	assert.NoError(t, err)
   194  
   195  	cm, err := clientset.CoreV1().ConfigMaps("default").Get(context.Background(), common.ArgoCDConfigMapName, metav1.GetOptions{})
   196  	assert.NoError(t, err)
   197  
   198  	assert.Equal(t, cm.Data["accounts.test"], "login")
   199  	assert.Equal(t, cm.Data["accounts.test.enabled"], "false")
   200  
   201  	secret, err := clientset.CoreV1().Secrets("default").Get(context.Background(), common.ArgoCDSecretName, metav1.GetOptions{})
   202  	assert.NoError(t, err)
   203  
   204  	assert.Equal(t, "hash", string(secret.Data["accounts.test.password"]))
   205  	assert.Equal(t, mTime.Format(time.RFC3339), string(secret.Data["accounts.test.passwordMtime"]))
   206  	assert.Equal(t, `[{"id":"123","iat":0}]`, string(secret.Data["accounts.test.tokens"]))
   207  }
   208  
   209  func TestUpdateAccount_UpdateAdminPassword(t *testing.T) {
   210  	clientset, settingsManager := fixtures(nil)
   211  	mTime := time.Now()
   212  
   213  	err := settingsManager.UpdateAccount("admin", func(account *Account) error {
   214  		account.PasswordHash = "newPassword"
   215  		account.PasswordMtime = &mTime
   216  		return nil
   217  	})
   218  	assert.NoError(t, err)
   219  
   220  	secret, err := clientset.CoreV1().Secrets("default").Get(context.Background(), common.ArgoCDSecretName, metav1.GetOptions{})
   221  	assert.NoError(t, err)
   222  
   223  	assert.Equal(t, "newPassword", string(secret.Data["admin.password"]))
   224  	assert.Equal(t, mTime.Format(time.RFC3339), string(secret.Data["admin.passwordMtime"]))
   225  }
   226  
   227  func TestUpdateAccount_AccountDoesNotExist(t *testing.T) {
   228  	_, settingsManager := fixtures(map[string]string{"accounts.test": "login"})
   229  
   230  	err := settingsManager.UpdateAccount("test1", func(account *Account) error {
   231  		account.Enabled = false
   232  		return nil
   233  	})
   234  	assert.Error(t, err)
   235  }