...

Source file src/github.com/sigstore/rekor/cmd/rekor-cli/app/pflag_groups.go

Documentation: github.com/sigstore/rekor/cmd/rekor-cli/app

     1  //
     2  // Copyright 2021 The Sigstore Authors.
     3  //
     4  // Licensed under the Apache License, Version 2.0 (the "License");
     5  // you may not use this file except in compliance with the License.
     6  // You may obtain a copy of the License at
     7  //
     8  //     http://www.apache.org/licenses/LICENSE-2.0
     9  //
    10  // Unless required by applicable law or agreed to in writing, software
    11  // distributed under the License is distributed on an "AS IS" BASIS,
    12  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  // See the License for the specific language governing permissions and
    14  // limitations under the License.
    15  
    16  package app
    17  
    18  import (
    19  	"encoding/base64"
    20  	"errors"
    21  	"fmt"
    22  	"net/url"
    23  	"strings"
    24  
    25  	"github.com/sigstore/rekor/pkg/pki"
    26  	"github.com/sigstore/rekor/pkg/types"
    27  	"github.com/spf13/cobra"
    28  	"github.com/spf13/viper"
    29  )
    30  
    31  // addFlagToCmd adds the specified command of a specified type to the command's flag set
    32  func addFlagToCmd(cmd *cobra.Command, required bool, flagType FlagType, flag, desc string) error {
    33  	cmd.Flags().Var(NewFlagValue(flagType, ""), flag, desc)
    34  	if required {
    35  		return cmd.MarkFlagRequired(flag)
    36  	}
    37  	return nil
    38  }
    39  
    40  // addLogIndexFlag adds the "log-index" command to the command's flag set
    41  func addLogIndexFlag(cmd *cobra.Command, required bool) error {
    42  	return addFlagToCmd(cmd, required, logIndexFlag, "log-index", "the index of the entry in the transparency log")
    43  }
    44  
    45  // addUUIDPFlags adds the "uuid" command to the command's flag set
    46  func addUUIDPFlags(cmd *cobra.Command, required bool) error {
    47  	return addFlagToCmd(cmd, required, uuidFlag, "uuid", "UUID of entry in transparency log (if known)")
    48  }
    49  
    50  func addArtifactPFlags(cmd *cobra.Command) error {
    51  	flags := map[string]struct {
    52  		flagType FlagType
    53  		desc     string
    54  		required bool
    55  	}{
    56  		"signature": {
    57  			fileOrURLFlag,
    58  			"path or URL to detached signature file",
    59  			false,
    60  		},
    61  		"type": {
    62  			typeFlag,
    63  			fmt.Sprintf("type of entry expressed as type(:version)?; supported types = %v", types.ListImplementedTypes()),
    64  			false,
    65  		},
    66  		"pki-format": {
    67  			pkiFormatFlag,
    68  			fmt.Sprintf("format of the signature and/or public key; options = %v", pki.SupportedFormats()),
    69  			false,
    70  		},
    71  		"public-key": {
    72  			multiFileOrURLFlag,
    73  			"path or URL to public key file",
    74  			false,
    75  		},
    76  		"artifact": {
    77  			fileOrURLFlag,
    78  			"path or URL to artifact file",
    79  			false,
    80  		},
    81  		"artifact-hash": {
    82  			shaFlag,
    83  			"hex encoded SHA256 hash of artifact (when using URL)",
    84  			false,
    85  		},
    86  		"entry": {
    87  			fileOrURLFlag,
    88  			"path or URL to pre-formatted entry file",
    89  			false,
    90  		},
    91  		"aad": {
    92  			base64Flag,
    93  			"base64 encoded additional authenticated data",
    94  			false,
    95  		},
    96  	}
    97  
    98  	for flag, flagVal := range flags {
    99  		if err := addFlagToCmd(cmd, flagVal.required, flagVal.flagType, flag, flagVal.desc); err != nil {
   100  			return err
   101  		}
   102  	}
   103  
   104  	return nil
   105  }
   106  
   107  func validateArtifactPFlags(uuidValid, indexValid bool) error {
   108  	uuidGiven := false
   109  	if uuidValid && viper.GetString("uuid") != "" {
   110  		uuidGiven = true
   111  	}
   112  	indexGiven := false
   113  	if indexValid && viper.GetString("log-index") != "" {
   114  		indexGiven = true
   115  	}
   116  
   117  	// if neither --entry or --artifact were given, then a reference to a uuid or index is needed
   118  	if viper.GetString("entry") == "" && viper.GetString("artifact") == "" && viper.GetString("artifact-hash") == "" {
   119  		if (uuidGiven && uuidValid) || (indexGiven && indexValid) {
   120  			return nil
   121  		}
   122  		return errors.New("either 'entry' or 'artifact' or 'artifact-hash' must be specified")
   123  	}
   124  
   125  	return nil
   126  }
   127  
   128  func CreatePropsFromPflags() *types.ArtifactProperties {
   129  	props := &types.ArtifactProperties{}
   130  
   131  	artifactString := viper.GetString("artifact")
   132  	if artifactString != "" {
   133  		if isURL(artifactString) {
   134  			props.ArtifactPath, _ = url.Parse(artifactString)
   135  		} else {
   136  			props.ArtifactPath = &url.URL{Path: artifactString}
   137  		}
   138  	}
   139  
   140  	props.ArtifactHash = viper.GetString("artifact-hash")
   141  
   142  	signatureString := viper.GetString("signature")
   143  	if signatureString != "" {
   144  		if isURL(signatureString) {
   145  			props.SignaturePath, _ = url.Parse(signatureString)
   146  		} else {
   147  			props.SignaturePath = &url.URL{Path: signatureString}
   148  		}
   149  	}
   150  
   151  	publicKeyString := viper.GetString("public-key")
   152  	splitPubKeyString := strings.Split(publicKeyString, ",")
   153  	if len(splitPubKeyString) > 0 {
   154  		collectedKeys := []*url.URL{}
   155  		for _, key := range splitPubKeyString {
   156  			if isURL(key) {
   157  				keyPath, _ := url.Parse(key)
   158  				collectedKeys = append(collectedKeys, keyPath)
   159  			} else {
   160  				collectedKeys = append(collectedKeys, &url.URL{Path: key})
   161  			}
   162  		}
   163  		props.PublicKeyPaths = collectedKeys
   164  	}
   165  
   166  	props.PKIFormat = viper.GetString("pki-format")
   167  	b64aad := viper.GetString("aad")
   168  	if b64aad != "" {
   169  		props.AdditionalAuthenticatedData, _ = base64.StdEncoding.DecodeString(b64aad)
   170  	}
   171  
   172  	return props
   173  }
   174  
   175  // ParseTypeFlag validates the requested type (and optional version) are supported
   176  func ParseTypeFlag(typeStr string) (string, string, error) {
   177  	// typeStr can come in as:
   178  	// type -> use default version for this kind
   179  	// type:version_string -> attempt to use specified version string
   180  
   181  	typeStrings := strings.SplitN(typeStr, ":", 2)
   182  	tf, ok := types.TypeMap.Load(typeStrings[0])
   183  	if !ok {
   184  		return "", "", fmt.Errorf("unknown type %v", typeStrings[0])
   185  	}
   186  	ti := tf.(func() types.TypeImpl)()
   187  	if ti == nil {
   188  		return "", "", fmt.Errorf("type %v is not implemented", typeStrings[0])
   189  	}
   190  
   191  	switch len(typeStrings) {
   192  	case 1:
   193  		return typeStrings[0], "", nil
   194  	case 2:
   195  		if !ti.IsSupportedVersion(typeStrings[1]) {
   196  			return "", "", fmt.Errorf("type %v does not support version %v", typeStrings[0], typeStrings[1])
   197  		}
   198  		return typeStrings[0], typeStrings[1], nil
   199  	}
   200  	return "", "", errors.New("malformed type string")
   201  }
   202  

View as plain text