github.com/jfrog/jfrog-cli-go@v1.22.1-0.20200318093948-4826ef344ffd/utils/config/config.go (about)

     1  package config
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"errors"
     7  	"fmt"
     8  	"github.com/buger/jsonparser"
     9  	"github.com/jfrog/jfrog-cli-go/utils/cliutils"
    10  	"github.com/jfrog/jfrog-cli-go/utils/lock"
    11  	"github.com/jfrog/jfrog-client-go/artifactory"
    12  	artifactoryAuth "github.com/jfrog/jfrog-client-go/artifactory/auth"
    13  	"github.com/jfrog/jfrog-client-go/artifactory/services"
    14  	"github.com/jfrog/jfrog-client-go/auth"
    15  	"github.com/jfrog/jfrog-client-go/config"
    16  	distributionAuth "github.com/jfrog/jfrog-client-go/distribution/auth"
    17  	"github.com/jfrog/jfrog-client-go/utils"
    18  	"github.com/jfrog/jfrog-client-go/utils/errorutils"
    19  	"github.com/jfrog/jfrog-client-go/utils/io/fileutils"
    20  	"github.com/jfrog/jfrog-client-go/utils/log"
    21  	"io/ioutil"
    22  	"os"
    23  	"path/filepath"
    24  	"sync"
    25  )
    26  
    27  // This is the default server id. It is used when adding a server config without providing a server ID
    28  const (
    29  	DefaultServerId   = "Default-Server"
    30  	JfrogConfigFile   = "jfrog-cli.conf"
    31  	JfrogDependencies = "dependencies"
    32  )
    33  
    34  func IsArtifactoryConfExists() (bool, error) {
    35  	conf, err := readConf()
    36  	if err != nil {
    37  		return false, err
    38  	}
    39  	return conf.Artifactory != nil && len(conf.Artifactory) > 0, nil
    40  }
    41  
    42  func IsMissionControlConfExists() (bool, error) {
    43  	conf, err := readConf()
    44  	if err != nil {
    45  		return false, err
    46  	}
    47  	return conf.MissionControl != nil && *conf.MissionControl != MissionControlDetails{}, nil
    48  }
    49  
    50  func IsBintrayConfExists() (bool, error) {
    51  	conf, err := readConf()
    52  	if err != nil {
    53  		return false, err
    54  	}
    55  	return conf.Bintray != nil, nil
    56  }
    57  
    58  func GetArtifactorySpecificConfig(serverId string) (*ArtifactoryDetails, error) {
    59  	conf, err := readConf()
    60  	if err != nil {
    61  		return nil, err
    62  	}
    63  	details := conf.Artifactory
    64  	if details == nil || len(details) == 0 {
    65  		return new(ArtifactoryDetails), nil
    66  	}
    67  	if len(serverId) == 0 {
    68  		details, err := GetDefaultConfiguredArtifactoryConf(details)
    69  		return details, errorutils.CheckError(err)
    70  	}
    71  	return getArtifactoryConfByServerId(serverId, details)
    72  }
    73  
    74  // Returns the default server configuration or error if not found.
    75  // Caller should perform the check error if required.
    76  func GetDefaultConfiguredArtifactoryConf(configs []*ArtifactoryDetails) (*ArtifactoryDetails, error) {
    77  	if len(configs) == 0 {
    78  		details := new(ArtifactoryDetails)
    79  		details.IsDefault = true
    80  		return details, nil
    81  	}
    82  	for _, conf := range configs {
    83  		if conf.IsDefault == true {
    84  			return conf, nil
    85  		}
    86  	}
    87  	return nil, errors.New("Couldn't find default server.")
    88  }
    89  
    90  // Returns default artifactory conf. Returns nil if default server doesn't exists.
    91  func GetDefaultArtifactoryConf() (*ArtifactoryDetails, error) {
    92  	configurations, err := GetAllArtifactoryConfigs()
    93  	if err != nil {
    94  		return nil, err
    95  	}
    96  
    97  	if len(configurations) == 0 {
    98  		log.Debug("No servers were configured.")
    99  		return nil, err
   100  	}
   101  
   102  	return GetDefaultConfiguredArtifactoryConf(configurations)
   103  }
   104  
   105  // Returns the configured server or error if the server id not found
   106  func GetArtifactoryConf(serverId string) (*ArtifactoryDetails, error) {
   107  	configs, err := GetAllArtifactoryConfigs()
   108  	if err != nil {
   109  		return nil, err
   110  	}
   111  	return getArtifactoryConfByServerId(serverId, configs)
   112  }
   113  
   114  // Returns the configured server or error if the server id not found
   115  func getArtifactoryConfByServerId(serverId string, configs []*ArtifactoryDetails) (*ArtifactoryDetails, error) {
   116  	for _, conf := range configs {
   117  		if conf.ServerId == serverId {
   118  			return conf, nil
   119  		}
   120  	}
   121  	return nil, errorutils.CheckError(errors.New(fmt.Sprintf("Server ID '%s' does not exist.", serverId)))
   122  }
   123  
   124  func GetAndRemoveConfiguration(serverName string, configs []*ArtifactoryDetails) (*ArtifactoryDetails, []*ArtifactoryDetails) {
   125  	for i, conf := range configs {
   126  		if conf.ServerId == serverName {
   127  			configs = append(configs[:i], configs[i+1:]...)
   128  			return conf, configs
   129  		}
   130  	}
   131  	return nil, configs
   132  }
   133  
   134  func GetAllArtifactoryConfigs() ([]*ArtifactoryDetails, error) {
   135  	conf, err := readConf()
   136  	if err != nil {
   137  		return nil, err
   138  	}
   139  	details := conf.Artifactory
   140  	if details == nil {
   141  		return make([]*ArtifactoryDetails, 0), nil
   142  	}
   143  	return details, nil
   144  }
   145  
   146  func ReadMissionControlConf() (*MissionControlDetails, error) {
   147  	conf, err := readConf()
   148  	if err != nil {
   149  		return nil, err
   150  	}
   151  	details := conf.MissionControl
   152  	if details == nil {
   153  		return new(MissionControlDetails), nil
   154  	}
   155  	return details, nil
   156  }
   157  
   158  func ReadBintrayConf() (*BintrayDetails, error) {
   159  	conf, err := readConf()
   160  	if err != nil {
   161  		return nil, err
   162  	}
   163  	details := conf.Bintray
   164  	if details == nil {
   165  		return new(BintrayDetails), nil
   166  	}
   167  	return details, nil
   168  }
   169  
   170  func SaveArtifactoryConf(details []*ArtifactoryDetails) error {
   171  	conf, err := readConf()
   172  	if err != nil {
   173  		return err
   174  	}
   175  	conf.Artifactory = details
   176  	return saveConfig(conf)
   177  }
   178  
   179  func SaveMissionControlConf(details *MissionControlDetails) error {
   180  	conf, err := readConf()
   181  	if err != nil {
   182  		return err
   183  	}
   184  	conf.MissionControl = details
   185  	return saveConfig(conf)
   186  }
   187  
   188  func SaveBintrayConf(details *BintrayDetails) error {
   189  	config, err := readConf()
   190  	if err != nil {
   191  		return err
   192  	}
   193  	config.Bintray = details
   194  	return saveConfig(config)
   195  }
   196  
   197  func saveConfig(config *ConfigV1) error {
   198  	config.Version = cliutils.GetConfigVersion()
   199  	b, err := json.Marshal(&config)
   200  	if err != nil {
   201  		return errorutils.CheckError(err)
   202  	}
   203  	var content bytes.Buffer
   204  	err = json.Indent(&content, b, "", "  ")
   205  	if err != nil {
   206  		return errorutils.CheckError(err)
   207  	}
   208  	path, err := getConfFilePath()
   209  	if err != nil {
   210  		return err
   211  	}
   212  
   213  	err = ioutil.WriteFile(path, []byte(content.String()), 0600)
   214  	if err != nil {
   215  		return errorutils.CheckError(err)
   216  	}
   217  
   218  	return nil
   219  }
   220  
   221  func readConf() (*ConfigV1, error) {
   222  	confFilePath, err := getConfFilePath()
   223  	if err != nil {
   224  		return nil, err
   225  	}
   226  	config := new(ConfigV1)
   227  	exists, err := fileutils.IsFileExists(confFilePath, false)
   228  	if err != nil {
   229  		return nil, err
   230  	}
   231  	if !exists {
   232  		return config, nil
   233  	}
   234  	content, err := fileutils.ReadFile(confFilePath)
   235  	if err != nil {
   236  		return nil, err
   237  	}
   238  	if len(content) == 0 {
   239  		return new(ConfigV1), nil
   240  	}
   241  	content, err = convertIfNecessary(content)
   242  	err = json.Unmarshal(content, &config)
   243  	return config, err
   244  }
   245  
   246  // The configuration schema can change between versions, therefore we need to convert old versions to the new schema.
   247  func convertIfNecessary(content []byte) ([]byte, error) {
   248  	version, err := jsonparser.GetString(content, "Version")
   249  	if err != nil {
   250  		if err.Error() == "Key path not found" {
   251  			version = "0"
   252  		} else {
   253  			return nil, errorutils.CheckError(err)
   254  		}
   255  	}
   256  	switch version {
   257  	case "0":
   258  		result := new(ConfigV1)
   259  		configV0 := new(ConfigV0)
   260  		err = json.Unmarshal(content, &configV0)
   261  		if errorutils.CheckError(err) != nil {
   262  			return nil, err
   263  		}
   264  		result = configV0.Convert()
   265  		err = saveConfig(result)
   266  		content, err = json.Marshal(&result)
   267  	}
   268  	return content, err
   269  }
   270  
   271  func GetJfrogDependenciesPath() (string, error) {
   272  	dependenciesDir := os.Getenv(cliutils.DependenciesDir)
   273  	if dependenciesDir != "" {
   274  		return utils.AddTrailingSlashIfNeeded(dependenciesDir), nil
   275  	}
   276  	jfrogHome, err := cliutils.GetJfrogHomeDir()
   277  	if err != nil {
   278  		return "", err
   279  	}
   280  	return filepath.Join(jfrogHome, JfrogDependencies), nil
   281  }
   282  
   283  func getConfFilePath() (string, error) {
   284  	confPath, err := cliutils.GetJfrogHomeDir()
   285  	if err != nil {
   286  		return "", err
   287  	}
   288  	os.MkdirAll(confPath, 0777)
   289  	return filepath.Join(confPath, JfrogConfigFile), nil
   290  }
   291  
   292  type ConfigV1 struct {
   293  	Artifactory    []*ArtifactoryDetails  `json:"artifactory"`
   294  	Bintray        *BintrayDetails        `json:"bintray,omitempty"`
   295  	MissionControl *MissionControlDetails `json:"MissionControl,omitempty"`
   296  	Version        string                 `json:"Version,omitempty"`
   297  }
   298  
   299  type ConfigV0 struct {
   300  	Artifactory    *ArtifactoryDetails    `json:"artifactory,omitempty"`
   301  	Bintray        *BintrayDetails        `json:"bintray,omitempty"`
   302  	MissionControl *MissionControlDetails `json:"MissionControl,omitempty"`
   303  }
   304  
   305  func (o *ConfigV0) Convert() *ConfigV1 {
   306  	config := new(ConfigV1)
   307  	config.Bintray = o.Bintray
   308  	config.MissionControl = o.MissionControl
   309  	if o.Artifactory != nil {
   310  		o.Artifactory.IsDefault = true
   311  		o.Artifactory.ServerId = DefaultServerId
   312  		config.Artifactory = []*ArtifactoryDetails{o.Artifactory}
   313  	}
   314  	return config
   315  }
   316  
   317  type ArtifactoryDetails struct {
   318  	Url                  string            `json:"url,omitempty"`
   319  	SshUrl               string            `json:"-"`
   320  	DistributionUrl      string            `json:"distributionUrl,omitempty"`
   321  	User                 string            `json:"user,omitempty"`
   322  	Password             string            `json:"password,omitempty"`
   323  	SshKeyPath           string            `json:"sshKeyPath,omitempty"`
   324  	SshPassphrase        string            `json:"SshPassphrase,omitempty"`
   325  	SshAuthHeaders       map[string]string `json:"SshAuthHeaders,omitempty"`
   326  	AccessToken          string            `json:"accessToken,omitempty"`
   327  	RefreshToken         string            `json:"refreshToken,omitempty"`
   328  	TokenRefreshInterval int               `json:"tokenRefreshInterval,omitempty"`
   329  	ClientCertPath       string            `json:"clientCertPath,omitempty"`
   330  	ClientCertKeyPath    string            `json:"clientCertKeyPath,omitempty"`
   331  	ServerId             string            `json:"serverId,omitempty"`
   332  	IsDefault            bool              `json:"isDefault,omitempty"`
   333  	InsecureTls          bool              `json:"-"`
   334  	// Deprecated, use password option instead.
   335  	ApiKey string `json:"apiKey,omitempty"`
   336  }
   337  
   338  type BintrayDetails struct {
   339  	ApiUrl            string `json:"-"`
   340  	DownloadServerUrl string `json:"-"`
   341  	User              string `json:"user,omitempty"`
   342  	Key               string `json:"key,omitempty"`
   343  	DefPackageLicense string `json:"defPackageLicense,omitempty"`
   344  }
   345  
   346  type MissionControlDetails struct {
   347  	Url         string `json:"url,omitempty"`
   348  	AccessToken string `json:"accessToken,omitempty"`
   349  }
   350  
   351  func (artifactoryDetails *ArtifactoryDetails) IsEmpty() bool {
   352  	return len(artifactoryDetails.Url) == 0
   353  }
   354  
   355  func (artifactoryDetails *ArtifactoryDetails) SetApiKey(apiKey string) {
   356  	artifactoryDetails.ApiKey = apiKey
   357  }
   358  
   359  func (artifactoryDetails *ArtifactoryDetails) SetUser(username string) {
   360  	artifactoryDetails.User = username
   361  }
   362  
   363  func (artifactoryDetails *ArtifactoryDetails) SetPassword(password string) {
   364  	artifactoryDetails.Password = password
   365  }
   366  
   367  func (artifactoryDetails *ArtifactoryDetails) SetAccessToken(accessToken string) {
   368  	artifactoryDetails.AccessToken = accessToken
   369  }
   370  
   371  func (artifactoryDetails *ArtifactoryDetails) SetRefreshToken(refreshToken string) {
   372  	artifactoryDetails.RefreshToken = refreshToken
   373  }
   374  
   375  func (artifactoryDetails *ArtifactoryDetails) SetClientCertPath(certificatePath string) {
   376  	artifactoryDetails.ClientCertPath = certificatePath
   377  }
   378  
   379  func (artifactoryDetails *ArtifactoryDetails) SetClientCertKeyPath(certificatePath string) {
   380  	artifactoryDetails.ClientCertKeyPath = certificatePath
   381  }
   382  
   383  func (artifactoryDetails *ArtifactoryDetails) GetApiKey() string {
   384  	return artifactoryDetails.ApiKey
   385  }
   386  
   387  func (artifactoryDetails *ArtifactoryDetails) GetUrl() string {
   388  	return artifactoryDetails.Url
   389  }
   390  
   391  func (artifactoryDetails *ArtifactoryDetails) GetDistributionUrl() string {
   392  	return artifactoryDetails.DistributionUrl
   393  }
   394  
   395  func (artifactoryDetails *ArtifactoryDetails) GetUser() string {
   396  	return artifactoryDetails.User
   397  }
   398  
   399  func (artifactoryDetails *ArtifactoryDetails) GetPassword() string {
   400  	return artifactoryDetails.Password
   401  }
   402  
   403  func (artifactoryDetails *ArtifactoryDetails) GetAccessToken() string {
   404  	return artifactoryDetails.AccessToken
   405  }
   406  
   407  func (artifactoryDetails *ArtifactoryDetails) GetRefreshToken() string {
   408  	return artifactoryDetails.RefreshToken
   409  }
   410  
   411  func (artifactoryDetails *ArtifactoryDetails) GetClientCertPath() string {
   412  	return artifactoryDetails.ClientCertPath
   413  }
   414  
   415  func (artifactoryDetails *ArtifactoryDetails) GetClientCertKeyPath() string {
   416  	return artifactoryDetails.ClientCertKeyPath
   417  }
   418  
   419  func (artifactoryDetails *ArtifactoryDetails) SshAuthHeaderSet() bool {
   420  	return len(artifactoryDetails.SshAuthHeaders) > 0
   421  }
   422  
   423  func (artifactoryDetails *ArtifactoryDetails) CreateArtAuthConfig() (auth.CommonDetails, error) {
   424  	artAuth := artifactoryAuth.NewArtifactoryDetails()
   425  	artAuth.SetUrl(artifactoryDetails.Url)
   426  	return artifactoryDetails.createArtAuthConfig(artAuth)
   427  }
   428  
   429  func (artifactoryDetails *ArtifactoryDetails) CreateDistAuthConfig() (auth.CommonDetails, error) {
   430  	artAuth := distributionAuth.NewDistributionDetails()
   431  	artAuth.SetUrl(artifactoryDetails.DistributionUrl)
   432  	return artifactoryDetails.createArtAuthConfig(artAuth)
   433  }
   434  
   435  func (artifactoryDetails *ArtifactoryDetails) createArtAuthConfig(commonDetails auth.CommonDetails) (auth.CommonDetails, error) {
   436  	commonDetails.SetSshUrl(artifactoryDetails.SshUrl)
   437  	commonDetails.SetSshAuthHeaders(artifactoryDetails.SshAuthHeaders)
   438  	commonDetails.SetAccessToken(artifactoryDetails.AccessToken)
   439  	// If refresh token is not empty, set a refresh handler and skip other credentials
   440  	if artifactoryDetails.RefreshToken != "" {
   441  		tokenRefreshServerId = artifactoryDetails.ServerId
   442  		commonDetails.SetTokenRefreshHandler(TokenRefreshHandler)
   443  	} else {
   444  		commonDetails.SetApiKey(artifactoryDetails.ApiKey)
   445  		commonDetails.SetUser(artifactoryDetails.User)
   446  		commonDetails.SetPassword(artifactoryDetails.Password)
   447  	}
   448  	commonDetails.SetClientCertPath(artifactoryDetails.ClientCertPath)
   449  	commonDetails.SetClientCertKeyPath(artifactoryDetails.ClientCertKeyPath)
   450  	commonDetails.SetSshKeyPath(artifactoryDetails.SshKeyPath)
   451  	commonDetails.SetSshPassphrase(artifactoryDetails.SshPassphrase)
   452  	if commonDetails.IsSshAuthentication() && !commonDetails.IsSshAuthHeaderSet() {
   453  		err := commonDetails.AuthenticateSsh(artifactoryDetails.SshKeyPath, artifactoryDetails.SshPassphrase)
   454  		if err != nil {
   455  			return nil, err
   456  		}
   457  	}
   458  	return commonDetails, nil
   459  }
   460  
   461  func (missionControlDetails *MissionControlDetails) GetAccessToken() string {
   462  	return missionControlDetails.AccessToken
   463  }
   464  
   465  func (missionControlDetails *MissionControlDetails) SetAccessToken(accessToken string) {
   466  	missionControlDetails.AccessToken = accessToken
   467  }
   468  
   469  // Internal golang locking for the same process.
   470  var mutex sync.Mutex
   471  var tokenRefreshServerId string
   472  
   473  func TokenRefreshHandler(currentAccessToken string) (newAccessToken string, err error) {
   474  	mutex.Lock()
   475  	lockFile, err := lock.CreateLock()
   476  	defer mutex.Unlock()
   477  	defer lockFile.Unlock()
   478  	if err != nil {
   479  		return "", err
   480  	}
   481  
   482  	serverConfiguration, err := GetArtifactoryConf(tokenRefreshServerId)
   483  	if err != nil {
   484  		return "", nil
   485  	}
   486  	// Token already refreshed
   487  	if serverConfiguration.AccessToken != "" && serverConfiguration.AccessToken != currentAccessToken {
   488  		return serverConfiguration.AccessToken, nil
   489  	}
   490  
   491  	refreshToken := serverConfiguration.RefreshToken
   492  	// Remove previous tokens
   493  	serverConfiguration.AccessToken = ""
   494  	serverConfiguration.RefreshToken = ""
   495  	// Try refreshing tokens
   496  	newToken, err := RefreshExpiredToken(serverConfiguration, currentAccessToken, refreshToken)
   497  
   498  	if err != nil {
   499  		log.Debug("Refresh token failed: " + err.Error())
   500  		log.Debug("Trying to create new tokens...")
   501  
   502  		expirySeconds, err := auth.ExtractExpiryFromAccessToken(currentAccessToken)
   503  		if err != nil {
   504  			return "", err
   505  		}
   506  
   507  		newToken, err = CreateTokensForConfig(serverConfiguration, expirySeconds)
   508  		if err != nil {
   509  			return "", nil
   510  		}
   511  	}
   512  
   513  	err = writeNewTokens(serverConfiguration, tokenRefreshServerId, newToken.AccessToken, newToken.RefreshToken)
   514  	if err != nil {
   515  		log.Error("Failed writing new tokens to config after handling access token expiry: " + err.Error())
   516  	}
   517  	return newToken.AccessToken, nil
   518  }
   519  
   520  func writeNewTokens(serverConfiguration *ArtifactoryDetails, serverId, accessToken, refreshToken string) error {
   521  	serverConfiguration.SetAccessToken(accessToken)
   522  	serverConfiguration.SetRefreshToken(refreshToken)
   523  
   524  	// Get configurations list
   525  	configurations, err := GetAllArtifactoryConfigs()
   526  	if err != nil {
   527  		return err
   528  	}
   529  
   530  	// Remove and get the server details from the configurations list
   531  	_, configurations = GetAndRemoveConfiguration(serverId, configurations)
   532  
   533  	// Append the configuration to the configurations list
   534  	configurations = append(configurations, serverConfiguration)
   535  	return SaveArtifactoryConf(configurations)
   536  }
   537  
   538  func CreateTokensForConfig(artifactoryDetails *ArtifactoryDetails, expirySeconds int) (services.CreateTokenResponseData, error) {
   539  	servicesManager, err := CreateTokensServiceManager(artifactoryDetails)
   540  	if err != nil {
   541  		return services.CreateTokenResponseData{}, err
   542  	}
   543  
   544  	createTokenParams := services.NewCreateTokenParams()
   545  	createTokenParams.Username = artifactoryDetails.User
   546  	createTokenParams.ExpiresIn = expirySeconds
   547  	// User-scoped token
   548  	createTokenParams.Scope = "member-of-groups:*"
   549  	createTokenParams.Refreshable = true
   550  
   551  	newToken, err := servicesManager.CreateToken(createTokenParams)
   552  	if err != nil {
   553  		return services.CreateTokenResponseData{}, err
   554  	}
   555  	return newToken, nil
   556  }
   557  
   558  func CreateInitialRefreshTokensIfNeeded(artifactoryDetails *ArtifactoryDetails) (err error) {
   559  	if !(artifactoryDetails.TokenRefreshInterval > 0 && artifactoryDetails.RefreshToken == "" && artifactoryDetails.AccessToken == "") {
   560  		return nil
   561  	}
   562  	mutex.Lock()
   563  	lockFile, err := lock.CreateLock()
   564  	defer mutex.Unlock()
   565  	defer lockFile.Unlock()
   566  	if err != nil {
   567  		return err
   568  	}
   569  
   570  	newToken, err := CreateTokensForConfig(artifactoryDetails, artifactoryDetails.TokenRefreshInterval*60)
   571  	if err != nil {
   572  		return err
   573  	}
   574  	// remove initializing value
   575  	artifactoryDetails.TokenRefreshInterval = 0
   576  	return writeNewTokens(artifactoryDetails, artifactoryDetails.ServerId, newToken.AccessToken, newToken.RefreshToken)
   577  }
   578  
   579  func RefreshExpiredToken(artifactoryDetails *ArtifactoryDetails, currentAccessToken string, refreshToken string) (services.CreateTokenResponseData, error) {
   580  	// The tokens passed as parameters are also used for authentication
   581  	noCredsDetails := new(ArtifactoryDetails)
   582  	noCredsDetails.Url = artifactoryDetails.Url
   583  	noCredsDetails.ClientCertPath = artifactoryDetails.ClientCertPath
   584  	noCredsDetails.ClientCertKeyPath = artifactoryDetails.ClientCertKeyPath
   585  	noCredsDetails.ServerId = artifactoryDetails.ServerId
   586  	noCredsDetails.IsDefault = artifactoryDetails.IsDefault
   587  
   588  	servicesManager, err := CreateTokensServiceManager(noCredsDetails)
   589  	if err != nil {
   590  		return services.CreateTokenResponseData{}, err
   591  	}
   592  
   593  	refreshTokenParams := services.NewRefreshTokenParams()
   594  	refreshTokenParams.AccessToken = currentAccessToken
   595  	refreshTokenParams.RefreshToken = refreshToken
   596  	return servicesManager.RefreshToken(refreshTokenParams)
   597  }
   598  
   599  func CreateTokensServiceManager(artDetails *ArtifactoryDetails) (*artifactory.ArtifactoryServicesManager, error) {
   600  	certPath, err := cliutils.GetJfrogSecurityDir()
   601  	if err != nil {
   602  		return nil, err
   603  	}
   604  	artAuth, err := artDetails.CreateArtAuthConfig()
   605  	if err != nil {
   606  		return nil, err
   607  	}
   608  	serviceConfig, err := config.NewConfigBuilder().
   609  		SetArtDetails(artAuth).
   610  		SetCertificatesPath(certPath).
   611  		SetInsecureTls(artDetails.InsecureTls).
   612  		SetDryRun(false).
   613  		Build()
   614  	if err != nil {
   615  		return nil, err
   616  	}
   617  	return artifactory.New(&artAuth, serviceConfig)
   618  }