github.com/pojntfx/hydrapp/hydrapp@v0.0.0-20240516002902-d08759d6ca9f/cmd/secrets_new.go (about)

     1  package cmd
     2  
     3  import (
     4  	"bytes"
     5  	"os"
     6  	"path/filepath"
     7  	"strings"
     8  	"time"
     9  
    10  	"github.com/pojntfx/hydrapp/hydrapp/pkg/secrets"
    11  	"github.com/spf13/cobra"
    12  	"github.com/spf13/viper"
    13  	"gopkg.in/yaml.v2"
    14  )
    15  
    16  const (
    17  	javaKeystorePasswordFlag    = "java-keystore-password"
    18  	javaCertificatePasswordFlag = "java-certificate-password"
    19  	javaCertificateAliasFlag    = "java-certificate-alias"
    20  	javaCertificateCNAMEFlag    = "java-certificate-cname"
    21  	javaCertificateValidityFlag = "java-certificate-validity"
    22  	javaRSABitsFlag             = "java-rsa-bits"
    23  
    24  	pgpKeyFullNameFlag = "pgp-key-full-name"
    25  	pgpKeyEmailFlag    = "pgp-key-email"
    26  	pgpKeyPasswordFlag = "pgp-key-password"
    27  
    28  	fullNameDefault            = "Anonymous hydrapp Developer"
    29  	emailDefault               = "test@example.com"
    30  	certificateValidityDefault = time.Hour * 24 * 365
    31  	javaRSABitsDefault         = 2048
    32  )
    33  
    34  var secretsNewCmd = &cobra.Command{
    35  	Use:     "new",
    36  	Aliases: []string{"n"},
    37  	Short:   "Generate new hydrapp secrets",
    38  	RunE: func(cmd *cobra.Command, args []string) error {
    39  		if err := viper.BindPFlags(cmd.PersistentFlags()); err != nil {
    40  			return err
    41  		}
    42  
    43  		keystorePassword := viper.GetString(javaKeystorePasswordFlag)
    44  		if strings.TrimSpace(keystorePassword) == "" {
    45  			v, err := secrets.GeneratePassword(32)
    46  			if err != nil {
    47  				return err
    48  			}
    49  
    50  			keystorePassword = v
    51  		}
    52  
    53  		certificatePassword := viper.GetString(javaCertificatePasswordFlag)
    54  		if strings.TrimSpace(certificatePassword) == "" {
    55  			v, err := secrets.GeneratePassword(32)
    56  			if err != nil {
    57  				return err
    58  			}
    59  
    60  			certificatePassword = v
    61  		}
    62  
    63  		keystoreBuf := &bytes.Buffer{}
    64  		if err := secrets.GenerateKeystore(
    65  			keystorePassword,
    66  			certificatePassword,
    67  			viper.GetString(javaCertificateAliasFlag),
    68  			viper.GetString(javaCertificateCNAMEFlag),
    69  			viper.GetDuration(javaCertificateValidityFlag),
    70  			viper.GetUint32(javaRSABitsFlag),
    71  			keystoreBuf,
    72  		); err != nil {
    73  			return err
    74  		}
    75  
    76  		pgpPassword := viper.GetString(pgpKeyPasswordFlag)
    77  		if strings.TrimSpace(pgpPassword) == "" {
    78  			v, err := secrets.GeneratePassword(32)
    79  			if err != nil {
    80  				return err
    81  			}
    82  
    83  			pgpPassword = v
    84  		}
    85  
    86  		pgpKey, pgpKeyID, err := secrets.GeneratePGPKey(
    87  			viper.GetString(pgpKeyFullNameFlag),
    88  			viper.GetString(pgpKeyEmailFlag),
    89  			pgpPassword,
    90  		)
    91  		if err != nil {
    92  			return err
    93  		}
    94  
    95  		output := &secrets.Root{
    96  			JavaSecrets: secrets.JavaSecrets{
    97  				Keystore:            keystoreBuf.Bytes(),
    98  				KeystorePassword:    keystorePassword,
    99  				CertificatePassword: certificatePassword,
   100  			},
   101  			PGPSecrets: secrets.PGPSecrets{
   102  				Key:         pgpKey,
   103  				KeyID:       pgpKeyID,
   104  				KeyPassword: pgpPassword,
   105  			},
   106  		}
   107  
   108  		if err := os.MkdirAll(filepath.Dir(viper.GetString(secretsFlag)), os.ModePerm); err != nil {
   109  			return err
   110  		}
   111  
   112  		out, err := os.OpenFile(viper.GetString(secretsFlag), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm)
   113  		if err != nil {
   114  			return err
   115  		}
   116  		defer out.Close()
   117  
   118  		return yaml.NewEncoder(out).Encode(output)
   119  	},
   120  }
   121  
   122  func init() {
   123  	secretsNewCmd.PersistentFlags().String(javaKeystorePasswordFlag, "", "Java/APK keystore password (auto-generated if not specified)")
   124  	secretsNewCmd.PersistentFlags().String(javaCertificatePasswordFlag, "", "Java/APK certificate password (auto-generated if not specified)")
   125  	secretsNewCmd.PersistentFlags().String(javaCertificateAliasFlag, fullNameDefault, "Java/APK certificate alias")
   126  	secretsNewCmd.PersistentFlags().String(javaCertificateCNAMEFlag, fullNameDefault, "Java/APK certificate CNAME")
   127  	secretsNewCmd.PersistentFlags().Duration(javaCertificateValidityFlag, certificateValidityDefault, "Java/APK certificate validty")
   128  	secretsNewCmd.PersistentFlags().Uint32(javaRSABitsFlag, javaRSABitsDefault, "Java/APK RSA bits")
   129  
   130  	secretsNewCmd.PersistentFlags().String(pgpKeyFullNameFlag, fullNameDefault, "PGP key full name")
   131  	secretsNewCmd.PersistentFlags().String(pgpKeyEmailFlag, emailDefault, "PGP key E-Mail")
   132  	secretsNewCmd.PersistentFlags().String(pgpKeyPasswordFlag, "", "PGP key password (auto-generated if not specified)")
   133  
   134  	viper.AutomaticEnv()
   135  
   136  	secretsCmd.AddCommand(secretsNewCmd)
   137  }