Documentation
¶
Overview ¶
Package api makes authenticated REST calls against Delinea Secret Server (on-prem or cloud) or the Delinea Platform. It performs the OAuth2 token grants itself with net/http — no SDK dependency — and exposes the raw request and response so callers can reach any API endpoint. It is the shared authentication and transport engine behind the delinea-util CLI (its raw verbs, check, and the secrets subcommand group) and can be embedded directly by other Go programs.
Long-running services ¶
Construct one Client per distinct credential at startup and share it — a Client is safe for concurrent use, and constructing one per request rebuilds the transport (and its TLS session state and connection pool) on every call. Token grants are guarded even when this advice is ignored: clients built without Config.Cache share a process-wide token cache, and clients with equivalent grant settings sharing a pointer-valued cache coalesce concurrent grants per credential. Successful grants are reused by later calls while the token remains fresh. A failed grant is shared only by callers waiting on that same in-flight attempt; it is not cached, so a later call tries again. This keeps one concurrent burst from racing an account toward lockout without suppressing recovery after credentials are repaired. Custom transports isolate grants per client. The same startup-constructed shape is what makes tests against secrets/secretstest natural — the two land together.
Index ¶
- Variables
- func CloudURL(tenant, tld string) (string, error)
- func NormalizeURL(raw string, allowInsecureHTTP bool) (string, error)
- func RedactConfigURL(raw string) string
- func ValidateHeaders(h http.Header) error
- type Backend
- type BufferedResponse
- type CacheKey
- type CachedToken
- type Client
- func (c *Client) Authenticate(ctx context.Context) (string, error)
- func (c *Client) CloseIdleConnections()
- func (c *Client) DiagnosticSnippet(body []byte) string
- func (c *Client) Do(ctx context.Context, r Request) (*Response, error)
- func (c *Client) DoBufferedResponse(ctx context.Context, r Request, limit int64) (*BufferedResponse, error)
- func (c *Client) GoString() string
- func (c *Client) InteractiveLogin(ctx context.Context, prompt Prompter) (string, error)
- func (c *Client) String() string
- func (c *Client) Target() Target
- func (c *Client) Token(ctx context.Context) (string, error)
- func (c *Client) VaultURL(ctx context.Context) (*url.URL, error)
- func (c *Client) VaultURLByID(ctx context.Context, id string) (*url.URL, error)
- func (c *Client) Vaults(ctx context.Context) ([]Vault, error)
- type CompareEvicter
- type Config
- type Mechanism
- type Prompter
- type Request
- type Response
- type Target
- type TokenCache
- type Vault
- type VaultConnection
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( ErrConfig = errors.New("invalid configuration") ErrAuth = errors.New("authentication failed") ErrAccessDenied = errors.New("access denied") ErrVault = errors.New("vault discovery failed") ErrTransport = errors.New("transport error") ErrTimeout = errors.New("timed out") )
Sentinel errors, matched with errors.Is. A completed HTTP response is never an error: Do returns a Response for any status code, and these cover only configuration, authentication, vault-discovery, and transport failures.
Functions ¶
func CloudURL ¶
CloudURL builds the base URL of a Secret Server Cloud tenant — https://{tenant}.secretservercloud.{tld} — from the tenant name and top-level domain that tss-sdk-go configurations carry as Tenant and TLD, so those configurations migrate mechanically. An empty tld means "com" (the SDK's default). The tld must name a Delinea cloud region (the same set the vault trust policy accepts): com, eu, com.au, com.sg, ca, co.uk, ae. The tenant must be a bare DNS label, not a URL or hostname.
func NormalizeURL ¶
NormalizeURL turns the base-URL spellings integration configs actually contain into the canonical form Config.URL wants, and rejects the unsafe ones. A bare host gains https://; trailing slashes and surrounding space are dropped; userinfo, query, and fragment are refused. The scheme is compared case-insensitively, so HTTP:// cannot slip past the check that http:// fails — plaintext http discloses the credential on the first request and is allowed only for a loopback host or when allowInsecureHTTP says the operator accepted that risk explicitly.
func RedactConfigURL ¶
RedactConfigURL preserves a valid origin while hiding components that commonly carry credentials (userinfo, query, fragment). A URL that cannot be parsed safely is hidden in full. It is the one redactor both api.Config and secrets.Config format through, so their safe-logging guarantee cannot drift.
func ValidateHeaders ¶
ValidateHeaders applies the same wire-level rules Config.Header and Request.Header must satisfy. Returned errors identify a rejected header by name but never reproduce its values, which may contain gateway credentials.
Types ¶
type Backend ¶
type Backend string
Backend is which Delinea service answers at a URL. It is what Target must agree with -- Target decides which token grant is performed and how the credentials are interpreted -- so it is the first thing to establish when authentication fails against the wrong kind of host.
func ProbeBackend ¶
ProbeBackend reports which service answers at cfg.URL: the Secret Server health endpoint is tried first, then the Platform one. It sends configured same-origin routing headers except Authorization, but ignores every Delinea credential field on cfg. Config.Header may itself authenticate to a same-origin gateway; it is the routing layer needed to reach the health endpoint, not the Delinea credential the probe is intended to withhold.
type BufferedResponse ¶
BufferedResponse is a completed response whose body has been read and closed. DiagnosticSnippet binds redaction to the bearer token actually sent on this response, so later token rotations cannot expose it.
func (*BufferedResponse) DiagnosticSnippet ¶
func (r *BufferedResponse) DiagnosticSnippet() string
DiagnosticSnippet returns this response body as a bounded, single-line diagnostic with the exact request bearer token redacted. Call it on the pointer DoBufferedResponse returned; a copied value has no binding and fails closed.
type CacheKey ¶
CacheKey identifies one credential's token. CredentialDigest is an HMAC of the credential secret under a process-random key: a credential change invalidates in-memory entries, and the digest is meaningless outside this process. CacheKey and CachedToken values must not be persisted: the former carries credential identity metadata and the latter contains a live bearer credential.
type CachedToken ¶
type CachedToken struct {
AccessToken string
TokenType string
ObtainedAt time.Time
ExpiresAt time.Time
}
CachedToken is one stored grant. Client validates AccessToken again when an entry is loaded, so malformed data from a custom cache is never admitted as a bearer credential.
func (CachedToken) Fresh ¶
func (t CachedToken) Fresh(now time.Time) bool
Fresh reports whether the token is safely reusable at now: inside 90% of its lifetime and clear of expiry by a minute — or by a tenth of the lifetime when that is shorter, so a token living less than ten minutes (a 60-second expires_in is a real Secret Server configuration) is still reusable rather than stale the instant it is stored.
func (CachedToken) GoString ¶
func (t CachedToken) GoString() string
GoString makes %#v redact exactly as String does.
func (CachedToken) MarshalJSON ¶
func (t CachedToken) MarshalJSON() ([]byte, error)
MarshalJSON redacts the AccessToken, mirroring Config: a CachedToken cannot round-trip a live bearer onto disk through a JSON encoder (structured loggers included). A cache that legitimately needs the value reads the field directly.
func (CachedToken) String ¶
func (t CachedToken) String() string
String and GoString redact the AccessToken so a CachedToken logged through the fmt verbs never emits the bearer. CachedToken crosses the public TokenCache boundary into consumer code, which may format it while debugging a cache.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client authenticates against one Delinea target and performs API calls. It is safe for concurrent use.
func New ¶
New validates cfg and builds a client with its own transport; it never mutates http.DefaultTransport and performs no network I/O. Header, CACert, and AllowedVaultHosts are copied, so mutating them after New returns has no effect on the client (a per-request header belongs in Request.Header); Transport, Backoff, and Cache are retained by reference and must stay valid for the client's lifetime.
func (*Client) Authenticate ¶
Authenticate verifies that this client's credential is accepted and returns the bearer token for reuse. Username/password and client credentials are verified by a token grant performed during this call (and shared by callers in the same concurrent wave) — a fresh, memoized, or cached token from an earlier call is deliberately not enough, since it may have been granted under a credential that has since been rotated or revoked. A pre-obtained token requires one additional, read-only request because returning the configured string proves nothing: Secret Server uses the current-user endpoint and Platform uses the vault inventory endpoint. A configured token therefore needs an explicit target.
func (*Client) CloseIdleConnections ¶
func (c *Client) CloseIdleConnections()
CloseIdleConnections closes connections held idle by the underlying transport. It does not interrupt active requests, and the Client remains usable. If Config.Transport is shared, this affects every client using that transport's idle connection pool.
func (*Client) DiagnosticSnippet ¶
DiagnosticSnippet renders server-controlled diagnostic text without allowing it to reflect this client's configured credentials or current bearer token into a terminal or CI log. For a body returned by Do or DoBufferedResponse, prefer the response's DiagnosticSnippet method: it also covers the exact token sent on that request after any number of later rotations. The client deliberately does not retain obsolete tokens: without a response identity, arbitrary bytes cannot be attributed to the old request that produced them.
func (*Client) Do ¶
Do performs one authenticated API call. It returns a Response for any HTTP status code; errors are reserved for configuration, authentication, vault discovery, and transport failures.
Example ¶
A Secret Server call: authenticate with the password grant and fetch one secret. Do returns a Response for any HTTP status; errors are reserved for configuration, authentication, and transport failures.
package main
import (
"context"
"encoding/json"
"fmt"
"log"
"net/http"
"os"
"github.com/DelineaXPM/delinea-common/api"
)
func main() {
client, err := api.New(api.Config{
URL: "https://acme.secretservercloud.com",
Username: "svc-api",
Password: os.Getenv("SS_PASSWORD"),
})
if err != nil {
log.Fatal(err)
}
resp, err := client.Do(context.Background(), api.Request{
Method: http.MethodGet,
Path: "/api/v1/secrets/126",
})
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
log.Fatalf("secret fetch failed: %s", resp.Status)
}
var secret struct {
ID int `json:"id"`
}
if err := json.NewDecoder(resp.Body).Decode(&secret); err != nil {
log.Fatal(err)
}
fmt.Println("fetched secret", secret.ID)
}
Output:
Example (PlatformVault) ¶
A Delinea Platform call routed to the tenant's Secret Server vault: the client-credentials grant runs against the platform, the vault broker discovers the vault URL, and UseVault sends the request there with the same bearer token.
package main
import (
"context"
"encoding/json"
"fmt"
"log"
"net/http"
"os"
"github.com/DelineaXPM/delinea-common/api"
)
func main() {
client, err := api.New(api.Config{
URL: "https://acme.secureplatform.io",
ClientID: os.Getenv("PLATFORM_CLIENT_ID"),
ClientSecret: os.Getenv("PLATFORM_CLIENT_SECRET"),
})
if err != nil {
log.Fatal(err)
}
resp, err := client.Do(context.Background(), api.Request{
Method: http.MethodGet,
Path: "/api/v1/secrets/4",
UseVault: true,
})
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
log.Fatalf("secret fetch failed: %s", resp.Status)
}
var secret struct {
ID int `json:"id"`
}
if err := json.NewDecoder(resp.Body).Decode(&secret); err != nil {
log.Fatal(err)
}
fmt.Println("fetched secret", secret.ID)
}
Output:
func (*Client) DoBufferedResponse ¶
func (c *Client) DoBufferedResponse(ctx context.Context, r Request, limit int64) (*BufferedResponse, error)
DoBufferedResponse performs the request like Do but returns at most limit response-body bytes, read within the retry loop, so a body read that fails before that limit is retried on the same budget as a transport or status failure — one loop, Retry-After honored once, no outer retry to compound with. To classify Secret Server's bounded expired-token 403, the engine may inspect up to secretServerExpiredTokenBodyLimit+1 bytes independently of the returned limit; an error encountered only in that extra inspection does not change the caller's completed bounded response. A Secret Server HEAD receiving 403 may make one read-only current-user request to confirm that bodyless response before recovery. The body is returned already read and the connection released. The response keeps credential-redaction context bound to the exact request token, so rendering its body in a diagnostic cannot leak another call's token. Callers that stream a large body use Do instead; the secrets resolver and vault discovery use this.
func (*Client) InteractiveLogin ¶
InteractiveLogin authenticates cfg.Username against the platform's Identity API (StartAuthentication / AdvanceAuthentication) and returns the resulting bearer token. Config.Target must be TargetPlatform; other targets are rejected before any request. This is the path for MFA-gated accounts (e.g. cloudadmin@tenant) that the OAuth2 grants cannot serve, because those grants cannot answer an MFA challenge. Redirect-based federated (external IdP / SSO) logins are not supported: a redirect from StartAuthentication is refused below. The password (UP) mechanism is answered from cfg.Password; every other challenge is delegated to prompt. The token is returned, not cached; pass it as Config.Token to later clients.
func (*Client) String ¶
String and GoString render the Client through Config's redaction. Config is held in the unexported cfg field, so fmt cannot invoke Config.String on it and would otherwise format the struct reflectively — printing Password, ClientSecret, and Token verbatim. A Client is the value an embedder is most likely to log (%+v), so it carries the same redaction guarantee as Config.
func (*Client) Target ¶
Target reports the resolved token grant for this client (ss, platform, or empty when only a pre-obtained Token was supplied).
func (*Client) Token ¶
Token returns the bearer token for this client, performing the configured grant (or loading the configured cache) on first use. A token near expiry is replaced with a fresh grant, so a long-lived client keeps working past its first token's lifetime.
Example ¶
Token exposes the bearer directly, for callers that make their own HTTP requests or hand the token to another tool.
package main
import (
"context"
"log"
"net/http"
"os"
"github.com/DelineaXPM/delinea-common/api"
)
func main() {
client, err := api.New(api.Config{
URL: "https://acme.secretservercloud.com",
Username: "svc-api",
Password: os.Getenv("SS_PASSWORD"),
})
if err != nil {
log.Fatal(err)
}
token, err := client.Token(context.Background())
if err != nil {
log.Fatal(err)
}
req, err := http.NewRequest(http.MethodGet, "https://acme.secretservercloud.com/api/v1/version", nil)
if err != nil {
log.Fatal(err)
}
req.Header.Set("Authorization", "Bearer "+token)
_ = req
}
Output:
func (*Client) VaultURL ¶
VaultURL discovers, validates, and memoizes the platform's default active vault URL for five minutes. After that it synchronously refreshes the route; a refresh failure is returned rather than using expired routing data.
func (*Client) VaultURLByID ¶
VaultURLByID discovers, validates, and memoizes the URL of a specific vault by its vaultId for five minutes, for callers that must reach a non-default vault. The URL is held to the same refresh and trust policy as the default. An empty id is refused rather than read as "the default": a caller passing through an unset configured ID must learn the configuration is incomplete, not silently route to the wrong vault (VaultURL is the way to ask for the default).
type CompareEvicter ¶
type CompareEvicter interface {
TokenCache
// EvictMatching removes key if and only if its currently stored token
// equals token, as one atomic step.
EvictMatching(key CacheKey, token string)
}
CompareEvicter is a TokenCache that can evict a key atomically — only while its stored token still equals a given value. When a Client discards a token a server rejected, it drops that token from the cache; doing so with a plain Load then Evict can race with another Client that stored a fresh token in the gap and delete the fresh one, forcing a needless re-grant. A cache that implements CompareEvicter closes that race; one that does not gets the best-effort two step. The built-in NewMemoryCache implements it, so a custom cache only needs to when several Clients share it concurrently and the occasional redundant grant matters.
type Config ¶
type Config struct {
URL string
Target Target
// AllowInsecureHTTP permits plaintext HTTP to a non-loopback host. Leave it
// false unless an operator has explicitly accepted that the credential and
// every API response will cross the network without TLS protection.
AllowInsecureHTTP bool
Username string
Password string
Domain string // optional AD domain (on-prem Secret Server only)
ClientID string
ClientSecret string
Token string // pre-obtained bearer token; when set no grant is performed
CACert []byte // optional PEM bundle of trusted roots, added to the system trust store rather than replacing it
// SkipTLSVerify disables TLS verification for this client's transport only.
// Unlike the CLIs, embedding this package emits no warning when it is set —
// the caller is responsible for confining it to a context where a
// machine-in-the-middle is not a concern.
SkipTLSVerify bool
Timeout time.Duration // header deadline and body idle limit per request (default 30s)
Retries int // attempts, on transport errors/timeouts and 408/429/500/502/503/504, for GET/HEAD and the token grant (a completed grant answer is never replayed); default 3
// Transport, when set, is the base RoundTripper for this client's requests
// — an escape hatch for a client TLS certificate (mTLS), a custom dialer, or
// bespoke proxy logic. Setting it hands TLS entirely to the caller: this
// package no longer configures roots or verification, so a transport with
// InsecureSkipVerify or an empty root pool is used as-is. It is therefore an
// error to combine Transport with CACert or SkipTLSVerify. The cross-origin
// redirect refusal still applies (it lives on the http.Client).
//
// Sharing one Transport across clients also shares its connection pool —
// what a service holding many credentials against one server wants. The
// combination rule above bounds that: because a shared Transport owns TLS,
// clients whose servers need different private CAs cannot share one; give
// each its own CACert (and accept a pool per client) instead.
// A custom Transport disables token caching because its authentication
// behavior is opaque to the package.
//
// Clients without Transport clone the process default as it existed when
// this package initialized. Later in-place changes to http.DefaultTransport
// are deliberately ignored; pass the changed transport here explicitly so
// its opaque grant boundary is enforced.
Transport http.RoundTripper `json:"-"`
// Header is merged into every request sent to the primary target's origin.
// It is deliberately NOT sent to a vault discovered on a different host, so
// a header meant for a gateway in front of the platform cannot leak to a
// third-party vault; use Request.Header to target a vault call. A
// per-request Request.Header value for the same key wins, and an
// Authorization entry here is ignored — the client always sets it last.
Header http.Header
// Backoff overrides the retry backoff (attempt is 0-based). Nil uses an
// exponential default.
Backoff func(attempt int) time.Duration `json:"-"`
// Cache shares bearer tokens across Clients. Nil means a process-wide
// shared memory cache (see NewMemoryCache), so code that constructs a
// Client per operation does not also perform a token grant per operation —
// the zero value is the safe value. Clients with equivalent grant settings
// sharing one cache instance also coalesce concurrent grants per credential.
// Cross-client coalescing requires a pointer-valued custom cache so instances
// have an unambiguous identity; value-valued caches still share completed
// entries but degrade to per-client coalescing. An opaque transport, whether
// supplied in Config or installed as http.DefaultTransport, disables caching;
// combining one with an explicit Cache is an error. Set DisableCache to opt
// out explicitly. A custom implementation must remain process-local and must
// not persist entries; see TokenCache.
Cache TokenCache `json:"-"`
// DisableCache turns off token caching for this client: every client
// grants its own token and nothing is shared or reused across clients.
// Combining it with an explicit Cache is a configuration error.
DisableCache bool
// Logger, when set, receives operational events: token grant outcomes,
// request retries, vault discovery, and discarded cache entries. Nil is
// silent — the default a CLI wants; a long-running service passes its own
// handler to see why a call was slow or a credential refused. Events
// carry metadata and, on a failed grant, the bounded credential-redacted
// snippet of the token endpoint's error response; never a credential, a
// request body, a successful response body, or a URL query string. Error
// details from an opaque caller-supplied transport are suppressed because
// arbitrary transport code may derive them from a request or response body.
Logger *slog.Logger `json:"-"`
// AllowedVaultHosts lists extra hosts trusted for discovered vault URLs.
// A hostname without a port trusts only HTTPS port 443; trust an alternate
// port by listing the exact host:port.
AllowedVaultHosts []string
}
Config holds connection and credential settings. A pre-obtained Token takes precedence over the grant credential fields; when Token is empty, exactly one grant style applies: Username/Password for Secret Server or ClientID/ClientSecret for the Delinea Platform. Token must be at least four bytes; shorter values are rejected as configuration errors.
func (Config) MarshalJSON ¶
MarshalJSON emits the Config with credentials and header values replaced by "[REDACTED]". JSON encoders (structured loggers included) never see those values, and a marshaled Config cannot round-trip them onto disk by design. Decoding a configuration file into Config is unaffected; Transport, Backoff, Cache, and Logger are not serializable and are skipped.
func (Config) String ¶
String renders credential-bearing fields safely, so a Config logged through the fmt verbs — including %+v of a struct that embeds one — never emits a credential. Header values are redacted and opaque extension points omitted.
func (Config) WithProbedTarget ¶
WithProbedTarget resolves TargetAuto by asking the server what it is, for the one-credential-pair shape CI integrations carry: an id/secret that is a Secret Server username/password on one tenant and a Platform client_id/client_secret on another. Give the pair in either field pair; the probe decides which grant it is, and the returned Config carries the pair in the fields that grant reads. An explicit Target returns the Config unchanged, so this is safe to call unconditionally; setting both pairs is ambiguous and refused, exactly as New would. The probe sends no Delinea credential, but does send configured same-origin gateway headers. One probe per constructed Config — cache the result, not the call.
type Mechanism ¶
type Mechanism struct {
// MechanismID is the opaque protocol identifier echoed back when answering.
MechanismID string `json:"MechanismId"`
// Name is the mechanism kind — e.g. UP, EMAIL, SMS, OATH — a match key.
Name string `json:"Name"`
// AnswerType is how the mechanism is answered; a value containing "Oob"
// marks an out-of-band challenge (an emailed link or code, or a push).
AnswerType string `json:"AnswerType"`
// PromptSelectMech is the human-facing label to show when offering this
// mechanism among others.
PromptSelectMech string `json:"PromptSelectMech"`
// PromptMechChosen is the human-facing message to show once this mechanism
// is chosen.
PromptMechChosen string `json:"PromptMechChosen"`
}
Mechanism is one way to satisfy an Identity API authentication challenge, e.g. UP (password), EMAIL, SMS, OTP, OATH, PF, SQ. A Prompter matches on the protocol identifiers (Name, MechanismID, AnswerType) and displays the human-facing prompts (PromptSelectMech, PromptMechChosen).
type Prompter ¶
type Prompter interface {
// ChooseMechanism picks one of mechs (always two or more) and returns
// its index.
ChooseMechanism(mechs []Mechanism) (int, error)
// ReadAnswer returns the user's response to prompt, an MFA code. For an
// out-of-band mechanism (emailed link, push), returning "" polls for
// completion instead of answering.
ReadAnswer(prompt string) (string, error)
}
Prompter supplies the interactive answers InteractiveLogin cannot derive from configuration. Callback error identity remains available through errors.Is and errors.As, but callback error text is treated as opaque and is not included in the error returned by InteractiveLogin.
type Request ¶
type Request struct {
Method string
Path string
Header http.Header
// Body is read fully into memory before the call (so a GET/HEAD can be
// replayed on retry), so it is not suited to streaming a very large upload.
// A Body whose Read can block must also implement io.Closer: cancellation
// closes it to unblock preparation. A non-closable Body must return from Read
// promptly for the request context to bound the whole call.
Body io.Reader
UseVault bool
VaultID string
}
Request is one API call. Path is absolute on the target and may carry a query string. UseVault routes the call to the platform's default vault, discovered through the vault broker, with the same bearer token; setting VaultID alongside it routes to that specific vault instead of the default.
type Response ¶
type Response struct {
StatusCode int
Status string
Proto string
Header http.Header
Body io.ReadCloser
}
Response is the completed HTTP response. Body is streamed; the caller must close it.
func (*Response) DiagnosticSnippet ¶
DiagnosticSnippet returns body as a bounded, single-line diagnostic with the exact request bearer token redacted. It is intended for bytes read from this response's streamed Body. Call it on the Response pointer returned by Do; a copied Response value has no binding and fails closed.
type TokenCache ¶
type TokenCache interface {
Load(key CacheKey) (CachedToken, bool)
Store(key CacheKey, tok CachedToken)
Evict(key CacheKey)
}
TokenCache stores bearer tokens outside a single Client, so several Clients for the same identity can share the result of one grant: when a Client's own token expires, it loads a token another already obtained rather than granting afresh. Clients with equivalent grant settings sharing the same pointer-valued cache also coalesce concurrent grants; a value-valued custom cache shares completed entries but cannot safely identify an instance for a cross-client in-flight grant. An opaque custom transport disables grant caching. NewMemoryCache is the provided implementation; callers may supply their own. Implementations must be process-local, must not persist CacheKey or CachedToken values, and must be safe for concurrent use. Store is best-effort; implementations must contain their own failures because a failing cache must never fail the call.
func NewMemoryCache ¶
func NewMemoryCache() TokenCache
NewMemoryCache returns a process-lifetime TokenCache for sharing across Clients, capped at 1024 entries with stale entries purged on overflow.
Example ¶
A shared in-memory cache lets many short-lived Clients reuse one token grant per identity for the life of the process; nothing is written to disk, and a rotated credential invalidates its entry immediately.
package main
import (
"context"
"fmt"
"log"
"net/http"
"os"
"github.com/DelineaXPM/delinea-common/api"
)
func main() {
cache := api.NewMemoryCache()
cfg := api.Config{
URL: "https://acme.secretservercloud.com",
Username: "svc-api",
Password: os.Getenv("SS_PASSWORD"),
Cache: cache,
}
for _, path := range []string{"/api/v1/users/current", "/api/v1/folders"} {
client, err := api.New(cfg)
if err != nil {
log.Fatal(err)
}
resp, err := client.Do(context.Background(), api.Request{Method: http.MethodGet, Path: path})
if err != nil {
log.Fatal(err)
}
resp.Body.Close()
client.CloseIdleConnections()
fmt.Println(path, resp.Status)
}
}
Output:
type Vault ¶
type Vault struct {
VaultID string `json:"vaultId"`
Name string `json:"name"`
Type string `json:"type"`
IsDefault bool `json:"isDefault"`
IsGlobalDefault bool `json:"isGlobalDefault"`
IsActive bool `json:"isActive"`
Connection VaultConnection `json:"connection"`
}
Vault is one entry from the platform vault broker's inventory.
type VaultConnection ¶
type VaultConnection struct {
URL string `json:"url"`
}
VaultConnection carries the vault's Secret Server base URL.