github.com/ActiveState/cli@v0.0.0-20240508170324-6801f60cd051/pkg/platform/api/secrets/secrets.go (about) 1 package secrets 2 3 import ( 4 "fmt" 5 6 httptransport "github.com/go-openapi/runtime/client" 7 "github.com/go-openapi/strfmt" 8 9 "github.com/ActiveState/cli/internal/errs" 10 "github.com/ActiveState/cli/internal/locale" 11 "github.com/ActiveState/cli/internal/logging" 12 "github.com/ActiveState/cli/internal/retryhttp" 13 "github.com/ActiveState/cli/pkg/platform/api" 14 "github.com/ActiveState/cli/pkg/platform/api/mono/mono_models" 15 "github.com/ActiveState/cli/pkg/platform/api/secrets/secrets_client" 16 secretsapiClient "github.com/ActiveState/cli/pkg/platform/api/secrets/secrets_client/secrets" 17 secretsModels "github.com/ActiveState/cli/pkg/platform/api/secrets/secrets_models" 18 "github.com/ActiveState/cli/pkg/platform/authentication" 19 ) 20 21 var ( 22 ErrNotFound = errs.New("Secret not found") 23 ErKeypairSave = errs.New("Could not save keypair") 24 ) 25 26 // Scope covers what scope a secret belongs to 27 type Scope string 28 29 var ( 30 // ScopeUser is the user scope 31 ScopeUser Scope = "user" 32 33 // ScopeProject is the project scope 34 ScopeProject Scope = "project" 35 ) 36 37 var persistentClient *Client 38 39 // Client encapsulates a Secrets Service API client and its configuration 40 type Client struct { 41 *secrets_client.Secrets 42 BaseURI string 43 auth *authentication.Auth 44 } 45 46 // GetClient gets the cached (if any) client instance that was initialized using our default settings 47 func GetClient(auth *authentication.Auth) *Client { 48 if persistentClient == nil { 49 persistentClient = NewDefaultClient(auth) 50 } 51 return persistentClient 52 } 53 54 // Reset will reset the client cache 55 func Reset() { 56 persistentClient = nil 57 } 58 59 // NewClient creates a new SecretsAPI client instance using the provided HTTP settings. 60 // It also expects to receive the actual Bearer token value that will be passed in each 61 // API request in order to authenticate each request. 62 func NewClient(schema, host, basePath string, auth *authentication.Auth) *Client { 63 logging.Debug("secrets-api scheme=%s host=%s base_path=%s", schema, host, basePath) 64 transportRuntime := httptransport.New(host, basePath, []string{schema}) 65 transportRuntime.Transport = api.NewRoundTripper(retryhttp.DefaultClient.StandardClient().Transport) 66 //transportRuntime.SetDebug(true) 67 secretsClient := &Client{ 68 Secrets: secrets_client.New(transportRuntime, strfmt.Default), 69 BaseURI: fmt.Sprintf("%s://%s%s", schema, host, basePath), 70 auth: auth, 71 } 72 return secretsClient 73 } 74 75 // NewDefaultClient creates a new Client using constants SecretsAPISchema, -Host, and -Path and 76 // a provided Bearer-token value. 77 func NewDefaultClient(auth *authentication.Auth) *Client { 78 serviceURL := api.GetServiceURL(api.ServiceSecrets) 79 return NewClient(serviceURL.Scheme, serviceURL.Host, serviceURL.Path, auth) 80 } 81 82 // DefaultClient represents a secretsapi Client instance that can be accessed by any package 83 // needing it. DefaultClient should be set by a call to InitializeClient; this, it can be nil. 84 var DefaultClient *Client 85 86 // InitializeClient will create new Client using defaults, including the api.BearerToken value. 87 // This new Client instance will be accessible as secretapi.DefaultClient afterwards. Calling 88 // this function multiple times will redefine the DefaultClient value using the defaults/constants 89 // available to it at the time of the call; thus, the DefaultClient can be re-initialized this way. 90 // Because this function is dependent on a runtime-value from pkg/platform/api, we are not relying on 91 // the init() function for instantiation; this must be called explicitly. 92 func InitializeClient(auth *authentication.Auth) *Client { 93 DefaultClient = NewDefaultClient(auth) 94 return DefaultClient 95 } 96 97 // Get is an alias for InitializeClient used to persist our Get() pattern used throughout the codebase 98 func Get(auth *authentication.Auth) *Client { 99 return InitializeClient(auth) 100 } 101 102 // AuthenticatedUserID will check with the Secrets Service to ensure the current Bearer token 103 // is a valid one and return the user's UID in the response. Otherwise, this function will return 104 // a Failure. 105 func (client *Client) AuthenticatedUserID() (strfmt.UUID, error) { 106 resOk, err := client.Authentication.GetWhoami(nil, client.auth.ClientAuth()) 107 if err != nil { 108 if api.ErrorCode(err) == 401 { 109 return "", locale.NewExternalError("err_api_not_authenticated") 110 } 111 return "", errs.Wrap(err, "Whoami failed") 112 } 113 return *resOk.Payload.UID, nil 114 } 115 116 // Persist will make the current client the persistentClient 117 func (client *Client) Persist() { 118 persistentClient = client 119 } 120 121 // FetchAll fetchs the current user's secrets for an organization. 122 func FetchAll(client *Client, org *mono_models.Organization) ([]*secretsModels.UserSecret, error) { 123 params := secretsapiClient.NewGetAllUserSecretsParams() 124 params.OrganizationID = org.OrganizationID 125 getOk, err := client.Secrets.Secrets.GetAllUserSecrets(params, client.auth.ClientAuth()) 126 if err != nil { 127 switch statusCode := api.ErrorCode(err); statusCode { 128 case 401: 129 return nil, locale.NewExternalError("err_api_not_authenticated") 130 default: 131 return nil, errs.Wrap(err, "GetAllUserSecrets failed") 132 } 133 } 134 return getOk.Payload, nil 135 } 136 137 // FetchDefinitions fetchs the secret definitions for a given project. 138 func FetchDefinitions(client *Client, projectID strfmt.UUID) ([]*secretsModels.SecretDefinition, error) { 139 params := secretsapiClient.NewGetDefinitionsParams() 140 params.ProjectID = projectID 141 getOk, err := client.Secrets.Secrets.GetDefinitions(params, client.auth.ClientAuth()) 142 if err != nil { 143 switch statusCode := api.ErrorCode(err); statusCode { 144 case 401: 145 return nil, locale.NewExternalError("err_api_not_authenticated") 146 default: 147 return nil, errs.Wrap(err, "GetDefinitions failed") 148 } 149 } 150 return getOk.Payload, nil 151 } 152 153 func SaveSecretShares(client *Client, org *mono_models.Organization, user *mono_models.User, shares []*secretsModels.UserSecretShare) error { 154 params := secretsapiClient.NewShareUserSecretsParams() 155 params.OrganizationID = org.OrganizationID 156 params.UserID = user.UserID 157 params.UserSecrets = shares 158 _, err := client.Secrets.Secrets.ShareUserSecrets(params, client.auth.ClientAuth()) 159 if err != nil { 160 logging.Debug("error sharing user secrets with %s: %v", user.Username, err) 161 return locale.WrapError(err, "secrets_err_save", "", err.Error()) 162 } 163 return nil 164 }