145 lines
4.1 KiB
Go
145 lines
4.1 KiB
Go
|
package cmd
|
||
|
|
||
|
import (
|
||
|
"crypto/x509"
|
||
|
"fmt"
|
||
|
"log"
|
||
|
"math/big"
|
||
|
"os"
|
||
|
|
||
|
"github.com/joho/godotenv"
|
||
|
"github.com/kelseyhightower/envconfig"
|
||
|
"github.com/spf13/cobra"
|
||
|
"github.com/spf13/viper"
|
||
|
"gitlab.com/urkob/go-cert-gen/internal/cert"
|
||
|
"gitlab.com/urkob/go-cert-gen/internal/io"
|
||
|
"gitlab.com/urkob/go-cert-gen/pkg/ca"
|
||
|
"gitlab.com/urkob/go-cert-gen/pkg/client"
|
||
|
pkgio "gitlab.com/urkob/go-cert-gen/pkg/io"
|
||
|
"gitlab.com/urkob/go-cert-gen/pkg/util"
|
||
|
)
|
||
|
|
||
|
var envConfig struct {
|
||
|
ViperConfig string `required:"true" split_words:"true"`
|
||
|
ViperConfigType string `required:"true" split_words:"true"`
|
||
|
Env string `required:"true" split_words:"true"`
|
||
|
}
|
||
|
|
||
|
var writer pkgio.WriterIface
|
||
|
|
||
|
func intEnvConfig(isProd bool) {
|
||
|
if !isProd {
|
||
|
err := godotenv.Load(util.RootDir() + "/.env")
|
||
|
if err != nil {
|
||
|
log.Fatalf("environment variable ENV is empty and an error occurred while loading the .env file: %s\n", err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
err := envconfig.Process("", &envConfig)
|
||
|
if err != nil {
|
||
|
log.Fatalf("envconfig.Process: %s\n", err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var rootCmd = &cobra.Command{
|
||
|
Use: "go-gen-cert",
|
||
|
Short: "go-gen-cert is a CLI tool to generate TLS certificates for your gRPC client/server communication",
|
||
|
Run: func(cmd *cobra.Command, args []string) {
|
||
|
caCfg := &ca.CaConfig{
|
||
|
SerialNumber: big.NewInt(viper.GetInt64("ca.serial_number")),
|
||
|
Subject: ca.CaSubject{
|
||
|
Organization: viper.GetString("ca.subject.organization"),
|
||
|
CommonName: viper.GetString("ca.subject.common_name"),
|
||
|
},
|
||
|
KeyUsage: x509.KeyUsage(viper.GetInt("ca.key_usage")),
|
||
|
ExtKeyUsage: getExtKeyUsage(viper.GetIntSlice("ca.ext_key_usage")),
|
||
|
Duration: viper.GetDuration("ca.duration"),
|
||
|
}
|
||
|
|
||
|
rootCA, err := cert.NewRootCA(caCfg)
|
||
|
if err != nil {
|
||
|
log.Fatalf("cert.NewRootCA: %s", err)
|
||
|
}
|
||
|
|
||
|
subjectKeyId, err := util.GetBytes(viper.Get("client.subject_key_id"))
|
||
|
if err != nil {
|
||
|
log.Fatalf("cert.NewRootCA: %s", err)
|
||
|
}
|
||
|
|
||
|
clientCfg := &client.ClientCertConfig{
|
||
|
Serial: &big.Int{},
|
||
|
Subject: client.Subject{
|
||
|
Organization: viper.GetString("client.subject.organization"),
|
||
|
Country: viper.GetString("client.subject.country"),
|
||
|
Province: viper.GetString("client.subject.province"),
|
||
|
Locality: viper.GetString("client.subject.locality"),
|
||
|
StreetAddress: viper.GetString("client.subject.street_address"),
|
||
|
PostalCode: viper.GetString("client.subject.postal_code"),
|
||
|
},
|
||
|
Duration: viper.GetDuration("client.duration"),
|
||
|
SubjectKeyId: subjectKeyId,
|
||
|
ExtKeyUsage: getExtKeyUsage(viper.GetIntSlice("client.ext_key_usage")),
|
||
|
KeyUsage: x509.KeyUsage(viper.GetInt("client.key_usage")),
|
||
|
}
|
||
|
|
||
|
clientCert, err := rootCA.WithClientCert(clientCfg)
|
||
|
if err != nil {
|
||
|
log.Fatalf("rootCA.WithClientCert: %s", err)
|
||
|
}
|
||
|
|
||
|
exportPem("root-ca.pem", rootCA.PEM())
|
||
|
exportPem("root-key.pem", rootCA.Key())
|
||
|
|
||
|
exportPem("client-cert.pem", clientCert.PEM())
|
||
|
exportPem("client-key.pem", clientCert.Key())
|
||
|
},
|
||
|
}
|
||
|
|
||
|
func getExtKeyUsage(intKeyUsageSlice []int) []x509.ExtKeyUsage {
|
||
|
extKeyUsage := make([]x509.ExtKeyUsage, len(intKeyUsageSlice))
|
||
|
for _, v := range intKeyUsageSlice {
|
||
|
extKeyUsage = append(extKeyUsage, x509.ExtKeyUsage(v))
|
||
|
}
|
||
|
return extKeyUsage
|
||
|
}
|
||
|
|
||
|
func exportPem(filename string, data []byte) {
|
||
|
outputPath, err := writer.WriteFile(filename, data)
|
||
|
if err != nil {
|
||
|
log.Fatalf("rootCA.WithClientCert: %s", err)
|
||
|
}
|
||
|
log.Printf("file created successfuly: %s\n", outputPath)
|
||
|
}
|
||
|
|
||
|
func init() {
|
||
|
intEnvConfig(false)
|
||
|
cobra.OnInitialize(initConfig)
|
||
|
}
|
||
|
|
||
|
func initConfig() {
|
||
|
if envConfig.ViperConfig != "" {
|
||
|
viper.AddConfigPath(util.RootDir())
|
||
|
viper.SetConfigName(envConfig.ViperConfig)
|
||
|
viper.SetConfigType(envConfig.ViperConfigType)
|
||
|
} else {
|
||
|
home, err := os.UserHomeDir()
|
||
|
cobra.CheckErr(err)
|
||
|
viper.AddConfigPath(home)
|
||
|
viper.SetConfigType("yaml")
|
||
|
viper.SetConfigName(".cobra")
|
||
|
}
|
||
|
|
||
|
if err := viper.ReadInConfig(); err != nil {
|
||
|
log.Fatalf("viper.ReadInConfig: %s", err)
|
||
|
}
|
||
|
log.Println("viper.GetString('export_dir)", viper.GetString("export_dir"))
|
||
|
writer = io.NewWriter(viper.GetString("export_dir"))
|
||
|
}
|
||
|
|
||
|
func Execute() {
|
||
|
if err := rootCmd.Execute(); err != nil {
|
||
|
fmt.Fprintln(os.Stderr, err)
|
||
|
os.Exit(1)
|
||
|
}
|
||
|
}
|