github.com/nats-io/nsc@v0.0.0-20221206222106-35db9400b257/cmd/editscopedsk.go (about) 1 /* 2 * Copyright 2018-2021 The NATS Authors 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 package cmd 17 18 import ( 19 "fmt" 20 21 "github.com/nats-io/jwt/v2" 22 "github.com/nats-io/nkeys" 23 "github.com/nats-io/nsc/cmd/store" 24 "github.com/spf13/cobra" 25 ) 26 27 func createEditSkopedSkCmd() *cobra.Command { 28 var params EditScopedSkParams 29 cmd := &cobra.Command{ 30 Use: "signing-key", 31 Short: "Edit a scoped signing key or promote a signing key to be scoped", 32 Long: `# Edit permissions associated with the account (n) signing key (sk): 33 nsc edit signing-key --account <n> --sk <sk> --allow-pubsub <subject>,... 34 nsc edit signing-key --account <n> --sk <sk> --allow-pub <subject>,... 35 nsc edit signing-key --account <n> --sk <sk> --allow-sub <subject>,... 36 `, 37 Args: cobra.MaximumNArgs(1), 38 SilenceUsage: true, 39 RunE: func(cmd *cobra.Command, args []string) error { 40 return RunAction(cmd, args, ¶ms) 41 }, 42 } 43 cmd.Flags().StringVarP(¶ms.skName, "sk", "", "", "signing key to set scope for or role name for already existing scoped signing key") 44 cmd.Flags().StringVarP(¶ms.role, "role", "", "", "role associated with the signing key scope") 45 params.AccountContextParams.BindFlags(cmd) 46 params.UserPermissionLimits.BindFlags(cmd) 47 return cmd 48 } 49 50 func init() { 51 editCmd.AddCommand(createEditSkopedSkCmd()) 52 } 53 54 type EditScopedSkParams struct { 55 skName string 56 role string 57 claim *jwt.AccountClaims 58 UserPermissionLimits 59 AccountContextParams 60 SignerParams 61 } 62 63 func (p *EditScopedSkParams) SetDefaults(ctx ActionCtx) error { 64 p.skName = NameFlagOrArgument(p.skName, ctx) 65 if err := p.AccountContextParams.SetDefaults(ctx); err != nil { 66 return err 67 } 68 p.SignerParams.SetDefaults(nkeys.PrefixByteOperator, true, ctx) 69 return nil 70 } 71 72 func (p *EditScopedSkParams) PreInteractive(ctx ActionCtx) error { 73 return nil 74 } 75 76 func (p *EditScopedSkParams) Load(ctx ActionCtx) error { 77 var err error 78 79 if err = p.AccountContextParams.Validate(ctx); err != nil { 80 return err 81 } 82 83 if p.skName == "" { 84 ctx.CurrentCmd().SilenceUsage = false 85 return fmt.Errorf("signing key is required") 86 } 87 88 p.claim, err = ctx.StoreCtx().Store.ReadAccountClaim(p.AccountContextParams.Name) 89 if err != nil { 90 return err 91 } 92 93 s, found := p.claim.SigningKeys.GetScope(p.skName) 94 if !found { 95 kp := keyByRoleName(ctx.StoreCtx().KeyStore, p.claim, p.skName) 96 if kp == nil { 97 // Couldn't find key by role name. 98 // Try resolving seed, public key, or filepath. 99 kp, err = store.ResolveKey(p.skName) 100 if err != nil { 101 return err 102 } 103 } 104 if kp == nil { 105 // Still don't have a key pair, give up. 106 return fmt.Errorf("signing-key not found") 107 } 108 109 p.skName, err = kp.PublicKey() 110 if err != nil { 111 return fmt.Errorf("signing-key public key error: %s", err) 112 } 113 } 114 if s == nil { 115 s = &jwt.UserScope{} 116 } 117 return p.UserPermissionLimits.Load(ctx, s.(*jwt.UserScope).Template) 118 } 119 120 func (p *EditScopedSkParams) PostInteractive(ctx ActionCtx) error { 121 return nil 122 } 123 124 func (p *EditScopedSkParams) Validate(ctx ActionCtx) error { 125 p.UserPermissionLimits.Validate(ctx) 126 127 if err := p.SignerParams.ResolveWithPriority(ctx, p.claim.Issuer); err != nil { 128 return err 129 } 130 131 return nil 132 } 133 134 func (p *EditScopedSkParams) Run(ctx ActionCtx) (store.Status, error) { 135 r := store.NewDetailedReport(true) 136 r.ReportSum = false 137 scope, _ := p.claim.SigningKeys.GetScope(p.skName) 138 if scope == nil { 139 scope = jwt.NewUserScope() 140 scope.(*jwt.UserScope).Key = p.skName 141 } 142 if ctx.AnySet("role") { 143 scope.(*jwt.UserScope).Role = p.role 144 } 145 s, err := p.UserPermissionLimits.Run(ctx, &(scope.(*jwt.UserScope).Template)) 146 if err != nil { 147 return nil, err 148 } 149 if s != nil { 150 r.Add(s.Details...) 151 } 152 p.claim.SigningKeys.AddScopedSigner(scope) 153 154 // we sign 155 token, err := p.claim.Encode(p.signerKP) 156 if err != nil { 157 return nil, err 158 } 159 160 // if the signer is not allowed, the store will reject 161 rs, err := ctx.StoreCtx().Store.StoreClaim([]byte(token)) 162 if rs != nil { 163 r.Add(rs) 164 } 165 if err != nil { 166 r.AddFromError(err) 167 } 168 if r.HasNoErrors() { 169 r.AddOK("edited signing key %q", p.skName) 170 } 171 return r, nil 172 }