115 lines
2.9 KiB
Go
115 lines
2.9 KiB
Go
|
package infisical
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"time"
|
||
|
|
||
|
"code.jhot.me/jhot/hats/internal/util"
|
||
|
"github.com/go-resty/resty/v2"
|
||
|
)
|
||
|
|
||
|
type InfisicalClient struct {
|
||
|
restClient *resty.Client
|
||
|
host string
|
||
|
clientId string
|
||
|
clientSecret string
|
||
|
accessToken string
|
||
|
tokenExpiration time.Time
|
||
|
}
|
||
|
|
||
|
func New(host string, clientId string, clientSecret string) *InfisicalClient {
|
||
|
return &InfisicalClient{
|
||
|
restClient: resty.New().SetBaseURL(fmt.Sprintf("%s/api", host)),
|
||
|
host: host,
|
||
|
clientId: clientId,
|
||
|
clientSecret: clientSecret,
|
||
|
accessToken: "",
|
||
|
tokenExpiration: time.Now(),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (c *InfisicalClient) Login() error {
|
||
|
var result LoginResponse
|
||
|
_, err := util.CheckSuccess(c.restClient.R().SetFormData(map[string]string{
|
||
|
"clientId": c.clientId,
|
||
|
"clientSecret": c.clientSecret,
|
||
|
}).SetResult(&result).Post("v1/auth/universal-auth/login"))
|
||
|
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
c.restClient.SetAuthScheme(result.TokenType).SetAuthToken(result.AccessToken)
|
||
|
c.accessToken = result.AccessToken
|
||
|
c.tokenExpiration = time.Now().Add(time.Duration(result.ExpiresIn) * time.Second)
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (c *InfisicalClient) CheckToken() error {
|
||
|
if c.accessToken == "" {
|
||
|
return fmt.Errorf("access token empty, please login first")
|
||
|
}
|
||
|
|
||
|
if time.Now().Before(c.tokenExpiration) {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
var result LoginResponse
|
||
|
_, err := util.CheckSuccess(c.restClient.R().SetResult(&result).SetBody(map[string]interface{}{
|
||
|
"accessToken": c.accessToken,
|
||
|
}).Post("v1/auth/token/renew"))
|
||
|
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("error renewing token: %w", err)
|
||
|
}
|
||
|
|
||
|
c.restClient.SetAuthScheme(result.TokenType).SetAuthToken(result.AccessToken)
|
||
|
c.accessToken = result.AccessToken
|
||
|
c.tokenExpiration = time.Now().Add(time.Duration(result.ExpiresIn) * time.Second)
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (c *InfisicalClient) ListSecrets(opts *RetrieveSecretOptions) ([]Secret, error) {
|
||
|
err := c.CheckToken()
|
||
|
if err != nil {
|
||
|
return []Secret{}, err
|
||
|
}
|
||
|
|
||
|
var result SecretsResponse
|
||
|
_, err = util.CheckSuccess(c.restClient.R().SetResult(&result).SetQueryParams(map[string]string{
|
||
|
"workspaceId": opts.WorkspaceID,
|
||
|
"environment": opts.Environment,
|
||
|
"secretPath": opts.SecretPath,
|
||
|
"include_imports": fmt.Sprintf("%t", opts.IncludeImports),
|
||
|
}).Get("v3/secrets/raw"))
|
||
|
|
||
|
if err != nil {
|
||
|
return []Secret{}, err
|
||
|
}
|
||
|
|
||
|
return result.Secrets, nil
|
||
|
}
|
||
|
|
||
|
func (c *InfisicalClient) GetSecret(name string, opts *RetrieveSecretOptions) (Secret, error) {
|
||
|
err := c.CheckToken()
|
||
|
if err != nil {
|
||
|
return Secret{}, err
|
||
|
}
|
||
|
|
||
|
var result SecretResponse
|
||
|
_, err = util.CheckSuccess(c.restClient.R().SetResult(&result).SetQueryParams(map[string]string{
|
||
|
"workspaceId": opts.WorkspaceID,
|
||
|
"environment": opts.Environment,
|
||
|
"secretPath": opts.SecretPath,
|
||
|
"include_imports": fmt.Sprintf("%t", opts.IncludeImports),
|
||
|
"type": "shared",
|
||
|
}).Get("v3/secrets/raw/" + name))
|
||
|
|
||
|
if err != nil {
|
||
|
return Secret{}, err
|
||
|
}
|
||
|
|
||
|
return result.Secret, nil
|
||
|
}
|