Skip to content

Commit

Permalink
Squashed 'keyconjurer-v2/' changes from be45b54..69d489f
Browse files Browse the repository at this point in the history
69d489f Apply formatting changes
249bab4 Add missing articles
df88087 Add Linux usage
fb27555 Update MacUsage.md (RiotGames#102)
5450ae6 Add new frontend with new instructions (RiotGames#101)
bdf33e5 Don't parse the updated_at field
9270394 Open a browser by default when logging in
6cabb2c Ensure account iteration order is stable
51b6b06 Return a HTTP 500 if Okta has a problem
8913eaa Improve keyconjurer accounts output
85f224a YubiKey support (RiotGames#98)
REVERT: be45b54 Remove unused return value
REVERT: b66a276 Run go test
REVERT: 6aa2105 Remove unnecessary refs that are breaking PR builds
REVERT: 10156de Conform to gorevives suggestions
REVERT: ba36b5b Strip symbols
REVERT: 68ff0dd Add the kitchensink module
REVERT: c31df25 terraform fmt
REVERT: 4d853f5 Move frontend to its own module
REVERT: b5b0040 Remove KMS policy
REVERT: 3531287 Add a load balancer module
REVERT: 4162a4f Oops
REVERT: 8fe40c3 Correct CLI_TARGETS
REVERT: e939fc0 Reduce copying
REVERT: 8f5d0fe Remove unnecessary quote
REVERT: 89d03e8 Fold client/makefile into root
REVERT: dee9d34 simplify Makefile a bit
REVERT: d3a8858 Tidy up Makefile
REVERT: 202b371 Fold frontend makefile into root
REVERT: 27883e5 Fix up Frontend Makefile
REVERT: a5ba274 Remove broken target
REVERT: a4cd0f6 Rename Makefile
REVERT: f467a1d Merge terraform makefile into root
REVERT: ef97642 Remove unused value
REVERT: 18296d1 Move Lambda function into its own module
REVERT: 9ec3b05 Use a temporary dir for building this target
REVERT: 4e2436e Remove note on legacy API
REVERT: 4d85d5c fixup! Move lambda function to lambda/
REVERT: d42f0d5 Remove unused function
REVERT: d26e60c Consolidate further
REVERT: 904f522 Fold cloud.go into cli/ folder
REVERT: d45aa3d Move lambda function to lambda/
REVERT: 4188119 Remove unused code
REVERT: 31655c2 Go mod tidy
REVERT: 764843e Consolidate pkg/ dir into internal/ directory
REVERT: b7f7235 Remove local copy of the coreos-oidc dependency
REVERT: 25fec03 Remove old cloud.Provider struct
REVERT: 371d092 Remove legacy auth providers
REVERT: f5dac64 Remove logrus
REVERT: 6494834 Modernize settings
REVERT: 6745a6f Remove the legacy API
REVERT: 849ba0a Allow users to provide flags through KEYCONJURERFLAGS
REVERT: 8159c2e Update README
REVERT: dd16f4b Use a single const for the build timestamp
REVERT: fd0649d Remove OneLogin test
REVERT: 1928a93 Only require env variables for build target
REVERT: 4f0dbf5 Don't rely on the context for the config & path
REVERT: c0c49ef Refactor get
REVERT: 4bb065d oops
REVERT: b89ad28 Don't use configinfo outside of context
REVERT: 655973b Remove appname
REVERT: 2e258c2 Remove notes
REVERT: 2980f1c Use buffers in test
REVERT: 7bd0158 Add function for resolving credentials file
REVERT: fa00d5c Simplify section managemnet
REVERT: b23eac8 Remove ~/.aws/config management
REVERT: f60f16f Use filepath instead of fmt Sprintf
REVERT: ecdb9d1 use t.Setenv for environment variables
REVERT: d5d3c90 Remove pipe
REVERT: 64f0529 Store the type of credentials within the creds
REVERT: 584b7e3 allow user to only output the URL
REVERT: ea246e6 Provide a better error message if Okta screws up
REVERT: 43cfa6a add server address const
REVERT: ebbf97b add the correct ID for the application
REVERT: c34d56a fix bypassing cache
REVERT: 5d6788a Correctly set headers
REVERT: b97ed75 Write errors in ServeJSON to log
REVERT: 3180045 Fix a bug where headers werent canonized
REVERT: a4e17a8 Assume headers are lowercase
REVERT: 2e80e39 apply the Oauth2 header ourselves
REVERT: 69bd103 Ensure a status code is set
REVERT: ded014f use http.Header.Get() rather than accessing the map
REVERT: e135a86 squash more bugs
REVERT: a717af6 add status messages
REVERT: 4ff8b00 add listener rule
REVERT: 13128ca add a trailing slash
REVERT: 9773a92 correct typo
REVERT: 997e0b1 fix broken xargs instruction
REVERT: d737cbf no longer support legacy ids
REVERT: 6c7646d Fix a bug where executing a command would brick existing config
REVERT: 4fc7636 Add the ability to bypass account cache
REVERT: 4374fdd Don't use global variables for flags
REVERT: c6bccbd Remove global quiet variable
REVERT: 983c5b8 Pass configuration in context
REVERT: 36c368e Simplify get
REVERT: bc065ff Use AWS provider directly
REVERT: e4068d6 Remove OneLogin
REVERT: d045ae4 Don't use global variables for new flags
REVERT: 742936c Immediately exit if --no-refresh specified
REVERT: 03ce54b Move RequestAttrs to http
REVERT: 177f761 Move serverless function to the serverless functions file
REVERT: b199a29 Don't pre-allocate a size
REVERT: 78138f4 All target must be first
REVERT: 8d270e4 Correctly upload all files
REVERT: fe124d8 Provide secrets to the new Lambda function
REVERT: ac30889 Tag new API with lambda.norpc
REVERT: a0e3b9d Use provided.al2 for the new function
REVERT: 7e61d24 Modernize Makefile
REVERT: c7910b9 Move new endpoint to distinguish it from legacy ones
REVERT: e00f286 use CSV
REVERT: 7859f5a Only enumerate Tencent or Amazon apps
REVERT: e80025e Correctly list applinks for user
REVERT: a3ee0ff Correctly fetch the username from the token
REVERT: 1322b31 Oops
REVERT: dad0fc0 fix visual errors with error reporting
REVERT: c47f278 Reduce nesting
REVERT: fe0e1e4 Call the KeyConjurer API instead of the Okta one
REVERT: a29f435 Allow user to disable refreshing of accounts
REVERT: d350649 Rename config path
REVERT: e205e49 Improve logging and add to testserver
REVERT: 9ccb6bd Add implementation of the new function
REVERT: 7b48b69 Move Lambdaify out of main
REVERT: 97c7beb add lambda <-> net/http translation layer
REVERT: b4d9398 Add skeleton for new required endpoint
REVERT: f7d2ddc Update Port
REVERT: 66cbb19 move fetching accounts into a function
REVERT: b2677bf Remove legacy accommodations
REVERT: 5e085c1 Correct set the timeout
REVERT: 2510385 Remove QR code device flow
REVERT: 216d1d7 Use context for timeouts
REVERT: aaf3f64 Add new versino of Cobra
REVERT: a8c8706 Add CLIENT_ID and OIDC_DOMAIN to Makefile
REVERT: 9c0a16c Simplify version flags
REVERT: d1ec64b Remove host flag
REVERT: 7a26205 Use consts file for client ID and OIDC domain
REVERT: 3a1dea7 Modify download command to use http.Client for non windows systems
REVERT: b38aeef We no longer store credentials
REVERT: df593b6 add a working roles command
REVERT: 639879d Implement Role & Provider finding
REVERT: 3251c26 Reinstate alias resolution
REVERT: efacea6 add logging to all requests we issue
REVERT: fd0a05e Add basic request monitoring
REVERT: dec08fe add slog
REVERT: cecf8b7 Add HTTP logging middleware
REVERT: 245af7a Remove base package
REVERT: 2183f57 Remove unused flag
REVERT: c1d4a9a Remove references to the API project from the client
REVERT: 1cb0884 Fix warnings
REVERT: 9068fa6 Remove unsupported roles command
REVERT: 7a2b62c Remove deprecated API calls
REVERT: a9ad856 Move cloud handlers to internal
REVERT: a549fd8 Correctly exchange the SAML assertion for tokens
REVERT: 56ae358 Return the session token when acquired
REVERT: ceb95e0 Add "hidden" scope which enables the token exchange endpoint
REVERT: b7be128 add some notes
REVERT: 01dd811 fixup! WIP add access token exchange
REVERT: 2e71142 WIP add access token exchange
REVERT: 905f278 Move oauth2 stuff to.. oauth2
REVERT: 936c3b0 Remove old method of interacting with Okta here
REVERT: 5ab579a Catch token expiry
REVERT: 072801b Remove bad check
REVERT: 884f6b1 Go mod tidy
REVERT: afe05bf Display a QR code to the user
REVERT: bf84d14 add qr terminal
REVERT: 7372508 Correctly render accounts
REVERT: 2c2ec53 Add helper method to identify that tokens have expired
REVERT: 39256f2 Correctly load and store the oauth tokens
REVERT: 9e13414 Move OIDC stuff to its own package
REVERT: 13976e7 Go mod tidy
REVERT: 665bc58 Correctly implement the device flow for Okta
REVERT: 3a292fc Add oauth2device
REVERT: 3690d08 Remove list providers command
REVERT: d399cc0 Move OAuth2 functionality to oauth2.go
REVERT: f665295 Split Login functionality into its own method
REVERT: eab9cb7 Correctly generate random values
REVERT: 2bc0394 Implement callback handling
REVERT: b53e4c1 Add the OAuth2 flow skeleton for logging in
REVERT: 45466db add oidc library
REVERT: 5099552 Add Oauth2 library

git-subtree-dir: keyconjurer-v2
git-subtree-split: 69d489f
  • Loading branch information
punmechanic committed Nov 7, 2023
1 parent 8ce6fac commit 6532079
Show file tree
Hide file tree
Showing 51 changed files with 19,846 additions and 2,997 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# G
# Manual additions
*.auto.tfvars
dev.env
Expand Down Expand Up @@ -277,3 +278,4 @@ $RECYCLE.BIN/
cli/keyconjurer-darwin*
cli/keyconjurer-linux*
cli/keyconjurer-windows.exe
vendor
5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

RELEASE ?= dev
VERSION ?= $(shell git rev-parse --short HEAD)
# This runs on Linux machines. Mac users should override TIMESTAMP.
TIMESTAMP ?= $(shell date --iso-8601=minutes)

## Standard targets for all Makefiles in our team

Expand Down Expand Up @@ -33,7 +35,6 @@ frontend/build/index.html: frontend/node_modules
cd frontend && \
REACT_APP_VERSION='$$(git rev-parse --short HEAD)-$(RELEASE)' \
REACT_APP_API_URL=${API_URL} \
REACT_APP_BINARY_NAME=${BINARY_NAME} \
REACT_APP_DOCUMENTATION_URL=${REACT_APP_DOCUMENTATION_URL} \
REACT_APP_CLIENT=webUI npm run-script build

Expand Down Expand Up @@ -66,7 +67,7 @@ cli/keyconjurer:
-X main.Version=$(shell git rev-parse --short HEAD)-$(RELEASE) \
-X main.ClientID=$(CLIENT_ID) \
-X main.OIDCDomain=$(OIDC_DOMAIN) \
-X main.BuildTimestamp='$(shell date --iso-8601=minutes)' \
-X main.BuildTimestamp='$(TIMESTAMP)' \
-X main.ServerAddress=$(SERVER_ADDRESS)" \
-o $(BUILD_TARGET)

Expand Down
10 changes: 6 additions & 4 deletions cli/accounts.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ var (

func init() {
accountsCmd.Flags().Bool(FlagNoRefresh, false, "Indicate that the account list should not be refreshed when executing this command. This is useful if you're not able to reach the account server.")
// TODO: Replace the address
accountsCmd.Flags().String(FlagServerAddress, ServerAddress, "The address of the account server. This does not usually need to be changed or specified.")
}

Expand All @@ -34,11 +33,14 @@ var accountsCmd = &cobra.Command{
config := ConfigFromCommand(cmd)
stdOut := cmd.OutOrStdout()
noRefresh, _ := cmd.Flags().GetBool(FlagNoRefresh)
loud := !ShouldUseMachineOutput(cmd.Flags())
if noRefresh {
config.DumpAccounts(stdOut)
if q, _ := cmd.Flags().GetBool(FlagQuiet); !q {
config.DumpAccounts(stdOut, loud)

if loud {
cmd.PrintErrf("--%s was specified - these results may be out of date, and you may not have access to accounts in this list.\n", FlagNoRefresh)
}

return nil
}

Expand Down Expand Up @@ -70,7 +72,7 @@ var accountsCmd = &cobra.Command{
}

config.UpdateAccounts(accounts)
config.DumpAccounts(stdOut)
config.DumpAccounts(stdOut, loud)
return nil
},
}
Expand Down
29 changes: 23 additions & 6 deletions cli/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"io"
"os"
"path/filepath"
"sort"
"time"

"strings"
Expand Down Expand Up @@ -73,8 +74,18 @@ func generateDefaultAlias(name string) string {
}

func (a *accountSet) ForEach(f func(id string, account Account, alias string)) {
for id, acc := range a.accounts {
f(id, *acc, acc.Alias)
// Golang does not maintain the order of maps, so we create a slice which is sorted instead.
var accounts []*Account
for _, acc := range a.accounts {
accounts = append(accounts, acc)
}

sort.SliceStable(accounts, func(i, j int) bool {
return accounts[i].Name < accounts[j].Name
})

for _, acc := range accounts {
f(acc.ID, *acc, acc.Alias)
}
}

Expand Down Expand Up @@ -169,12 +180,18 @@ func (a *accountSet) ReplaceWith(other []Account) {
}
}

func (a accountSet) WriteTable(w io.Writer) {
func (a accountSet) WriteTable(w io.Writer, withHeaders bool) {
tbl := csv.NewWriter(w)
tbl.Write([]string{"id,name,alias"})
tbl.Comma = '\t'

if withHeaders {
tbl.Write([]string{"id", "name", "alias"})
}

a.ForEach(func(id string, acc Account, alias string) {
tbl.Write([]string{id, acc.Name, alias})
})

tbl.Flush()
}

Expand Down Expand Up @@ -290,8 +307,8 @@ func (c *Config) UpdateAccounts(entries []Account) {
c.Accounts.ReplaceWith(entries)
}

func (c *Config) DumpAccounts(w io.Writer) {
c.Accounts.WriteTable(w)
func (c *Config) DumpAccounts(w io.Writer, withHeaders bool) {
c.Accounts.WriteTable(w, withHeaders)
}

func EnsureConfigFileExists(fp string) (io.ReadWriteCloser, error) {
Expand Down
16 changes: 8 additions & 8 deletions cli/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"os"
"time"

"github.com/RobotsAndPencils/go-saml"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/sts"
Expand Down Expand Up @@ -109,11 +108,12 @@ A role must be specified when using this command through the --role flag. You ma
return nil
}

if roleName == "" && account.MostRecentRole != "" {
if roleName == "" {
if account.MostRecentRole == "" {
cmd.PrintErrln("You must specify the --role flag with this command")
return nil
}
roleName = account.MostRecentRole
} else {
cmd.PrintErrln("You must specify the --role flag with this command")
return nil
}

if config.TimeRemaining != 0 && timeRemaining == DefaultTimeRemaining {
Expand Down Expand Up @@ -143,14 +143,14 @@ A role must be specified when using this command through the --role flag. You ma
return nil
}

assertionBytes, err := ExchangeWebSSOTokenForSAMLAssertion(cmd.Context(), client, oidcDomain, tok)
assertion, err := ExchangeWebSSOTokenForSAMLAssertion(cmd.Context(), client, oidcDomain, tok)
if err != nil {
cmd.PrintErrf("failed to fetch SAML assertion: %s\n", err)
return nil
}

assertionStr := string(assertionBytes)
samlResponse, err := saml.ParseEncodedResponse(assertionStr)
assertionStr := string(assertion)
samlResponse, err := ParseBase64EncodedSAMLResponse(assertionStr)
if err != nil {
cmd.PrintErrf("could not parse assertion: %s\n", err)
return nil
Expand Down
51 changes: 46 additions & 5 deletions cli/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,24 @@ package main

import (
"context"
"fmt"
"os"

"github.com/pkg/browser"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"golang.org/x/exp/slog"
"golang.org/x/oauth2"
)

var FlagURLOnly = "url-only"
var (
FlagURLOnly = "url-only"
FlagNoBrowser = "no-browser"
)

func init() {
loginCmd.Flags().BoolP(FlagURLOnly, "u", false, "Print only the URL to visit rather than a user-friendly message")
loginCmd.Flags().BoolP(FlagNoBrowser, "b", false, "Do not open a browser window, printing the URL instead")
}

// ShouldUseMachineOutput indicates whether or not we should write to standard output as if the user is a machine.
Expand All @@ -38,8 +45,17 @@ var loginCmd = &cobra.Command{
oidcDomain, _ := cmd.Flags().GetString(FlagOIDCDomain)
clientID, _ := cmd.Flags().GetString(FlagClientID)
urlOnly, _ := cmd.Flags().GetBool(FlagURLOnly)
isMachineOutput := ShouldUseMachineOutput(cmd.Flags()) || urlOnly
token, err := Login(cmd.Context(), oidcDomain, clientID, isMachineOutput)

var outputMode LoginOutputMode = LoginOutputModeBrowser{}
if noBrowser, _ := cmd.Flags().GetBool(FlagNoBrowser); noBrowser {
if ShouldUseMachineOutput(cmd.Flags()) || urlOnly {
outputMode = LoginOutputModeURLOnly{}
} else {
outputMode = LoginOutputModeHumanFriendlyMessage{}
}
}

token, err := Login(cmd.Context(), oidcDomain, clientID, outputMode)
if err != nil {
return err
}
Expand All @@ -48,7 +64,7 @@ var loginCmd = &cobra.Command{
},
}

func Login(ctx context.Context, domain, clientID string, machineOutput bool) (*oauth2.Token, error) {
func Login(ctx context.Context, domain, clientID string, outputMode LoginOutputMode) (*oauth2.Token, error) {
oauthCfg, err := DiscoverOAuth2Config(ctx, domain, clientID)
if err != nil {
return nil, err
Expand All @@ -64,5 +80,30 @@ func Login(ctx context.Context, domain, clientID string, machineOutput bool) (*o
return nil, err
}

return RedirectionFlow(ctx, oauthCfg, state, codeChallenge, codeVerifier, machineOutput)
return RedirectionFlow(ctx, oauthCfg, state, codeChallenge, codeVerifier, outputMode)
}

type LoginOutputMode interface {
PrintURL(url string) error
}

type LoginOutputModeBrowser struct{}

func (LoginOutputModeBrowser) PrintURL(url string) error {
slog.Debug("trying to open browser window", slog.String("url", url))
return browser.OpenURL(url)
}

type LoginOutputModeURLOnly struct{}

func (LoginOutputModeURLOnly) PrintURL(url string) error {
fmt.Fprintln(os.Stdout, url)
return nil
}

type LoginOutputModeHumanFriendlyMessage struct{}

func (LoginOutputModeHumanFriendlyMessage) PrintURL(url string) error {
fmt.Printf("Visit the following link in your terminal: %s\n", url)
return nil
}
17 changes: 10 additions & 7 deletions cli/oauth2.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ import (
"golang.org/x/oauth2"
)

// stateBufSize is the size of the buffer used to generate the state parameter.
// 43 is a magic number - It generates states that are not too short or long for Okta's validation.
const stateBufSize = 43

func NewHTTPClient() *http.Client {
// Some Darwin systems require certs to be loaded from the system certificate store or attempts to verify SSL certs on internal websites may fail.
tr := http.DefaultTransport
Expand Down Expand Up @@ -136,7 +140,7 @@ func (e OAuth2Error) Error() string {
}

func GenerateCodeVerifierAndChallenge() (string, string, error) {
codeVerifierBuf := make([]byte, 43)
codeVerifierBuf := make([]byte, stateBufSize)
rand.Read(codeVerifierBuf)
codeVerifier := base64.RawURLEncoding.EncodeToString(codeVerifierBuf)
codeChallengeHash := sha256.Sum256([]byte(codeVerifier))
Expand All @@ -145,12 +149,12 @@ func GenerateCodeVerifierAndChallenge() (string, string, error) {
}

func GenerateState() (string, error) {
stateBuf := make([]byte, 43)
stateBuf := make([]byte, stateBufSize)
rand.Read(stateBuf)
return base64.URLEncoding.EncodeToString([]byte(stateBuf)), nil
}

func RedirectionFlow(ctx context.Context, oauthCfg *oauth2.Config, state, codeChallenge, codeVerifier string, machineOutput bool) (*oauth2.Token, error) {
func RedirectionFlow(ctx context.Context, oauthCfg *oauth2.Config, state, codeChallenge, codeVerifier string, outputMode LoginOutputMode) (*oauth2.Token, error) {
listener := NewOAuth2Listener()
go listener.Listen(ctx)
oauthCfg.RedirectURL = "http://localhost:57468"
Expand All @@ -159,10 +163,9 @@ func RedirectionFlow(ctx context.Context, oauthCfg *oauth2.Config, state, codeCh
oauth2.SetAuthURLParam("code_challenge", codeChallenge),
)

if machineOutput {
fmt.Println(url)
} else {
fmt.Printf("Visit the following link in your terminal: %s\n", url)
if err := outputMode.PrintURL(url); err != nil {
// This is unlikely to ever happen
return nil, fmt.Errorf("failed to display link: %w", err)
}

code, err := listener.WaitForAuthorizationCode(ctx, state)
Expand Down
4 changes: 1 addition & 3 deletions cli/roles.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package main

import (
"github.com/RobotsAndPencils/go-saml"
"github.com/spf13/cobra"
)

Expand Down Expand Up @@ -44,8 +43,7 @@ var rolesCmd = cobra.Command{
return nil
}

assertionStr := string(assertionBytes)
samlResponse, err := saml.ParseEncodedResponse(assertionStr)
samlResponse, err := ParseBase64EncodedSAMLResponse(string(assertionBytes))
if err != nil {
cmd.PrintErrf("could not parse assertion: %s\n", err)
return nil
Expand Down
4 changes: 4 additions & 0 deletions cli/saml.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,7 @@ func getARN(value string) RoleProviderPair {
}
return p
}

func ParseBase64EncodedSAMLResponse(xml string) (*saml.Response, error) {
return saml.ParseEncodedResponse(xml)
}
2 changes: 1 addition & 1 deletion cli/saml_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
)

func TestAwsFindRoleDoesntBreakIfYouHaveMultipleRoles(t *testing.T) {
resp := saml.Response{}
var resp saml.Response
resp.AddAttribute("https://aws.amazon.com/SAML/Attributes/Role", "arn:cloud:iam::1234:saml-provider/Okta,arn:cloud:iam::1234:role/Admin")
resp.AddAttribute("https://aws.amazon.com/SAML/Attributes/Role", "arn:cloud:iam::1234:saml-provider/Okta,arn:cloud:iam::1234:role/Power")
pair, err := FindRoleInSAML("Power", &resp)
Expand Down
1 change: 0 additions & 1 deletion example.env
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ export S3_TF_BUCKET_NAME='<S3_TF_BUCKET_NAME>'
export S3_TF_BUCKET_TAGS="TagSet=[{Key=Name,Value=keyconjurer}]"
export S3_FRONTEND_BUCKET='<Bucket to Hold UI/CLI binaries>'

export BINARY_NAME='keyconjurer'
export LOGSTASH_ENDPOINT='<LOGSTASH_ENDPOINT>'
export SECRETS_RETRIEVER='kms_blob'

Expand Down
Loading

0 comments on commit 6532079

Please sign in to comment.