github.com/kbehouse/nsc@v0.0.6/cmd/revoke_listactivation.go (about) 1 /* 2 * Copyright 2018-2020 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 "time" 21 22 "github.com/kbehouse/nsc/cmd/store" 23 cli "github.com/nats-io/cliprompts/v2" 24 "github.com/nats-io/jwt/v2" 25 "github.com/nats-io/nkeys" 26 "github.com/spf13/cobra" 27 "github.com/xlab/tablewriter" 28 ) 29 30 func createRevokeListActivationCmd() *cobra.Command { 31 var params RevokeListActivationParams 32 cmd := &cobra.Command{ 33 Use: "list_activations", 34 Aliases: []string{"list-activations"}, 35 Short: "List account revocations for an export", 36 Args: MaxArgs(0), 37 SilenceUsage: true, 38 RunE: func(cmd *cobra.Command, args []string) error { 39 return RunAction(cmd, args, ¶ms) 40 }, 41 } 42 43 cmd.Flags().StringVarP(¶ms.subject, "subject", "s", "", "export subject") 44 cmd.Flags().BoolVarP(¶ms.service, "service", "", false, "service") 45 46 params.AccountContextParams.BindFlags(cmd) 47 48 return cmd 49 } 50 51 func init() { 52 revokeCmd.AddCommand(createRevokeListActivationCmd()) 53 } 54 55 // RevokeListActivationParams hold the info necessary to add a user to the revocation list in an account 56 type RevokeListActivationParams struct { 57 AccountContextParams 58 SignerParams 59 claim *jwt.AccountClaims 60 export *jwt.Export 61 possibleExports jwt.Exports 62 subject string 63 service bool 64 } 65 66 func (p *RevokeListActivationParams) SetDefaults(ctx ActionCtx) error { 67 p.AccountContextParams.SetDefaults(ctx) 68 p.SignerParams.SetDefaults(nkeys.PrefixByteOperator, true, ctx) 69 return nil 70 } 71 72 func (p *RevokeListActivationParams) PreInteractive(ctx ActionCtx) error { 73 var err error 74 75 if err = p.AccountContextParams.Edit(ctx); err != nil { 76 return err 77 } 78 79 p.service, err = cli.Confirm("is service", p.service) 80 if err != nil { 81 return err 82 } 83 84 return nil 85 } 86 87 func (p *RevokeListActivationParams) Load(ctx ActionCtx) error { 88 var err error 89 90 if err = p.AccountContextParams.Validate(ctx); err != nil { 91 return err 92 } 93 94 p.claim, err = ctx.StoreCtx().Store.ReadAccountClaim(p.AccountContextParams.Name) 95 if err != nil { 96 return err 97 } 98 99 if len(p.claim.Exports) == 0 { 100 return fmt.Errorf("account %q doesn't have exports", p.AccountContextParams.Name) 101 } 102 103 kind := jwt.Stream 104 if p.service { 105 kind = jwt.Service 106 } 107 108 for _, v := range p.claim.Exports { 109 if v.Type != kind { 110 continue 111 } 112 p.possibleExports.Add(v) 113 } 114 115 if len(p.possibleExports) == 0 { 116 return fmt.Errorf("account %q doesn't have %v exports", 117 p.AccountContextParams.Name, kind) 118 } 119 120 return nil 121 } 122 123 func (p *RevokeListActivationParams) Validate(ctx ActionCtx) error { 124 125 if len(p.possibleExports) == 1 && p.subject == "" { 126 p.subject = string(p.possibleExports[0].Subject) 127 } 128 129 if p.subject == "" { 130 ctx.CurrentCmd().SilenceUsage = false 131 return fmt.Errorf("a subject is required") 132 } 133 134 sub := jwt.Subject(p.subject) 135 for _, e := range p.possibleExports { 136 if sub.IsContainedIn(e.Subject) { 137 p.export = e 138 break 139 } 140 } 141 142 if err := p.SignerParams.Resolve(ctx); err != nil { 143 return err 144 } 145 146 return nil 147 } 148 149 func (p *RevokeListActivationParams) PostInteractive(ctx ActionCtx) error { 150 var choices []string 151 if p.subject == "" { 152 for _, v := range p.possibleExports { 153 choices = append(choices, string(v.Subject)) 154 } 155 } 156 kind := jwt.Stream 157 if p.service { 158 kind = jwt.Service 159 } 160 161 i, err := cli.Select(fmt.Sprintf("select %s export", kind.String()), "", choices) 162 if err != nil { 163 return err 164 } 165 p.export = p.possibleExports[i] 166 if p.subject == "" { 167 p.subject = string(p.export.Subject) 168 } 169 170 if err := p.SignerParams.Edit(ctx); err != nil { 171 return err 172 } 173 174 return nil 175 } 176 177 func (p *RevokeListActivationParams) Run(ctx ActionCtx) (store.Status, error) { 178 if p.export == nil { 179 return nil, fmt.Errorf("unable to locate export") 180 } 181 kind := jwt.Stream 182 if p.service { 183 kind = jwt.Service 184 } 185 if len(p.export.Revocations) == 0 { 186 return nil, fmt.Errorf("%v %s has no revocations", kind, p.export.Name) 187 } 188 189 name := p.export.Name 190 if name == "" { 191 name = string(p.export.Subject) 192 } 193 194 table := tablewriter.CreateTable() 195 table.AddTitle(fmt.Sprintf("Revoked Accounts for %v %s", kind, name)) 196 table.AddHeaders("Public Key", "Revoke Credentials Before") 197 198 for pubKey, at := range p.export.Revocations { 199 if pubKey == "*" { 200 pubKey = "* [All Accounts]" 201 } 202 t := time.Unix(at, 0) 203 formatted := t.Format(time.RFC1123) 204 table.AddRow(pubKey, formatted) 205 } 206 207 return nil, Write("--", []byte(table.Render())) 208 }