github.com/moqsien/xraycore@v1.8.5/main/commands/all/tls/cert.go (about)

     1  package tls
     2  
     3  import (
     4  	"context"
     5  	"crypto/x509"
     6  	"encoding/json"
     7  	"os"
     8  	"strings"
     9  	"time"
    10  
    11  	"github.com/moqsien/xraycore/common"
    12  	"github.com/moqsien/xraycore/common/protocol/tls/cert"
    13  	"github.com/moqsien/xraycore/common/task"
    14  	"github.com/moqsien/xraycore/main/commands/base"
    15  )
    16  
    17  // cmdCert is the tls cert command
    18  var cmdCert = &base.Command{
    19  	UsageLine: "{{.Exec}} tls cert [--ca] [--domain=example.com] [--expire=240h]",
    20  	Short:     "Generate TLS certificates",
    21  	Long: `
    22  Generate TLS certificates.
    23  
    24  Arguments:
    25  
    26  	-domain=domain_name 
    27  		The domain name for the certificate.
    28  
    29  	-name=common_name 
    30  		The common name for the certificate.
    31  
    32  	-org=organization 
    33  		The organization name for the certificate.
    34  
    35  	-ca 
    36  		Whether this certificate is a CA
    37  
    38  	-json 
    39  		The output of certificate to JSON
    40  
    41  	-file 
    42  		The certificate path to save.
    43  
    44  	-expire 
    45  		Expire time of the certificate. Default value 3 months.
    46  `,
    47  }
    48  
    49  func init() {
    50  	cmdCert.Run = executeCert // break init loop
    51  }
    52  
    53  var (
    54  	certDomainNames stringList
    55  	_               = func() bool {
    56  		cmdCert.Flag.Var(&certDomainNames, "domain", "Domain name for the certificate")
    57  		return true
    58  	}()
    59  
    60  	certCommonName   = cmdCert.Flag.String("name", "Xray Inc", "The common name of this certificate")
    61  	certOrganization = cmdCert.Flag.String("org", "Xray Inc", "Organization of the certificate")
    62  	certIsCA         = cmdCert.Flag.Bool("ca", false, "Whether this certificate is a CA")
    63  	certJSONOutput   = cmdCert.Flag.Bool("json", true, "Print certificate in JSON format")
    64  	certFileOutput   = cmdCert.Flag.String("file", "", "Save certificate in file.")
    65  	certExpire       = cmdCert.Flag.Duration("expire", time.Hour*24*90 /* 90 days */, "Time until the certificate expires. Default value 3 months.")
    66  )
    67  
    68  func executeCert(cmd *base.Command, args []string) {
    69  	var opts []cert.Option
    70  	if *certIsCA {
    71  		opts = append(opts, cert.Authority(*certIsCA))
    72  		opts = append(opts, cert.KeyUsage(x509.KeyUsageCertSign|x509.KeyUsageKeyEncipherment|x509.KeyUsageDigitalSignature))
    73  	}
    74  
    75  	opts = append(opts, cert.NotAfter(time.Now().Add(*certExpire)))
    76  	opts = append(opts, cert.CommonName(*certCommonName))
    77  	if len(certDomainNames) > 0 {
    78  		opts = append(opts, cert.DNSNames(certDomainNames...))
    79  	}
    80  	opts = append(opts, cert.Organization(*certOrganization))
    81  
    82  	cert, err := cert.Generate(nil, opts...)
    83  	if err != nil {
    84  		base.Fatalf("failed to generate TLS certificate: %s", err)
    85  	}
    86  
    87  	if *certJSONOutput {
    88  		printJSON(cert)
    89  	}
    90  
    91  	if len(*certFileOutput) > 0 {
    92  		if err := printFile(cert, *certFileOutput); err != nil {
    93  			base.Fatalf("failed to save file: %s", err)
    94  		}
    95  	}
    96  }
    97  
    98  func printJSON(certificate *cert.Certificate) {
    99  	certPEM, keyPEM := certificate.ToPEM()
   100  	jCert := &jsonCert{
   101  		Certificate: strings.Split(strings.TrimSpace(string(certPEM)), "\n"),
   102  		Key:         strings.Split(strings.TrimSpace(string(keyPEM)), "\n"),
   103  	}
   104  	content, err := json.MarshalIndent(jCert, "", "  ")
   105  	common.Must(err)
   106  	os.Stdout.Write(content)
   107  	os.Stdout.WriteString("\n")
   108  }
   109  
   110  func writeFile(content []byte, name string) error {
   111  	f, err := os.Create(name)
   112  	if err != nil {
   113  		return err
   114  	}
   115  	defer f.Close()
   116  
   117  	return common.Error2(f.Write(content))
   118  }
   119  
   120  func printFile(certificate *cert.Certificate, name string) error {
   121  	certPEM, keyPEM := certificate.ToPEM()
   122  	return task.Run(context.Background(), func() error {
   123  		return writeFile(certPEM, name+"_cert.pem")
   124  	}, func() error {
   125  		return writeFile(keyPEM, name+"_key.pem")
   126  	})
   127  }
   128  
   129  type stringList []string
   130  
   131  func (l *stringList) String() string {
   132  	return "String list"
   133  }
   134  
   135  func (l *stringList) Set(v string) error {
   136  	if v == "" {
   137  		base.Fatalf("empty value")
   138  	}
   139  	*l = append(*l, v)
   140  	return nil
   141  }
   142  
   143  type jsonCert struct {
   144  	Certificate []string `json:"certificate"`
   145  	Key         []string `json:"key"`
   146  }