github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/worker/uniter/runner/jujuc/secret-grant.go (about) 1 // Copyright 2021 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package jujuc 5 6 import ( 7 "github.com/juju/cmd/v3" 8 "github.com/juju/errors" 9 "github.com/juju/gnuflag" 10 "github.com/juju/names/v5" 11 12 jujucmd "github.com/juju/juju/cmd" 13 "github.com/juju/juju/core/secrets" 14 ) 15 16 type secretGrantCommand struct { 17 cmd.CommandBase 18 ctx Context 19 20 secretURI *secrets.URI 21 app string 22 unit string 23 relation string 24 25 relationId int 26 relationIdProxy gnuflag.Value 27 } 28 29 // NewSecretGrantCommand returns a command to grant access to a secret. 30 func NewSecretGrantCommand(ctx Context) (cmd.Command, error) { 31 cmd := &secretGrantCommand{ctx: ctx} 32 var err error 33 cmd.relationIdProxy, err = NewRelationIdValue(ctx, &cmd.relationId) 34 if err != nil { 35 return nil, errors.Trace(err) 36 } 37 return cmd, nil 38 } 39 40 // Info implements cmd.Command. 41 func (c *secretGrantCommand) Info() *cmd.Info { 42 doc := ` 43 Grant access to view the value of a specified secret. 44 Access is granted in the context of a relation - unless revoked 45 earlier, once the relation is removed, so too is the access grant. 46 47 By default, all units of the related application are granted access. 48 Optionally specify a unit name to limit access to just that unit. 49 50 Examples: 51 secret-grant secret:9m4e2mr0ui3e8a215n4g -r 0 --unit mediawiki/6 52 secret-grant secret:9m4e2mr0ui3e8a215n4g --relation db:2 53 ` 54 return jujucmd.Info(&cmd.Info{ 55 Name: "secret-grant", 56 Args: "<ID>", 57 Purpose: "grant access to a secret", 58 Doc: doc, 59 }) 60 } 61 62 // SetFlags implements cmd.Command. 63 func (c *secretGrantCommand) SetFlags(f *gnuflag.FlagSet) { 64 f.StringVar(&c.unit, "unit", "", "the unit to grant access") 65 f.Var(c.relationIdProxy, "r", "the relation with which to associate the grant") 66 f.Var(c.relationIdProxy, "relation", "the relation with which to associate the grant") 67 } 68 69 // Init implements cmd.Command. 70 func (c *secretGrantCommand) Init(args []string) error { 71 if len(args) < 1 { 72 return errors.New("missing secret URI") 73 } 74 var err error 75 if c.secretURI, err = secrets.ParseURI(args[0]); err != nil { 76 return errors.Trace(err) 77 } 78 if c.relationId == -1 { 79 return errors.Errorf("no relation id specified") 80 } 81 r, err := c.ctx.Relation(c.relationId) 82 if err != nil { 83 return errors.Trace(err) 84 } 85 c.relation = r.RelationTag().Id() 86 c.app = r.RemoteApplicationName() 87 if c.unit != "" { 88 if !names.IsValidUnit(c.unit) { 89 return errors.NotValidf("unit %q", c.unit) 90 } 91 appNameForUnit, _ := names.UnitApplication(c.unit) 92 if appNameForUnit != c.app { 93 return errors.Errorf("cannot specify unit %q in relation to application %q", c.unit, c.app) 94 } 95 } 96 return cmd.CheckEmpty(args[1:]) 97 } 98 99 // Run implements cmd.Command. 100 func (c *secretGrantCommand) Run(_ *cmd.Context) error { 101 args := &SecretGrantRevokeArgs{ 102 RelationKey: &c.relation, 103 } 104 if c.unit != "" { 105 args.UnitName = &c.unit 106 } 107 if c.app != "" { 108 args.ApplicationName = &c.app 109 } 110 111 return c.ctx.GrantSecret(c.secretURI, args) 112 }