github.com/kbehouse/nsc@v0.0.6/cmd/describejwt.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  	"errors"
    20  	"fmt"
    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/spf13/cobra"
    26  )
    27  
    28  func createDescribeJwtCmd() *cobra.Command {
    29  	var params DescribeFile
    30  	var cmd = &cobra.Command{
    31  		Use:          "jwt",
    32  		Short:        "Describe a jwt/creds file",
    33  		Args:         MaxArgs(0),
    34  		Example:      fmt.Sprintf(`%s describe -f pathorurl`, GetToolName()),
    35  		SilenceUsage: true,
    36  		RunE: func(cmd *cobra.Command, args []string) error {
    37  			if err := RunStoreLessAction(cmd, args, &params); err != nil {
    38  				return err
    39  			}
    40  			return nil
    41  		},
    42  	}
    43  	cmd.Flags().StringVarP(&params.outputFile, "output-file", "o", "--", "output file, '--' is stdout")
    44  	cmd.Flags().StringVarP(&params.file, "file", "f", "", "a token file or url to a token file")
    45  
    46  	return cmd
    47  }
    48  
    49  func init() {
    50  	describeCmd.AddCommand(createDescribeJwtCmd())
    51  }
    52  
    53  type DescribeFile struct {
    54  	file       string
    55  	kind       jwt.ClaimType
    56  	outputFile string
    57  	token      string
    58  }
    59  
    60  func (p *DescribeFile) SetDefaults(ctx ActionCtx) error {
    61  	return nil
    62  }
    63  
    64  func (p *DescribeFile) PreInteractive(ctx ActionCtx) error {
    65  	var err error
    66  	p.file, err = cli.Prompt("token file or url", p.file)
    67  	return err
    68  }
    69  
    70  func (p *DescribeFile) Load(ctx ActionCtx) error {
    71  	if p.file == "" {
    72  		ctx.CurrentCmd().SilenceErrors = false
    73  		ctx.CurrentCmd().SilenceUsage = false
    74  		return errors.New("file is required")
    75  	}
    76  	if d, err := LoadFromFileOrURL(p.file); err == nil {
    77  		p.token, err = jwt.ParseDecoratedJWT(d)
    78  		if err != nil {
    79  			return err
    80  		}
    81  		gc, err := jwt.DecodeGeneric(p.token)
    82  		if err != nil {
    83  			return err
    84  		}
    85  		p.kind = gc.ClaimType()
    86  	}
    87  	return nil
    88  }
    89  
    90  func (p *DescribeFile) PostInteractive(ctx ActionCtx) error {
    91  	return nil
    92  }
    93  
    94  func (p *DescribeFile) Validate(ctx ActionCtx) error {
    95  	return nil
    96  }
    97  
    98  func (p *DescribeFile) handleRaw() (store.Status, error) {
    99  	var err error
   100  	var raw []byte
   101  	if Json || JsonPath != "" {
   102  		raw, err = bodyAsJson([]byte(p.token))
   103  		if err != nil {
   104  			return nil, err
   105  		}
   106  		if JsonPath != "" {
   107  			raw, err = GetField(raw, JsonPath)
   108  			if err != nil {
   109  				return nil, err
   110  			}
   111  		}
   112  	}
   113  	raw = append(raw, '\n')
   114  	if err := Write(p.outputFile, raw); err != nil {
   115  		return nil, err
   116  	}
   117  	var s store.Status
   118  	if !IsStdOut(p.outputFile) {
   119  		k := "description"
   120  		if Raw {
   121  			k = "jwt"
   122  		}
   123  		s = store.OKStatus("wrote jwt %s to %#q", k, AbbrevHomePaths(p.outputFile))
   124  	}
   125  	return s, nil
   126  }
   127  
   128  func (p *DescribeFile) Run(ctx ActionCtx) (store.Status, error) {
   129  	if Json || Raw || JsonPath != "" {
   130  		return p.handleRaw()
   131  	}
   132  
   133  	var describer Describer
   134  	switch p.kind {
   135  	case jwt.AccountClaim:
   136  		ac, err := jwt.DecodeAccountClaims(p.token)
   137  		if err != nil {
   138  			return nil, err
   139  		}
   140  		describer = NewAccountDescriber(*ac)
   141  	case jwt.ActivationClaim:
   142  		ac, err := jwt.DecodeActivationClaims(p.token)
   143  		if err != nil {
   144  			return nil, err
   145  		}
   146  		describer = NewActivationDescriber(*ac)
   147  	case jwt.UserClaim:
   148  		uc, err := jwt.DecodeUserClaims(p.token)
   149  		if err != nil {
   150  			return nil, err
   151  		}
   152  		describer = NewUserDescriber(*uc)
   153  	case jwt.OperatorClaim:
   154  		oc, err := jwt.DecodeOperatorClaims(p.token)
   155  		if err != nil {
   156  			return nil, err
   157  		}
   158  		describer = NewOperatorDescriber(*oc)
   159  	}
   160  
   161  	if describer == nil {
   162  		return nil, fmt.Errorf("describer for %q is not implemented", p.kind)
   163  	}
   164  
   165  	if err := Write(p.outputFile, []byte(describer.Describe())); err != nil {
   166  		return nil, err
   167  	}
   168  	var s store.Status
   169  	if !IsStdOut(p.outputFile) {
   170  		s = store.OKStatus("wrote account description to %#q", AbbrevHomePaths(p.outputFile))
   171  	}
   172  	return s, nil
   173  }