Merge rebrand/phase-a: Threshold CLI/binary, packaging, docs, legacy fallbacks
ci / check (push) Failing after 12m27s
ci / check (push) Failing after 12m27s
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
commit
443e483a16
216 files changed
+1378
-1180
No files matched your search
+35
-36
@@ -15,7 +15,6 @@ import (
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -53,14 +52,14 @@ const (
|
||||
|
||||
// Config is used to configure the creation of the client
|
||||
type Config struct {
|
||||
// Addr is the address of the Boundary controller. This should be a
|
||||
// complete URL such as "http://boundary.example.com". If you need a custom
|
||||
// Addr is the address of the Threshold controller. This should be a
|
||||
// complete URL such as "http://threshold.example.com". If you need a custom
|
||||
// SSL cert or want to enable insecure mode, you need to specify a custom
|
||||
// HttpClient.
|
||||
Addr string
|
||||
|
||||
// Token is the client token that reuslts from authentication and can be
|
||||
// used to make calls into Boundary
|
||||
// used to make calls into Threshold
|
||||
Token string
|
||||
|
||||
// RecoveryKmsWrapper is a wrapper used in the recovery KMS authentication
|
||||
@@ -68,9 +67,9 @@ type Config struct {
|
||||
// per-call, regardless of any value set in Token.
|
||||
RecoveryKmsWrapper wrapping.Wrapper
|
||||
|
||||
// HttpClient is the HTTP client to use. Boundary sets sane defaults for the
|
||||
// HttpClient is the HTTP client to use. Threshold sets sane defaults for the
|
||||
// http.Client and its associated http.Transport created in DefaultConfig.
|
||||
// If you must modify Boundary's defaults, it is suggested that you start
|
||||
// If you must modify Threshold's defaults, it is suggested that you start
|
||||
// with that client and modify as needed rather than start with an empty
|
||||
// client (or http.DefaultClient). Currently if the client is cloned the
|
||||
// same HttpClient is used.
|
||||
@@ -114,20 +113,20 @@ type Config struct {
|
||||
}
|
||||
|
||||
// TLSConfig contains the parameters needed to configure TLS on the HTTP client
|
||||
// used to communicate with Boundary.
|
||||
// used to communicate with Threshold.
|
||||
type TLSConfig struct {
|
||||
// CACert is the path to a PEM-encoded CA cert file to use to verify the
|
||||
// Boundary server SSL certificate.
|
||||
// Threshold server SSL certificate.
|
||||
CACert string
|
||||
|
||||
// CAPath is the path to a directory of PEM-encoded CA cert files to verify
|
||||
// the Boundary server SSL certificate.
|
||||
// the Threshold server SSL certificate.
|
||||
CAPath string
|
||||
|
||||
// ClientCert is the path to the certificate for Boundary communication
|
||||
// ClientCert is the path to the certificate for Threshold communication
|
||||
ClientCert string
|
||||
|
||||
// ClientKey is the path to the private key for Boundary communication
|
||||
// ClientKey is the path to the private key for Threshold communication
|
||||
ClientKey string
|
||||
|
||||
// ServerName, if set, is used to set the SNI host when connecting via
|
||||
@@ -162,7 +161,7 @@ func RateLimitLinearJitterBackoff(min, max time.Duration, attemptNum int, resp *
|
||||
// safe to modify the return value of this function.
|
||||
//
|
||||
// The default Addr is http://127.0.0.1:9200, but this can be overridden by
|
||||
// setting the `BOUNDARY_ADDR` environment variable.
|
||||
// setting the `THRESHOLD_ADDR` environment variable.
|
||||
//
|
||||
// If an error is encountered, this will return nil.
|
||||
func DefaultConfig() (*Config, error) {
|
||||
@@ -270,7 +269,7 @@ func (c *Config) setAddr(addr string) error {
|
||||
// Remove trailing or leading slashes
|
||||
path := strings.Trim(u.Path, "/")
|
||||
// Remove v1 in front or back (e.g. they could have
|
||||
// https://boundary.example.com/myinstall/v1 which would put it at the
|
||||
// https://threshold.example.com/myinstall/v1 which would put it at the
|
||||
// back)
|
||||
path = strings.TrimPrefix(path, "v1")
|
||||
path = strings.TrimSuffix(path, "v1")
|
||||
@@ -296,15 +295,15 @@ func (c *Config) ReadEnvironment() error {
|
||||
var envServerName string
|
||||
|
||||
// Parse the environment variables
|
||||
if v := os.Getenv(EnvBoundaryAddr); v != "" {
|
||||
if v := Getenv(EnvBoundaryAddr); v != "" {
|
||||
c.Addr = v
|
||||
}
|
||||
|
||||
if v := os.Getenv(EnvBoundaryToken); v != "" {
|
||||
if v := Getenv(EnvBoundaryToken); v != "" {
|
||||
c.Token = v
|
||||
}
|
||||
|
||||
if v := os.Getenv(EnvBoundaryMaxRetries); v != "" {
|
||||
if v := Getenv(EnvBoundaryMaxRetries); v != "" {
|
||||
maxRetries, err := strconv.ParseUint(v, 10, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -318,7 +317,7 @@ func (c *Config) ReadEnvironment() error {
|
||||
c.MaxRetries = int(maxRetries)
|
||||
}
|
||||
|
||||
if v := os.Getenv(EnvBoundarySRVLookup); v != "" {
|
||||
if v := Getenv(EnvBoundarySRVLookup); v != "" {
|
||||
var err error
|
||||
lookup, err := strconv.ParseBool(v)
|
||||
if err != nil {
|
||||
@@ -327,7 +326,7 @@ func (c *Config) ReadEnvironment() error {
|
||||
c.SRVLookup = lookup
|
||||
}
|
||||
|
||||
if t := os.Getenv(EnvBoundaryClientTimeout); t != "" {
|
||||
if t := Getenv(EnvBoundaryClientTimeout); t != "" {
|
||||
clientTimeout, err := parseutil.ParseDurationSecond(t)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not parse %q", EnvBoundaryClientTimeout)
|
||||
@@ -335,7 +334,7 @@ func (c *Config) ReadEnvironment() error {
|
||||
c.Timeout = clientTimeout
|
||||
}
|
||||
|
||||
if v := os.Getenv(EnvBoundaryRateLimit); v != "" {
|
||||
if v := Getenv(EnvBoundaryRateLimit); v != "" {
|
||||
rateLimit, burstLimit, err := parseRateLimit(v)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -346,31 +345,31 @@ func (c *Config) ReadEnvironment() error {
|
||||
// TLS Config
|
||||
{
|
||||
var foundTLSConfig bool
|
||||
if v := os.Getenv(EnvBoundaryCACert); v != "" {
|
||||
if v := Getenv(EnvBoundaryCACert); v != "" {
|
||||
foundTLSConfig = true
|
||||
envCACert = v
|
||||
}
|
||||
if v := os.Getenv(EnvBoundaryCAPath); v != "" {
|
||||
if v := Getenv(EnvBoundaryCAPath); v != "" {
|
||||
foundTLSConfig = true
|
||||
envCAPath = v
|
||||
}
|
||||
if v := os.Getenv(EnvBoundaryClientCert); v != "" {
|
||||
if v := Getenv(EnvBoundaryClientCert); v != "" {
|
||||
foundTLSConfig = true
|
||||
envClientCert = v
|
||||
}
|
||||
if v := os.Getenv(EnvBoundaryClientKey); v != "" {
|
||||
if v := Getenv(EnvBoundaryClientKey); v != "" {
|
||||
foundTLSConfig = true
|
||||
envClientKey = v
|
||||
}
|
||||
if v := os.Getenv(EnvBoundaryTLSInsecure); v != "" {
|
||||
if v := Getenv(EnvBoundaryTLSInsecure); v != "" {
|
||||
foundTLSConfig = true
|
||||
var err error
|
||||
envInsecure, err = strconv.ParseBool(v)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not parse BOUNDARY_TLS_INSECURE")
|
||||
return fmt.Errorf("could not parse THRESHOLD_TLS_INSECURE")
|
||||
}
|
||||
}
|
||||
if v := os.Getenv(EnvBoundaryTLSServerName); v != "" {
|
||||
if v := Getenv(EnvBoundaryTLSServerName); v != "" {
|
||||
foundTLSConfig = true
|
||||
envServerName = v
|
||||
}
|
||||
@@ -405,7 +404,7 @@ func parseRateLimit(val string) (rate float64, burst int, err error) {
|
||||
return rate, burst, err
|
||||
}
|
||||
|
||||
// Client is the client to the Boundary API. Create a client with NewClient.
|
||||
// Client is the client to the Threshold API. Create a client with NewClient.
|
||||
type Client struct {
|
||||
modifyLock sync.RWMutex
|
||||
config *Config
|
||||
@@ -413,10 +412,10 @@ type Client struct {
|
||||
|
||||
// NewClient returns a new client for the given configuration.
|
||||
//
|
||||
// If the configuration is nil, Boundary will use configuration from
|
||||
// If the configuration is nil, Threshold will use configuration from
|
||||
// DefaultConfig(), which is the recommended starting configuration.
|
||||
//
|
||||
// If the environment variable `BOUNDARY_TOKEN` is present, the token will be
|
||||
// If the environment variable `THRESHOLD_TOKEN` is present, the token will be
|
||||
// automatically added to the client. Otherwise, you must manually call
|
||||
// `SetToken()`.
|
||||
func NewClient(c *Config) (*Client, error) {
|
||||
@@ -465,9 +464,9 @@ func (c *Client) Addr() string {
|
||||
return c.config.Addr
|
||||
}
|
||||
|
||||
// Sets the address of Boundary in the client. The format of address should
|
||||
// Sets the address of Threshold in the client. The format of address should
|
||||
// be "<Scheme>://<Host>:<Port>". Setting this on a client will override the
|
||||
// value of the BOUNDARY_ADDR environment variable.
|
||||
// value of the THRESHOLD_ADDR environment variable.
|
||||
func (c *Client) SetAddr(addr string) error {
|
||||
c.modifyLock.Lock()
|
||||
defer c.modifyLock.Unlock()
|
||||
@@ -624,7 +623,7 @@ func copyHeaders(in http.Header) http.Header {
|
||||
return ret
|
||||
}
|
||||
|
||||
// NewRequest creates a new raw request object to query the Boundary controller
|
||||
// NewRequest creates a new raw request object to query the Threshold controller
|
||||
// configured for this client. This is an advanced method and generally
|
||||
// doesn't need to be called externally.
|
||||
func (c *Client) NewRequest(ctx context.Context, method, requestPath string, body any, opt ...Option) (*retryablehttp.Request, error) {
|
||||
@@ -762,7 +761,7 @@ func (c *Client) Do(r *retryablehttp.Request, opt ...Option) (*Response, error)
|
||||
return !unicode.IsPrint(c)
|
||||
})
|
||||
if idx != -1 {
|
||||
return nil, fmt.Errorf("configured Boundary token contains non-printable characters and cannot be used")
|
||||
return nil, fmt.Errorf("configured Threshold token contains non-printable characters and cannot be used")
|
||||
}
|
||||
|
||||
if outputCurlString {
|
||||
@@ -848,9 +847,9 @@ func (c *Client) Do(r *retryablehttp.Request, opt ...Option) (*Response, error)
|
||||
"but the client is configured to use TLS. Please either enable TLS\n"+
|
||||
"on the server or run the client with -address set to an address\n"+
|
||||
"that uses the http protocol:\n\n"+
|
||||
" boundary <command> -address http://<address>\n\n"+
|
||||
"You can also set the BOUNDARY_ADDR environment variable:\n\n\n"+
|
||||
" BOUNDARY_ADDR=http://<address> boundary <command>\n\n"+
|
||||
" threshold <command> -address http://<address>\n\n"+
|
||||
"You can also set the THRESHOLD_ADDR environment variable:\n\n\n"+
|
||||
" THRESHOLD_ADDR=http://<address> threshold <command>\n\n"+
|
||||
"where <address> is replaced by the actual address to the controller.",
|
||||
err)
|
||||
}
|
||||
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
// legacyEnvPrefix is the environment variable prefix used by upstream
|
||||
// HashiCorp Boundary. It is still honored as a fallback.
|
||||
legacyEnvPrefix = "BOUNDARY_"
|
||||
// envPrefix is the preferred environment variable prefix for Threshold.
|
||||
envPrefix = "THRESHOLD_"
|
||||
)
|
||||
|
||||
// PreferredEnvName returns the Threshold (THRESHOLD_*) form of an environment
|
||||
// variable name. Names that do not use the legacy BOUNDARY_ prefix are
|
||||
// returned unchanged.
|
||||
func PreferredEnvName(name string) string {
|
||||
if strings.HasPrefix(name, legacyEnvPrefix) {
|
||||
return envPrefix + strings.TrimPrefix(name, legacyEnvPrefix)
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
// LegacyEnvName returns the legacy (BOUNDARY_*) form of an environment
|
||||
// variable name. Names that do not use the THRESHOLD_ prefix are returned
|
||||
// unchanged.
|
||||
func LegacyEnvName(name string) string {
|
||||
if strings.HasPrefix(name, envPrefix) {
|
||||
return legacyEnvPrefix + strings.TrimPrefix(name, envPrefix)
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
// LookupEnv looks up an environment variable, preferring the THRESHOLD_*
|
||||
// name and falling back to the legacy BOUNDARY_* name. The name may be given
|
||||
// with either prefix; names with neither prefix are looked up as-is.
|
||||
func LookupEnv(name string) (string, bool) {
|
||||
if v, ok := os.LookupEnv(PreferredEnvName(LegacyEnvName(name))); ok {
|
||||
return v, true
|
||||
}
|
||||
return os.LookupEnv(LegacyEnvName(name))
|
||||
}
|
||||
|
||||
// Getenv is like os.Getenv but follows the LookupEnv precedence. A set but
|
||||
// empty THRESHOLD_* variable falls through to the legacy BOUNDARY_* variable.
|
||||
func Getenv(name string) string {
|
||||
if v := os.Getenv(PreferredEnvName(LegacyEnvName(name))); v != "" {
|
||||
return v
|
||||
}
|
||||
return os.Getenv(LegacyEnvName(name))
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
package api
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestEnvFallback(t *testing.T) {
|
||||
t.Setenv("THRESHOLD_ZZ_TEST", "")
|
||||
t.Setenv("BOUNDARY_ZZ_TEST", "old")
|
||||
if got := Getenv("BOUNDARY_ZZ_TEST"); got != "old" {
|
||||
t.Fatalf("want old, got %q", got)
|
||||
}
|
||||
t.Setenv("THRESHOLD_ZZ_TEST", "new")
|
||||
if got := Getenv("BOUNDARY_ZZ_TEST"); got != "new" {
|
||||
t.Fatalf("want new, got %q", got)
|
||||
}
|
||||
if got, ok := LookupEnv("THRESHOLD_ZZ_TEST"); !ok || got != "new" {
|
||||
t.Fatalf("want new, got %q %v", got, ok)
|
||||
}
|
||||
if PreferredEnvName("BOUNDARY_ADDR") != "THRESHOLD_ADDR" || LegacyEnvName("THRESHOLD_ADDR") != "BOUNDARY_ADDR" {
|
||||
t.Fatal("name mapping")
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,6 @@ package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
retryablehttp "github.com/hashicorp/go-retryablehttp"
|
||||
@@ -60,15 +59,15 @@ func (d *OutputStringError) parseRequest() {
|
||||
for k, v := range d.Request.Header {
|
||||
for _, h := range v {
|
||||
if strings.ToLower(k) == "authorization" {
|
||||
tokenName := os.Getenv("BOUNDARY_TOKEN_NAME")
|
||||
keyringType := os.Getenv("BOUNDARY_KEYRING_TYPE")
|
||||
tokenName := Getenv("THRESHOLD_TOKEN_NAME")
|
||||
keyringType := Getenv("THRESHOLD_KEYRING_TYPE")
|
||||
switch {
|
||||
case tokenName == "none" || keyringType == "none":
|
||||
h = `Bearer <token>`
|
||||
case tokenName == "" && keyringType == "":
|
||||
h = `Bearer $(boundary config get-token)`
|
||||
h = `Bearer $(threshold config get-token)`
|
||||
default:
|
||||
h = fmt.Sprintf("Bearer $(boundary config get-token -keyring-type %s -token-name %s)", keyringType, tokenName)
|
||||
h = fmt.Sprintf("Bearer $(threshold config get-token -keyring-type %s -token-name %s)", keyringType, tokenName)
|
||||
}
|
||||
}
|
||||
d.parsedCurlString = fmt.Sprintf("%s -H \"%s: %s\"", d.parsedCurlString, k, h)
|
||||
|
||||
Reference in new issue
Block a user