github.com/Schaudge/grailbase@v0.0.0-20240223061707-44c758a471c0/cmdutil/access.go (about) 1 // Copyright 2018 GRAIL, Inc. All rights reserved. 2 // Use of this source code is governed by the Apache-2.0 3 // license that can be found in the LICENSE file. 4 5 package cmdutil 6 7 import ( 8 "fmt" 9 "io" 10 "os" 11 "time" 12 13 v23 "v.io/v23" 14 "v.io/v23/context" 15 "v.io/x/lib/cmdline" 16 ) 17 18 // WriteBlessings will write the current principal and blessings to the 19 // supplied io.Writer. 20 func WriteBlessings(ctx *context.T, out io.Writer) { 21 // Mimic the principal dump output. 22 principal := v23.GetPrincipal(ctx) 23 fmt.Fprintf(out, "Public key: %s\n", principal.PublicKey()) 24 fmt.Fprintf(out, "---------------- BlessingStore ----------------") 25 fmt.Fprint(out, principal.BlessingStore().DebugString()) 26 fmt.Fprintf(out, "---------------- BlessingRoots ----------------") 27 fmt.Fprint(out, principal.Roots().DebugString()) 28 } 29 30 // CheckAccess checkes that the current process has credentials that 31 // will be valid for at least another 30 minutes. It is intended to 32 // allow for more useful and obvious error reporting. 33 func CheckAccess(ctx *context.T) (time.Duration, error) { 34 if principal := v23.GetPrincipal(ctx); principal != nil { 35 // We have access to some credentials so we'll try to load them. 36 _, err := v23.WithPrincipal(ctx, principal) 37 if err != nil { 38 return 0, err 39 } 40 blessings, _ := principal.BlessingStore().Default() 41 now := time.Now() 42 left := blessings.Expiry().Sub(now) 43 if blessings.Expiry().After(now.Add(30 * time.Minute)) { 44 return left, nil 45 } 46 if blessings.Expiry().IsZero() { 47 return left, fmt.Errorf("credentials are not set, try setting the V23_CREDENTIALS using 'export V23_CREDENTIALS=%s'", os.ExpandEnv("${HOME}/.v23")) 48 } 49 return left, fmt.Errorf("credentials are set to expire in %v, use grail-access to refresh them", left) 50 } 51 return 0, fmt.Errorf("credentials directory doesn't exist, use the grail-access and/or grail-role commands to create one and to login") 52 } 53 54 type runner struct { 55 access bool 56 ctxfn func() *context.T 57 run func(*context.T, *cmdline.Env, []string) error 58 } 59 60 // Run implements cmdline.Runner. 61 func (r runner) Run(env *cmdline.Env, args []string) error { 62 ctx := r.ctxfn() 63 if os.Getenv("GRAIL_CMDUTIL_NO_ACCESS_CHECK") != "1" && r.access { 64 if _, err := CheckAccess(ctx); err != nil { 65 return err 66 } 67 } 68 return r.run(ctx, env, args) 69 } 70 71 // V23RunnerFunc is like cmdutil.RunnerFunc, but allows for a context.T 72 // parameter that is given the context as obtained from ctxfn. 73 func V23RunnerFunc(ctxfn func() *context.T, run func(*context.T, *cmdline.Env, []string) error) cmdline.Runner { 74 return RunnerFunc(runner{false, ctxfn, run}.Run) 75 } 76 77 // RunnerFuncWithAccessCheck is like V23RunnerFunc, but also calls CheckAccess 78 // to test for credential existence/expiry. 79 func RunnerFuncWithAccessCheck(ctxfn func() *context.T, run func(*context.T, *cmdline.Env, []string) error) cmdline.Runner { 80 return RunnerFunc(runner{true, ctxfn, run}.Run) 81 }