mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-26 12:27:06 +00:00 
			
		
		
		
	Feature: Integrate crypto/tls/generate_cert.go command
This commit is contained in:
		
							
								
								
									
										158
									
								
								cmd/cert.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										158
									
								
								cmd/cert.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,158 @@ | |||||||
|  | // Copyright 2009 The Go Authors. All rights reserved. | ||||||
|  | // Copyright 2014 The Gogs Authors. All rights reserved. | ||||||
|  | // Use of this source code is governed by a MIT-style | ||||||
|  | // license that can be found in the LICENSE file. | ||||||
|  |  | ||||||
|  | package cmd | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"crypto/ecdsa" | ||||||
|  | 	"crypto/elliptic" | ||||||
|  | 	"crypto/rand" | ||||||
|  | 	"crypto/rsa" | ||||||
|  | 	"crypto/x509" | ||||||
|  | 	"crypto/x509/pkix" | ||||||
|  | 	"encoding/pem" | ||||||
|  | 	"log" | ||||||
|  | 	"math/big" | ||||||
|  | 	"net" | ||||||
|  | 	"os" | ||||||
|  | 	"strings" | ||||||
|  | 	"time" | ||||||
|  |  | ||||||
|  | 	"github.com/codegangsta/cli" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | var CmdCert = cli.Command{ | ||||||
|  | 	Name:  "cert", | ||||||
|  | 	Usage: "Generate self-signed certificate", | ||||||
|  | 	Description: `Generate a self-signed X.509 certificate for a TLS server.  | ||||||
|  | Outputs to 'cert.pem' and 'key.pem' and will overwrite existing files.`, | ||||||
|  | 	Action: runCert, | ||||||
|  | 	Flags: []cli.Flag{ | ||||||
|  | 		cli.StringFlag{"host", "", "Comma-separated hostnames and IPs to generate a certificate for", ""}, | ||||||
|  | 		cli.StringFlag{"ecdsa-curve", "", "ECDSA curve to use to generate a key. Valid values are P224, P256, P384, P521", ""}, | ||||||
|  | 		cli.IntFlag{"rsa-bits", 2048, "Size of RSA key to generate. Ignored if --ecdsa-curve is set", ""}, | ||||||
|  | 		cli.StringFlag{"start-date", "", "Creation date formatted as Jan 1 15:04:05 2011", ""}, | ||||||
|  | 		cli.DurationFlag{"duration", 365 * 24 * time.Hour, "Duration that certificate is valid for", ""}, | ||||||
|  | 		cli.BoolFlag{"ca", "whether this cert should be its own Certificate Authority", ""}, | ||||||
|  | 	}, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func publicKey(priv interface{}) interface{} { | ||||||
|  | 	switch k := priv.(type) { | ||||||
|  | 	case *rsa.PrivateKey: | ||||||
|  | 		return &k.PublicKey | ||||||
|  | 	case *ecdsa.PrivateKey: | ||||||
|  | 		return &k.PublicKey | ||||||
|  | 	default: | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func pemBlockForKey(priv interface{}) *pem.Block { | ||||||
|  | 	switch k := priv.(type) { | ||||||
|  | 	case *rsa.PrivateKey: | ||||||
|  | 		return &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(k)} | ||||||
|  | 	case *ecdsa.PrivateKey: | ||||||
|  | 		b, err := x509.MarshalECPrivateKey(k) | ||||||
|  | 		if err != nil { | ||||||
|  | 			log.Fatal("unable to marshal ECDSA private key: %v", err) | ||||||
|  | 		} | ||||||
|  | 		return &pem.Block{Type: "EC PRIVATE KEY", Bytes: b} | ||||||
|  | 	default: | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func runCert(ctx *cli.Context) { | ||||||
|  | 	if len(ctx.String("host")) == 0 { | ||||||
|  | 		log.Fatal("Missing required --host parameter") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var priv interface{} | ||||||
|  | 	var err error | ||||||
|  | 	switch ctx.String("ecdsa-curve") { | ||||||
|  | 	case "": | ||||||
|  | 		priv, err = rsa.GenerateKey(rand.Reader, ctx.Int("rsa-bits")) | ||||||
|  | 	case "P224": | ||||||
|  | 		priv, err = ecdsa.GenerateKey(elliptic.P224(), rand.Reader) | ||||||
|  | 	case "P256": | ||||||
|  | 		priv, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader) | ||||||
|  | 	case "P384": | ||||||
|  | 		priv, err = ecdsa.GenerateKey(elliptic.P384(), rand.Reader) | ||||||
|  | 	case "P521": | ||||||
|  | 		priv, err = ecdsa.GenerateKey(elliptic.P521(), rand.Reader) | ||||||
|  | 	default: | ||||||
|  | 		log.Fatalf("Unrecognized elliptic curve: %q", ctx.String("ecdsa-curve")) | ||||||
|  | 	} | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatalf("Failed to generate private key: %s", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var notBefore time.Time | ||||||
|  | 	if len(ctx.String("start-date")) == 0 { | ||||||
|  | 		notBefore = time.Now() | ||||||
|  | 	} else { | ||||||
|  | 		notBefore, err = time.Parse("Jan 2 15:04:05 2006", ctx.String("start-date")) | ||||||
|  | 		if err != nil { | ||||||
|  | 			log.Fatalf("Failed to parse creation date: %s", err) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	notAfter := notBefore.Add(ctx.Duration("duration")) | ||||||
|  |  | ||||||
|  | 	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) | ||||||
|  | 	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatalf("Failed to generate serial number: %s", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	template := x509.Certificate{ | ||||||
|  | 		SerialNumber: serialNumber, | ||||||
|  | 		Subject: pkix.Name{ | ||||||
|  | 			Organization: []string{"Acme Co"}, | ||||||
|  | 		}, | ||||||
|  | 		NotBefore: notBefore, | ||||||
|  | 		NotAfter:  notAfter, | ||||||
|  |  | ||||||
|  | 		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, | ||||||
|  | 		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, | ||||||
|  | 		BasicConstraintsValid: true, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	hosts := strings.Split(ctx.String("host"), ",") | ||||||
|  | 	for _, h := range hosts { | ||||||
|  | 		if ip := net.ParseIP(h); ip != nil { | ||||||
|  | 			template.IPAddresses = append(template.IPAddresses, ip) | ||||||
|  | 		} else { | ||||||
|  | 			template.DNSNames = append(template.DNSNames, h) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if ctx.Bool("ca") { | ||||||
|  | 		template.IsCA = true | ||||||
|  | 		template.KeyUsage |= x509.KeyUsageCertSign | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey(priv), priv) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatalf("Failed to create certificate: %s", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	certOut, err := os.Create("cert.pem") | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatalf("Failed to open cert.pem for writing: %s", err) | ||||||
|  | 	} | ||||||
|  | 	pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) | ||||||
|  | 	certOut.Close() | ||||||
|  | 	log.Println("Written cert.pem") | ||||||
|  |  | ||||||
|  | 	keyOut, err := os.OpenFile("key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatal("failed to open key.pem for writing: %v", err) | ||||||
|  | 	} | ||||||
|  | 	pem.Encode(keyOut, pemBlockForKey(priv)) | ||||||
|  | 	keyOut.Close() | ||||||
|  | 	log.Println("Written key.pem") | ||||||
|  | } | ||||||
| @@ -21,7 +21,7 @@ OFFLINE_MODE = false | |||||||
| DISABLE_ROUTER_LOG = false | DISABLE_ROUTER_LOG = false | ||||||
| ; Generate steps: | ; Generate steps: | ||||||
| ; $ cd path/to/gogs/custom/https | ; $ cd path/to/gogs/custom/https | ||||||
| ; $ go run $GOROOT/src/pkg/crypto/tls/generate_cert.go -ca=true -duration=8760h0m0s -host=myhost.example.com | ; $ ./gogs cert -ca=true -duration=8760h0m0s -host=myhost.example.com | ||||||
| CERT_FILE = custom/https/cert.pem | CERT_FILE = custom/https/cert.pem | ||||||
| KEY_FILE = custom/https/key.pem | KEY_FILE = custom/https/key.pem | ||||||
| ; Upper level of template and static file path | ; Upper level of template and static file path | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								gogs.go
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								gogs.go
									
									
									
									
									
								
							| @@ -35,6 +35,7 @@ func main() { | |||||||
| 		cmd.CmdUpdate, | 		cmd.CmdUpdate, | ||||||
| 		cmd.CmdFix, | 		cmd.CmdFix, | ||||||
| 		cmd.CmdDump, | 		cmd.CmdDump, | ||||||
|  | 		cmd.CmdCert, | ||||||
| 	} | 	} | ||||||
| 	app.Flags = append(app.Flags, []cli.Flag{}...) | 	app.Flags = append(app.Flags, []cli.Flag{}...) | ||||||
| 	app.Run(os.Args) | 	app.Run(os.Args) | ||||||
|   | |||||||
| @@ -87,6 +87,12 @@ func Fatal(skip int, format string, v ...interface{}) { | |||||||
| 	os.Exit(1) | 	os.Exit(1) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func Close() { | ||||||
|  | 	for _, l := range loggers { | ||||||
|  | 		l.Close() | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| // .___        __                 _____ | // .___        __                 _____ | ||||||
| // |   | _____/  |_  ____________/ ____\____    ____  ____ | // |   | _____/  |_  ____________/ ____\____    ____  ____ | ||||||
| // |   |/    \   __\/ __ \_  __ \   __\\__  \ _/ ___\/ __ \ | // |   |/    \   __\/ __ \_  __ \   __\\__  \ _/ ___\/ __ \ | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Unknwon
					Unknwon