mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 19:58:17 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			200 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			200 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Package cli provides the template for adding new cfssl commands
 | 
						|
package cli
 | 
						|
 | 
						|
/*
 | 
						|
cfssl is the command line tool to issue/sign/bundle client certificate. It's
 | 
						|
also a tool to start a HTTP server to handle web requests for signing, bundling
 | 
						|
and verification.
 | 
						|
 | 
						|
Usage:
 | 
						|
	cfssl command [-flags] arguments
 | 
						|
 | 
						|
The commands are defined in the cli subpackages and include
 | 
						|
 | 
						|
	bundle	 create a certificate bundle
 | 
						|
	sign	 signs a certificate signing request (CSR)
 | 
						|
	serve	 starts a HTTP server handling sign and bundle requests
 | 
						|
	version	 prints the current cfssl version
 | 
						|
	genkey   generates a key and an associated CSR
 | 
						|
	gencert  generates a key and a signed certificate
 | 
						|
	gencsr   generates a certificate request
 | 
						|
	selfsign generates a self-signed certificate
 | 
						|
	ocspsign signs an OCSP response
 | 
						|
 | 
						|
Use "cfssl [command] -help" to find out more about a command.
 | 
						|
*/
 | 
						|
 | 
						|
import (
 | 
						|
	"encoding/base64"
 | 
						|
	"encoding/json"
 | 
						|
	"errors"
 | 
						|
	"flag"
 | 
						|
	"fmt"
 | 
						|
	"io/ioutil"
 | 
						|
	"os"
 | 
						|
 | 
						|
	"github.com/cloudflare/cfssl/config"
 | 
						|
)
 | 
						|
 | 
						|
// Command holds the implementation details of a cfssl command.
 | 
						|
type Command struct {
 | 
						|
	// The Usage Text
 | 
						|
	UsageText string
 | 
						|
	// Flags to look up in the global table
 | 
						|
	Flags []string
 | 
						|
	// Main runs the command, args are the arguments after flags
 | 
						|
	Main func(args []string, c Config) error
 | 
						|
}
 | 
						|
 | 
						|
var cmdName string
 | 
						|
 | 
						|
// usage is the cfssl usage heading. It will be appended with names of defined commands in cmds
 | 
						|
// to form the final usage message of cfssl.
 | 
						|
const usage = `Usage:
 | 
						|
Available commands:
 | 
						|
`
 | 
						|
 | 
						|
// printDefaultValue is a helper function to print out a user friendly
 | 
						|
// usage message of a flag. It's useful since we want to write customized
 | 
						|
// usage message on selected subsets of the global flag set. It is
 | 
						|
// borrowed from standard library source code. Since flag value type is
 | 
						|
// not exported, default string flag values are printed without
 | 
						|
// quotes. The only exception is the empty string, which is printed as "".
 | 
						|
func printDefaultValue(f *flag.Flag) {
 | 
						|
	format := "  -%s=%s: %s\n"
 | 
						|
	if f.DefValue == "" {
 | 
						|
		format = "  -%s=%q: %s\n"
 | 
						|
	}
 | 
						|
	fmt.Fprintf(os.Stderr, format, f.Name, f.DefValue, f.Usage)
 | 
						|
}
 | 
						|
 | 
						|
// PopFirstArgument returns the first element and the rest of a string
 | 
						|
// slice and return error if failed to do so. It is a helper function
 | 
						|
// to parse non-flag arguments previously used in cfssl commands.
 | 
						|
func PopFirstArgument(args []string) (string, []string, error) {
 | 
						|
	if len(args) < 1 {
 | 
						|
		return "", nil, errors.New("not enough arguments are supplied --- please refer to the usage")
 | 
						|
	}
 | 
						|
	return args[0], args[1:], nil
 | 
						|
}
 | 
						|
 | 
						|
// Start is the entrance point of cfssl command line tools.
 | 
						|
func Start(cmds map[string]*Command) error {
 | 
						|
	// cfsslFlagSet is the flag sets for cfssl.
 | 
						|
	var cfsslFlagSet = flag.NewFlagSet("cfssl", flag.ExitOnError)
 | 
						|
	var c Config
 | 
						|
 | 
						|
	registerFlags(&c, cfsslFlagSet)
 | 
						|
	// Initial parse of command line arguments. By convention, only -h/-help is supported.
 | 
						|
	if flag.Usage == nil {
 | 
						|
		flag.Usage = func() {
 | 
						|
			fmt.Fprintf(os.Stderr, usage)
 | 
						|
			for name := range cmds {
 | 
						|
				fmt.Fprintf(os.Stderr, "\t%s\n", name)
 | 
						|
			}
 | 
						|
			fmt.Fprintf(os.Stderr, "Top-level flags:\n")
 | 
						|
			flag.PrintDefaults()
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	flag.Parse()
 | 
						|
 | 
						|
	if flag.NArg() < 1 {
 | 
						|
		fmt.Fprintf(os.Stderr, "No command is given.\n")
 | 
						|
		flag.Usage()
 | 
						|
		return errors.New("no command was given")
 | 
						|
	}
 | 
						|
 | 
						|
	// Clip out the command name and args for the command
 | 
						|
	cmdName = flag.Arg(0)
 | 
						|
	args := flag.Args()[1:]
 | 
						|
	cmd, found := cmds[cmdName]
 | 
						|
	if !found {
 | 
						|
		fmt.Fprintf(os.Stderr, "Command %s is not defined.\n", cmdName)
 | 
						|
		flag.Usage()
 | 
						|
		return errors.New("undefined command")
 | 
						|
	}
 | 
						|
	// always have flag 'loglevel' for each command
 | 
						|
	cmd.Flags = append(cmd.Flags, "loglevel")
 | 
						|
	// The usage of each individual command is re-written to mention
 | 
						|
	// flags defined and referenced only in that command.
 | 
						|
	cfsslFlagSet.Usage = func() {
 | 
						|
		fmt.Fprintf(os.Stderr, "\t%s", cmd.UsageText)
 | 
						|
		for _, name := range cmd.Flags {
 | 
						|
			if f := cfsslFlagSet.Lookup(name); f != nil {
 | 
						|
				printDefaultValue(f)
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	// Parse all flags and take the rest as argument lists for the command
 | 
						|
	cfsslFlagSet.Parse(args)
 | 
						|
	args = cfsslFlagSet.Args()
 | 
						|
 | 
						|
	var err error
 | 
						|
	if c.ConfigFile != "" {
 | 
						|
		c.CFG, err = config.LoadFile(c.ConfigFile)
 | 
						|
		if err != nil {
 | 
						|
			fmt.Fprintf(os.Stderr, "Failed to load config file: %v", err)
 | 
						|
			return errors.New("failed to load config file")
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if err := cmd.Main(args, c); err != nil {
 | 
						|
		fmt.Fprintln(os.Stderr, err)
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
// ReadStdin reads from stdin if the file is "-"
 | 
						|
func ReadStdin(filename string) ([]byte, error) {
 | 
						|
	if filename == "-" {
 | 
						|
		return ioutil.ReadAll(os.Stdin)
 | 
						|
	}
 | 
						|
	return ioutil.ReadFile(filename)
 | 
						|
}
 | 
						|
 | 
						|
// PrintCert outputs a cert, key and csr to stdout
 | 
						|
func PrintCert(key, csrBytes, cert []byte) {
 | 
						|
	out := map[string]string{}
 | 
						|
	if cert != nil {
 | 
						|
		out["cert"] = string(cert)
 | 
						|
	}
 | 
						|
 | 
						|
	if key != nil {
 | 
						|
		out["key"] = string(key)
 | 
						|
	}
 | 
						|
 | 
						|
	if csrBytes != nil {
 | 
						|
		out["csr"] = string(csrBytes)
 | 
						|
	}
 | 
						|
 | 
						|
	jsonOut, err := json.Marshal(out)
 | 
						|
	if err != nil {
 | 
						|
		return
 | 
						|
	}
 | 
						|
	fmt.Printf("%s\n", jsonOut)
 | 
						|
}
 | 
						|
 | 
						|
// PrintOCSPResponse outputs an OCSP response to stdout
 | 
						|
// ocspResponse is base64 encoded
 | 
						|
func PrintOCSPResponse(resp []byte) {
 | 
						|
	b64Resp := base64.StdEncoding.EncodeToString(resp)
 | 
						|
 | 
						|
	out := map[string]string{"ocspResponse": b64Resp}
 | 
						|
	jsonOut, err := json.Marshal(out)
 | 
						|
	if err != nil {
 | 
						|
		return
 | 
						|
	}
 | 
						|
	fmt.Printf("%s\n", jsonOut)
 | 
						|
}
 | 
						|
 | 
						|
// PrintCRL outputs the CRL to stdout
 | 
						|
func PrintCRL(certList []byte) {
 | 
						|
	b64Resp := base64.StdEncoding.EncodeToString(certList)
 | 
						|
 | 
						|
	fmt.Printf("%s\n", b64Resp)
 | 
						|
}
 |