Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/auth-clientCredentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ var clientCredentialsCmd = man.Docs.GetCommand("auth/client-credentials",

func auth_clientCredentials(cmd *cobra.Command, args []string) {
c := cli.New(cmd, args)
cp := InitProfile(c, false)
_, cp := InitProfile(c, false)

var clientId string
var clientSecret string
Expand Down
2 changes: 1 addition & 1 deletion cmd/auth-login.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (

func auth_codeLogin(cmd *cobra.Command, args []string) {
c := cli.New(cmd, args)
cp := InitProfile(c, false)
_, cp := InitProfile(c, false)

c.Print("Initiating login...")
tok, publicClientID, err := auth.LoginWithPKCE(
Expand Down
2 changes: 1 addition & 1 deletion cmd/auth-logout.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (

func auth_logout(cmd *cobra.Command, args []string) {
c := cli.New(cmd, args)
cp := InitProfile(c, false)
_, cp := InitProfile(c, false)
c.Println("Initiating logout...")

// we can only revoke access tokens stored for the code login flow, not client credentials
Expand Down
2 changes: 1 addition & 1 deletion cmd/auth-printAccessToken.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ var auth_printAccessTokenCmd = man.Docs.GetCommand("auth/print-access-token",

func auth_printAccessToken(cmd *cobra.Command, args []string) {
c := cli.New(cmd, args)
cp := InitProfile(c, false)
_, cp := InitProfile(c, false)

ac := cp.GetAuthCredentials()
switch ac.AuthType {
Expand Down
128 changes: 82 additions & 46 deletions cmd/root.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
/*
Copyright © 2023 NAME HERE <EMAIL ADDRESS>
*/
package cmd

import (
Expand Down Expand Up @@ -35,7 +32,10 @@
BuildTime string `json:"build_time"`
}

func InitProfile(c *cli.Cli, onlyNew bool) *profiles.ProfileStore {
// InitProfile initializes the profile store and loads the profile specified in the flags
// if onlyNew is set to true, a new profile will be created and returned
// returns the profile and the current profile store
func InitProfile(c *cli.Cli, onlyNew bool) (*profiles.Profile, *profiles.ProfileStore) {
var err error
profileName := c.FlagHelper.GetOptionalString("profile")

Expand All @@ -45,126 +45,157 @@
}

// short circuit if onlyNew is set to enable creating a new profile
if onlyNew {
return nil
if onlyNew && profileName == "" {
return profile, nil
}

// check if there exists a default profile and warn if not with steps to create one
if profile.GetGlobalConfig().GetDefaultProfile() == "" {
c.ExitWithWarning("No default profile set. Use `" + config.AppName + " profile create <profile> <endpoint>` to create a default profile.")
c.ExitWithWarning(fmt.Sprintf("No default profile set. Use `%s profile create <profile> <endpoint>` to create a default profile.", config.AppName))
}
c.Printf("Using profile [%s]\n", profile.GetGlobalConfig().GetDefaultProfile())

if profileName == "" {
profileName = profile.GetGlobalConfig().GetDefaultProfile()
}

c.Printf(fmt.Sprintf("Using profile [%s]\n", profileName))

Check failure on line 61 in cmd/root.go

View workflow job for this annotation

GitHub Actions / lint

printf: non-constant format string in call to (*github.com/opentdf/otdfctl/pkg/cli.Cli).Printf (govet)

// load profile
cp, err := profile.UseProfile(profileName)
if err != nil {
c.ExitWithError("Failed to load profile "+profileName, err)
c.ExitWithError(fmt.Sprintf("Failed to load profile: %s", profileName), err)
}

return cp
return profile, cp
}

// instantiates a new handler with authentication via client credentials
// TODO make this a preRun hook
//
//nolint:nestif // separate refactor [https://github.com/opentdf/otdfctl/issues/383]
func NewHandler(c *cli.Cli) handlers.Handler {
// if global flags are set then validate and create a temporary profile in memory
var cp *profiles.ProfileStore

// Non-profile flags
host := c.FlagHelper.GetOptionalString("host")
tlsNoVerify := c.FlagHelper.GetOptionalBool("tls-no-verify")
withClientCreds := c.FlagHelper.GetOptionalString("with-client-creds")
withClientCredsFile := c.FlagHelper.GetOptionalString("with-client-creds-file")
withAccessToken := c.FlagHelper.GetOptionalString("with-access-token")
var inMemoryProfile bool

// if global flags are set then validate and create a temporary profile in memory
var cp *profiles.ProfileStore
authFlags := []string{"--with-access-token", "--with-client-creds", "--with-client-creds-file"}
nonProfileFlags := append([]string{"--host", "--tls-no-verify"}, authFlags...)
hasNonProfileFlags := host != "" || tlsNoVerify || withClientCreds != "" || withClientCredsFile != "" || withAccessToken != ""

//nolint:nestif // nested if statements are necessary for validation
if host != "" || tlsNoVerify || withClientCreds != "" || withClientCredsFile != "" {
err := errors.New(
"when using global flags --host, --tls-no-verify, --with-client-creds, or --with-client-creds-file, " +
"profiles will not be used and all required flags must be set",
)
if hasNonProfileFlags {
err := fmt.Errorf("when using global flags %s, profiles will not be used and all required flags must be set", cli.PrettyList(nonProfileFlags))

// host must be set
if host == "" {
cli.ExitWithError("Host must be set", err)
}

// either with-client-creds or with-client-creds-file must be set
if withClientCreds == "" && withClientCredsFile == "" {
cli.ExitWithError("Either --with-client-creds or --with-client-creds-file must be set", err)
} else if withClientCreds != "" && withClientCredsFile != "" {
cli.ExitWithError("Only one of --with-client-creds or --with-client-creds-file can be set", err)
authFlagsCounter := 0
if withAccessToken != "" {
authFlagsCounter++
}

var cc auth.ClientCredentials
if withClientCreds != "" {
cc, err = auth.GetClientCredsFromJSON([]byte(withClientCreds))
} else {
cc, err = auth.GetClientCredsFromFile(withClientCredsFile)
authFlagsCounter++
}
if err != nil {
cli.ExitWithError("Failed to get client credentials", err)
if withClientCredsFile != "" {
authFlagsCounter++
}
if authFlagsCounter == 0 {
cli.ExitWithError(fmt.Sprintf("One of %s must be set", cli.PrettyList(authFlags)), err)
} else if authFlagsCounter > 1 {
cli.ExitWithError(fmt.Sprintf("Only one of %s must be set", cli.PrettyList(authFlags)), err)
}

inMemoryProfile = true
profile, err = profiles.New(profiles.WithInMemoryStore())
if err != nil || profile == nil {
cli.ExitWithError("Failed to initialize a temporary profile", err)
cli.ExitWithError("Failed to initialize in-memory profile", err)
}

if err := profile.AddProfile("temp", host, tlsNoVerify, true); err != nil {
cli.ExitWithError("Failed to create temporary profile", err)
cli.ExitWithError("Failed to create in-memory profile", err)
}

// add credentials to the temporary profile
cp, err = profile.UseProfile("temp")
if err != nil {
cli.ExitWithError("Failed to load temporary profile", err)
cli.ExitWithError("Failed to load in-memory profile", err)
}

// add credentials to the temporary profile
if err := cp.SetAuthCredentials(profiles.AuthCredentials{
AuthType: profiles.PROFILE_AUTH_TYPE_CLIENT_CREDENTIALS,
ClientId: cc.ClientId,
ClientSecret: cc.ClientSecret,
}); err != nil {
cli.ExitWithError("Failed to set client credentials", err)
// get credentials from flags
if withAccessToken != "" {
claims, err := auth.ParseClaimsJWT(withAccessToken)
if err != nil {
cli.ExitWithError("Failed to get access token", err)
}

if err := cp.SetAuthCredentials(profiles.AuthCredentials{
AuthType: profiles.PROFILE_AUTH_TYPE_ACCESS_TOKEN,
AccessToken: profiles.AuthCredentialsAccessToken{
AccessToken: withAccessToken,
Expiration: claims.Expiration,
},
}); err != nil {
cli.ExitWithError("Failed to set access token", err)
}
} else {
var cc auth.ClientCredentials
if withClientCreds != "" {
cc, err = auth.GetClientCredsFromJSON([]byte(withClientCreds))
} else if withClientCredsFile != "" {
cc, err = auth.GetClientCredsFromFile(withClientCredsFile)
}
if err != nil {
cli.ExitWithError("Failed to get client credentials", err)
}

// add credentials to the temporary profile
if err := cp.SetAuthCredentials(profiles.AuthCredentials{
AuthType: profiles.PROFILE_AUTH_TYPE_CLIENT_CREDENTIALS,
ClientId: cc.ClientId,
ClientSecret: cc.ClientSecret,
}); err != nil {
cli.ExitWithError("Failed to set client credentials", err)
}
}
if err := cp.Save(); err != nil {
cli.ExitWithError("Failed to save profile", err)
}
} else {
cp = InitProfile(c, false)
profile, cp = InitProfile(c, false)
}

if err := auth.ValidateProfileAuthCredentials(c.Context(), cp); err != nil {
if errors.Is(err, auth.ErrPlatformConfigNotFound) {
cli.ExitWithError(fmt.Sprintf("Failed to get platform configuration. Is the platform accepting connections at '%s'?", cp.GetEndpoint()), nil)
}
if inMemoryProfile {
cli.ExitWithError("Failed to authenticate with flag-provided client credentials", err)
cli.ExitWithError("Failed to authenticate with flag-provided client credentials.", err)
}
if errors.Is(err, auth.ErrProfileCredentialsNotFound) {
cli.ExitWithWarning("Profile missing credentials. Please login or add client credentials.")
}

if errors.Is(err, auth.ErrAccessTokenExpired) {
cli.ExitWithWarning("Access token expired. Please login again.")
cli.ExitWithWarning("Access token expired. Please login or add flag-provided credentials.")
}
if errors.Is(err, auth.ErrAccessTokenNotFound) {
cli.ExitWithWarning("No access token found. Please login or add client credentials.")
cli.ExitWithWarning("No access token found. Please login or add flag-provided credentials.")
}
cli.ExitWithError("Failed to get access token", err)
cli.ExitWithError("Failed to get access token.", err)
}

h, err := handlers.New(handlers.WithProfile(cp))
if err != nil {
cli.ExitWithError("Failed to create handler", err)
cli.ExitWithError("Unexpected error", err)
}
return h
}
Expand All @@ -181,7 +212,7 @@
BuildTime: config.BuildTime,
}

c.Println(config.AppName + " version " + config.Version + " (" + config.BuildTime + ") " + config.CommitSha)
c.Println(fmt.Sprintf("%s version %s (%s) %s", config.AppName, config.Version, config.BuildTime, config.CommitSha))
c.ExitWithJSON(v)
return
}
Expand Down Expand Up @@ -243,5 +274,10 @@
rootCmd.GetDocFlag("with-client-creds").Default,
rootCmd.GetDocFlag("with-client-creds").Description,
)
RootCmd.PersistentFlags().String(
rootCmd.GetDocFlag("with-access-token").Name,
rootCmd.GetDocFlag("with-access-token").Default,
rootCmd.GetDocFlag("with-access-token").Description,
)
RootCmd.AddGroup(&cobra.Group{ID: TDF})
}
2 changes: 2 additions & 0 deletions docs/man/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ command:
- fatal
- panic
default: info
- name: with-access-token
description: access token for authentication via bearer token
- name: with-client-creds-file
description: path to a JSON file containing a 'clientId' and 'clientSecret' for auth via client-credentials flow
- name: with-client-creds
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ require (
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/go-jose/go-jose/v3 v3.0.3 // indirect
github.com/go-jose/go-jose/v4 v4.0.4 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
Expand Down
41 changes: 41 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ github.com/gabriel-vasile/mimetype v1.4.5 h1:J7wGKdGu33ocBOhGy0z653k/lFKLFDPJMG8
github.com/gabriel-vasile/mimetype v1.4.5/go.mod h1:ibHel+/kbxn9x2407k1izTA1S81ku1z/DlgOW2QE0M4=
github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw=
github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-jose/go-jose/v3 v3.0.3 h1:fFKWeig/irsp7XD2zBxvnmA/XaRWp5V3CBsZXJF7G7k=
github.com/go-jose/go-jose/v3 v3.0.3/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ=
github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E=
github.com/go-jose/go-jose/v4 v4.0.4/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
Expand All @@ -120,6 +122,7 @@ github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keL
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
Expand Down Expand Up @@ -303,6 +306,7 @@ github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQ
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
github.com/yuin/goldmark v1.3.7/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yuin/goldmark v1.5.4 h1:2uY/xC0roWy8IBEGLgB1ywIoEJFGmRrX21YQcvGZzjU=
github.com/yuin/goldmark v1.5.4/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yuin/goldmark-emoji v1.0.2 h1:c/RgTShNgHTtc6xdz2KKI74jJr6rWi7FPgnP9GAsO5s=
Expand All @@ -327,29 +331,66 @@ go.opentelemetry.io/otel/trace v1.29.0 h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt3
go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ=
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA=
golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU=
golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d h1:kHjw/5UfflP/L5EbledDrcG4C2597RtymmGRZvHiCuY=
google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d/go.mod h1:mw8MG/Qz5wfgYr6VqVCiZcHe/GJEfI+oGGDCohaVgB0=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d h1:JU0iKnSg02Gmb5ZdV8nYsKEKsP6o/FGVWTrw4i1DA9A=
Expand Down
Loading
Loading