github.com/nats-io/nsc@v0.0.0-20221206222106-35db9400b257/cmd/revoke_clearactivation.go (about) 1 /* 2 * Copyright 2018-2022 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 cli "github.com/nats-io/cliprompts/v2" 22 "github.com/nats-io/jwt/v2" 23 "github.com/nats-io/nkeys" 24 "github.com/nats-io/nsc/cmd/store" 25 "github.com/spf13/cobra" 26 ) 27 28 func createClearRevokeActivationCmd() *cobra.Command { 29 var params RevokeClearActivationParams 30 cmd := &cobra.Command{ 31 Use: "delete_activation", 32 Aliases: []string{"delete-activation"}, 33 Short: "Remove an account revocation from an export", 34 Args: MaxArgs(0), 35 SilenceUsage: true, 36 RunE: func(cmd *cobra.Command, args []string) error { 37 return RunAction(cmd, args, ¶ms) 38 }, 39 } 40 41 cmd.Flags().StringVarP(¶ms.subject, "subject", "s", "", "export subject") 42 cmd.Flags().BoolVarP(¶ms.service, "service", "", false, "service") 43 params.accountKey.BindFlags("target-account", "t", nkeys.PrefixByteAccount, cmd) 44 45 params.AccountContextParams.BindFlags(cmd) 46 47 return cmd 48 } 49 50 func init() { 51 revokeCmd.AddCommand(createClearRevokeActivationCmd()) 52 } 53 54 // RevokeClearActivationParams hold the info necessary to add a user to the revocation list in an account 55 type RevokeClearActivationParams struct { 56 AccountContextParams 57 SignerParams 58 claim *jwt.AccountClaims 59 export *jwt.Export 60 possibleExports jwt.Exports 61 subject string 62 service bool 63 accountKey PubKeyParams 64 } 65 66 func (p *RevokeClearActivationParams) SetDefaults(ctx ActionCtx) error { 67 p.accountKey.AllowWildcard = true 68 p.AccountContextParams.SetDefaults(ctx) 69 if err := p.accountKey.SetDefaults(ctx); err != nil { 70 return err 71 } 72 p.SignerParams.SetDefaults(nkeys.PrefixByteOperator, true, ctx) 73 return nil 74 } 75 76 func (p *RevokeClearActivationParams) PreInteractive(ctx ActionCtx) error { 77 var err error 78 79 if err = p.AccountContextParams.Edit(ctx); err != nil { 80 return err 81 } 82 83 p.service, err = cli.Confirm("is service", p.service) 84 if err != nil { 85 return err 86 } 87 88 return nil 89 } 90 91 func (p *RevokeClearActivationParams) Load(ctx ActionCtx) error { 92 var err error 93 94 if err = p.AccountContextParams.Validate(ctx); err != nil { 95 return err 96 } 97 98 p.claim, err = ctx.StoreCtx().Store.ReadAccountClaim(p.AccountContextParams.Name) 99 if err != nil { 100 return err 101 } 102 103 if len(p.claim.Exports) == 0 { 104 return fmt.Errorf("account %q doesn't have exports", p.AccountContextParams.Name) 105 } 106 107 kind := jwt.Stream 108 if p.service { 109 kind = jwt.Service 110 } 111 112 for _, v := range p.claim.Exports { 113 if v.Type != kind { 114 continue 115 } 116 p.possibleExports.Add(v) 117 } 118 119 if len(p.possibleExports) == 0 { 120 return fmt.Errorf("account %q doesn't have %v exports", 121 p.AccountContextParams.Name, kind) 122 } 123 124 return nil 125 } 126 127 func (p *RevokeClearActivationParams) PostInteractive(ctx ActionCtx) error { 128 var exports []string 129 if p.subject == "" { 130 for _, v := range p.possibleExports { 131 exports = append(exports, string(v.Subject)) 132 } 133 } 134 kind := jwt.Stream 135 if p.service { 136 kind = jwt.Service 137 } 138 139 i, err := cli.Select(fmt.Sprintf("select %v export", kind), "", exports) 140 if err != nil { 141 return err 142 } 143 p.export = p.possibleExports[i] 144 if p.subject == "" { 145 p.subject = string(p.export.Subject) 146 } 147 if len(p.export.Revocations) == 0 { 148 return fmt.Errorf("%v export %s doesn't have revocations", kind, p.export.Name) 149 } 150 accounts, err := ListAccounts(ctx.StoreCtx().Store) 151 if err != nil { 152 return err 153 } 154 keyToName := make(map[string]string) 155 keyToName["*"] = "* [All Accounts]" 156 for _, a := range accounts { 157 if a.Err == nil { 158 keyToName[a.Claims.Claims().Subject] = a.Name 159 } 160 } 161 var keys []PubKeyChoice 162 for k := range p.export.Revocations { 163 n := keyToName[k] 164 if n == "" { 165 n = "[Unknown Account]" 166 } 167 n = fmt.Sprintf("%s: %s", k, n) 168 keys = append(keys, PubKeyChoice{Key: k, Label: n}) 169 } 170 if err = p.accountKey.Select("select account revocation to delete", keys...); err != nil { 171 return err 172 } 173 return p.SignerParams.Edit(ctx) 174 } 175 176 func (p *RevokeClearActivationParams) Validate(ctx ActionCtx) error { 177 if len(p.possibleExports) == 1 && p.subject == "" { 178 p.subject = string(p.possibleExports[0].Subject) 179 } 180 if p.subject == "" { 181 ctx.CurrentCmd().SilenceUsage = false 182 return fmt.Errorf("a subject is required") 183 } 184 if err := p.accountKey.Valid(); err != nil { 185 return err 186 } 187 sub := jwt.Subject(p.subject) 188 for _, e := range p.possibleExports { 189 if sub.IsContainedIn(e.Subject) { 190 p.export = e 191 break 192 } 193 } 194 if p.export == nil { 195 return fmt.Errorf("unable to locate export") 196 } 197 return p.SignerParams.Resolve(ctx) 198 } 199 200 func (p *RevokeClearActivationParams) Run(ctx ActionCtx) (store.Status, error) { 201 p.export.ClearRevocation(p.accountKey.publicKey) 202 token, err := p.claim.Encode(p.signerKP) 203 if err != nil { 204 return nil, err 205 } 206 r := store.NewDetailedReport(true) 207 StoreAccountAndUpdateStatus(ctx, token, r) 208 if r.HasNoErrors() { 209 kind := jwt.Stream 210 if p.service { 211 kind = jwt.Service 212 } 213 214 if p.accountKey.publicKey == jwt.All { 215 r.AddOK("deleted %v %s revocation for all accounts", kind, p.export.Name) 216 } else { 217 r.AddOK("deleted %v %s revocation for account %s", kind, p.export.Name, p.accountKey.publicKey) 218 } 219 } 220 return r, nil 221 }