diff --git a/internal/clis/hmpki/generate.go b/internal/clis/hmpki/generate.go index 9cbc685..2a40a02 100644 --- a/internal/clis/hmpki/generate.go +++ b/internal/clis/hmpki/generate.go @@ -5,28 +5,34 @@ import ( ) // Needed by all subcommands. -var Output string - -// Needed by some subcommands. -var KeyFile string +var Name string +var OutDir string func init() { rootCmd.AddCommand(generateCmd) - // All "generate" commands output an artifact to a file, - // be it a key or a cert, etc. + // Name for artifacts being written to file(s). generateCmd.PersistentFlags().StringVarP( - &Output, - "output", - "o", + &Name, + "name", + "n", "", - "output filename", + "name of the artifact being benerated", ) - generateCmd.MarkPersistentFlagRequired("output") - generateCmd.MarkPersistentFlagFilename("output") + generateCmd.MarkPersistentFlagRequired("name") + + // Output direcotry. + generateCmd.PersistentFlags().StringVar( + &OutDir, + "output-dir", + ".", + "output directory for artifacts produced by this command, defaults to the current directory", + ) + generateCmd.MarkPersistentFlagRequired("output-dir") + generateCmd.MarkPersistentFlagDirname("output-dir") } var generateCmd = &cobra.Command{ Use: "generate", - Short: "Generate pki resources (keys/certs)", + Short: "Generate pki resources (cas/keys/certs)", } diff --git a/internal/clis/hmpki/generate_ca.go b/internal/clis/hmpki/generate_ca.go index 58f8275..4259a63 100644 --- a/internal/clis/hmpki/generate_ca.go +++ b/internal/clis/hmpki/generate_ca.go @@ -1,7 +1,6 @@ package hmpki import ( - "crypto/ecdsa" "crypto/rand" "crypto/x509" "crypto/x509/pkix" @@ -9,7 +8,7 @@ import ( "errors" "math" "math/big" - "os" + "path" "time" "git.handmadecities.com/HMC/shhh/pkg/pki" @@ -18,41 +17,19 @@ import ( func init() { generateCmd.AddCommand(generateCACmd) - - generateCACmd.Flags().StringVar( - &KeyFile, - "key-file", - "", - "File that contains the private key that will be associated to the CA", - ) - generateCACmd.MarkFlagRequired("key-file") - generateCACmd.MarkFlagFilename("key-file") } var generateCACmd = &cobra.Command{ Use: "ca", Short: "Generate a Certificate Authority", RunE: func(cmd *cobra.Command, args []string) error { - // Read key from KeyFile. - keyPemBytes, err := os.ReadFile(KeyFile) - if err != nil { - return err - } - privBlock, _ := pem.Decode(keyPemBytes) - if privBlock == nil || privBlock.Type != pki.PEMTypePrivateKey { - return errors.New("Invalid pem key file, or first block is not a private key") - } - rawKey, err := x509.ParsePKCS8PrivateKey(privBlock.Bytes) - - key, ok := rawKey.(*ecdsa.PrivateKey) - if !ok { - return errors.New("key file did not contain an ecdsa private key") - } + // Private key for the ca. + key := pki.GenerateKey() // Cryptographically random 64bit number as the serial. sn, err := rand.Int(rand.Reader, big.NewInt(math.MaxInt64)) if err != nil { - errors.New("Could not generate a ca serial number") + return errors.New("Could not generate a ca serial number") } caTmpl := &x509.Certificate{ SerialNumber: sn, @@ -87,17 +64,16 @@ var generateCACmd = &cobra.Command{ Bytes: caBytes, }) - caf, err := os.OpenFile( - Output, - // Write only, and fail if it alreay exists. - os.O_WRONLY|os.O_CREATE|os.O_EXCL, - pki.CertFilePerms, - ) + // Write ca to disk. + cafn := path.Join(OutDir, Name+"_ca.crt") + err = createFileWith(cafn, caPEMBytes, pki.CertFilePerms) if err != nil { return err } - defer caf.Close() - if _, err = caf.Write(caPEMBytes); err != nil { + // Write private key to disk. + keyfn := path.Join(OutDir, Name+"_ca.key") + err = createFileWith(keyfn, pki.MarshalKeyToPEM(key), pki.PrivateKeyFilePerms) + if err != nil { return err }