...

Source file src/github.com/sassoftware/relic/cmdline/token/signcmd.go

Documentation: github.com/sassoftware/relic/cmdline/token

     1  //
     2  // Copyright (c) SAS Institute Inc.
     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  
    17  package token
    18  
    19  import (
    20  	"bytes"
    21  	"context"
    22  	"errors"
    23  	"fmt"
    24  	"os"
    25  
    26  	"github.com/sassoftware/relic/cmdline/shared"
    27  	"github.com/sassoftware/relic/internal/signinit"
    28  	"github.com/sassoftware/relic/signers"
    29  	"github.com/spf13/cobra"
    30  )
    31  
    32  var SignCmd = &cobra.Command{
    33  	Use:   "sign",
    34  	Short: "Sign a package using a token",
    35  	RunE:  signCmd,
    36  }
    37  
    38  var (
    39  	argIfUnsigned bool
    40  	argSigType    string
    41  	argOutput     string
    42  )
    43  
    44  func init() {
    45  	shared.RootCmd.AddCommand(SignCmd)
    46  	addKeyFlags(SignCmd)
    47  	SignCmd.Flags().StringVarP(&argFile, "file", "f", "", "Input file to sign")
    48  	SignCmd.Flags().StringVarP(&argOutput, "output", "o", "", "Output file")
    49  	SignCmd.Flags().StringVarP(&argSigType, "sig-type", "T", "", "Specify signature type (default: auto-detect)")
    50  	SignCmd.Flags().BoolVar(&argIfUnsigned, "if-unsigned", false, "Skip signing if the file already has a signature")
    51  	shared.AddDigestFlag(SignCmd)
    52  	shared.AddLateHook(func() {
    53  		signers.MergeFlags(SignCmd.Flags())
    54  	})
    55  }
    56  
    57  func signCmd(cmd *cobra.Command, args []string) error {
    58  	if argFile == "" || argKeyName == "" {
    59  		return errors.New("--file and --key are required")
    60  	}
    61  	if argOutput == "" {
    62  		argOutput = argFile
    63  	}
    64  	mod, err := signers.ByFile(argFile, argSigType)
    65  	if err != nil {
    66  		return shared.Fail(err)
    67  	}
    68  	if mod.Sign == nil {
    69  		return shared.Fail(errors.New("can't sign this type of file"))
    70  	}
    71  	flags, err := mod.FlagsFromCmdline(cmd.Flags())
    72  	if err != nil {
    73  		return shared.Fail(err)
    74  	}
    75  	hash, err := shared.GetDigest()
    76  	if err != nil {
    77  		return shared.Fail(err)
    78  	}
    79  	token, err := openTokenByKey(argKeyName)
    80  	if err != nil {
    81  		return shared.Fail(err)
    82  	}
    83  	cert, opts, err := signinit.Init(context.Background(), mod, token, argKeyName, hash, flags)
    84  	if err != nil {
    85  		return shared.Fail(err)
    86  	}
    87  	opts.Path = argFile
    88  	infile, err := os.OpenFile(argFile, os.O_RDWR, 0)
    89  	if err != nil {
    90  		return shared.Fail(err)
    91  	}
    92  	defer infile.Close()
    93  	if argIfUnsigned {
    94  		if signed, err := mod.IsSigned(infile); err != nil {
    95  			return shared.Fail(err)
    96  		} else if signed {
    97  			fmt.Fprintf(os.Stderr, "skipping already-signed file: %s\n", argFile)
    98  			return nil
    99  		}
   100  		if _, err := infile.Seek(0, 0); err != nil {
   101  			return shared.Fail(fmt.Errorf("failed to rewind input file: %s", err))
   102  		}
   103  	}
   104  	// transform the input, sign the stream, and apply the result
   105  	transform, err := mod.GetTransform(infile, *opts)
   106  	if err != nil {
   107  		return shared.Fail(err)
   108  	}
   109  	stream, err := transform.GetReader()
   110  	if err != nil {
   111  		return shared.Fail(err)
   112  	}
   113  	blob, err := mod.Sign(stream, cert, *opts)
   114  	if err != nil {
   115  		return shared.Fail(err)
   116  	}
   117  	mimeType := opts.Audit.GetMimeType()
   118  	if err := transform.Apply(argOutput, mimeType, bytes.NewReader(blob)); err != nil {
   119  		return shared.Fail(err)
   120  	}
   121  	// if needed, do a final fixup step
   122  	if mod.Fixup != nil {
   123  		f, err := os.OpenFile(argOutput, os.O_RDWR, 0)
   124  		if err != nil {
   125  			return shared.Fail(err)
   126  		}
   127  		defer f.Close()
   128  		if err := mod.Fixup(f); err != nil {
   129  			return shared.Fail(err)
   130  		}
   131  	}
   132  	if err := signinit.PublishAudit(opts.Audit); err != nil {
   133  		return err
   134  	}
   135  	fmt.Fprintln(os.Stderr, "Signed", argFile)
   136  	return nil
   137  }
   138  

View as plain text