github.com/jenkins-x/jx/v2@v2.1.155/pkg/cloud/iks/iam.go (about)

     1  package iks
     2  
     3  import (
     4  	"encoding/base64"
     5  	"fmt"
     6  
     7  	bluemix "github.com/IBM-Cloud/bluemix-go"
     8  	"github.com/IBM-Cloud/bluemix-go/bmxerror"
     9  	"github.com/IBM-Cloud/bluemix-go/rest"
    10  )
    11  
    12  const (
    13  	//ErrCodeInvalidToken  ...
    14  	ErrCodeInvalidToken = "InvalidToken"
    15  )
    16  
    17  //IAMError ...
    18  type IAMError struct {
    19  	ErrorCode    string `json:"errorCode"`
    20  	ErrorMessage string `json:"errorMessage"`
    21  	ErrorDetails string `json:"errorDetails"`
    22  }
    23  
    24  //Description ...
    25  func (e IAMError) Description() string {
    26  	if e.ErrorDetails != "" {
    27  		return e.ErrorDetails
    28  	}
    29  	return e.ErrorMessage
    30  }
    31  
    32  //IAMTokenResponse ...
    33  type IAMTokenResponse struct {
    34  	AccessToken     string `json:"access_token"`
    35  	RefreshToken    string `json:"refresh_token"`
    36  	UAAAccessToken  string `json:"uaa_token"`
    37  	UAARefreshToken string `json:"uaa_refresh_token"`
    38  	TokenType       string `json:"token_type"`
    39  }
    40  
    41  //IAMAuthRepository ...
    42  type IAMAuthRepository struct {
    43  	config   *bluemix.Config
    44  	client   *rest.Client
    45  	endpoint string
    46  }
    47  
    48  //NewIAMAuthRepository ...
    49  func NewIAMAuthRepository(config *bluemix.Config, client *rest.Client) (*IAMAuthRepository, error) {
    50  	var endpoint string
    51  
    52  	if config.TokenProviderEndpoint != nil {
    53  		endpoint = *config.TokenProviderEndpoint
    54  	} else {
    55  		var err error
    56  		endpoint, err = config.EndpointLocator.IAMEndpoint()
    57  		if err != nil {
    58  			return nil, err
    59  		}
    60  	}
    61  
    62  	return &IAMAuthRepository{
    63  		config:   config,
    64  		client:   client,
    65  		endpoint: endpoint,
    66  	}, nil
    67  }
    68  
    69  //AuthenticatePassword ...
    70  func (auth *IAMAuthRepository) AuthenticatePassword(username string, password string) error {
    71  	data := make(map[string]string, 1)
    72  	data["grant_type"] = "password"
    73  	data["username"] = username
    74  	data["password"] = password
    75  	return auth.getToken(data)
    76  }
    77  
    78  //AuthenticateAPIKey ...
    79  func (auth *IAMAuthRepository) AuthenticateAPIKey(apiKey string) error {
    80  	data := make(map[string]string, 1)
    81  	data["grant_type"] = "urn:ibm:params:oauth:grant-type:apikey"
    82  	data["apikey"] = apiKey
    83  	return auth.getToken(data)
    84  }
    85  
    86  //AuthenticateSSO ...
    87  func (auth *IAMAuthRepository) AuthenticateSSO(passcode string) error {
    88  	data := make(map[string]string, 1)
    89  	data["grant_type"] = "urn:ibm:params:oauth:grant-type:passcode"
    90  	data["passcode"] = passcode
    91  	return auth.getToken(data)
    92  }
    93  
    94  //RefreshToken ...
    95  func (auth *IAMAuthRepository) RefreshToken() (string, error) {
    96  	data := make(map[string]string, 1)
    97  	data["grant_type"] = "refresh_token"
    98  	data["refresh_token"] = auth.config.IAMRefreshToken
    99  
   100  	err := auth.getToken(data)
   101  	if err != nil {
   102  		return "", err
   103  	}
   104  
   105  	return auth.config.IAMAccessToken, nil
   106  }
   107  
   108  func (auth *IAMAuthRepository) getToken(data map[string]string) error {
   109  	request := rest.PostRequest(auth.endpoint+"/oidc/token").
   110  		Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte("bx:bx"))).
   111  		Field("response_type", "cloud_iam,uaa").
   112  		Field("uaa_client_id", "cf").
   113  		Field("uaa_client_secret", "")
   114  
   115  	for k, v := range data {
   116  		request.Field(k, v)
   117  	}
   118  
   119  	var tokens IAMTokenResponse
   120  	var apiErr IAMError
   121  
   122  	resp, err := auth.client.Do(request, &tokens, &apiErr)
   123  	if err != nil {
   124  		return err
   125  	}
   126  
   127  	if apiErr.ErrorCode != "" {
   128  		if apiErr.ErrorCode == "BXNIM0407E" {
   129  			return bmxerror.New(ErrCodeInvalidToken, apiErr.Description())
   130  		}
   131  		return bmxerror.NewRequestFailure(apiErr.ErrorCode, apiErr.Description(), resp.StatusCode)
   132  	}
   133  
   134  	auth.config.IAMAccessToken = fmt.Sprintf("%s %s", tokens.TokenType, tokens.AccessToken)
   135  	auth.config.IAMRefreshToken = tokens.RefreshToken
   136  
   137  	auth.config.UAAAccessToken = fmt.Sprintf("%s %s", tokens.TokenType, tokens.UAAAccessToken)
   138  	auth.config.UAARefreshToken = tokens.UAARefreshToken
   139  
   140  	return nil
   141  }
   142  
   143  func (auth *IAMAuthRepository) RefreshTokenToLinkAccounts(account *Account) error {
   144  	data := make(map[string]string, 1)
   145  	data["grant_type"] = "refresh_token"
   146  	data["refresh_token"] = auth.config.IAMRefreshToken
   147  	data["bss_account"] = account.GUID
   148  	data["ims_account"] = account.IMSAccountID
   149  
   150  	err := auth.getToken(data)
   151  	if err != nil {
   152  		return err
   153  	}
   154  
   155  	return nil
   156  }