From 3243432d486d119a8fbad51c2d7c4213ceb899f0 Mon Sep 17 00:00:00 2001 From: Gerasimos Maropoulos Date: Fri, 28 Oct 2016 21:21:57 +0300 Subject: [PATCH] A small improvement to LETSENCRYPT and LETSENCRYPTPROD just an improvement to the `LETSENCRYPT` in order to meet your needs, it lets you configure the cache file to any directory or to disable it by passing "" as the second argument. **OUTLINE** ``` // ListenLETSENCRYPT starts a server listening at the specific nat address // using key & certification taken from the letsencrypt.org 's servers // it's also starts a second 'http' server to redirect all 'http://$ADDR_HOSTNAME:80' to the' https://$ADDR' // it creates a cache file to store the certifications, for performance reasons, this file by-default is "./letsencrypt.cache" // if you skip the second parameter then the cache file is "./letsencrypt.cache" // if you want to disable cache then simple pass as second argument an empty emtpy string "" // // example: https://github.com/iris-contrib/examples/blob/master/letsencyrpt/main.go // // supports localhost domains for testing, // NOTE: if you are ready for production then use `$app.Serve(iris.LETSENCRYPTPROD("mydomain.com"))` instead ListenLETSENCRYPT(addr string, cacheFileOptional ...string) ``` **OVERVIEW** ``` package main import "github.com/kataras/iris" func main() { iris.Get("/", func(ctx *iris.Context) { ctx.Write("Hello from SECURE SERVER!") }) iris.ListenLETSENCRYPT("mydomain.com", "./mycachefile.cache) } ``` --- README.md | 9 ++++++-- http.go | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++----- iris.go | 28 +++++++++++++++++------ 3 files changed, 90 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index cb7e6f75..cd63e1e2 100644 --- a/README.md +++ b/README.md @@ -181,11 +181,16 @@ iris.Listen(":8080") ```go iris.ListenTLS(":8080", "./ssl/mycert.cert", "./ssl/mykey.key") ``` -`ListenLETSENCRYPT(addr string)` +`ListenLETSENCRYPT(addr string, cacheFileOptional ...string)` ```go -iris.ListenLETSENCRYPT(":8080") +iris.ListenLETSENCRYPT("mydomain.com") ``` +```go +iris.Serve(iris.LETSENCRYPTPROD("myproductionwebsite.com")) +``` + And + ```go ListenUNIX(addr string, mode os.FileMode) Close() error diff --git a/http.go b/http.go index c854c378..0d0c5943 100644 --- a/http.go +++ b/http.go @@ -3,10 +3,6 @@ package iris import ( "bytes" "crypto/tls" - "github.com/iris-contrib/letsencrypt" - "github.com/kataras/go-errors" - "github.com/valyala/fasthttp" - "github.com/valyala/fasthttp/fasthttpadaptor" "log" "net" "net/http" @@ -16,6 +12,12 @@ import ( "strings" "sync" "time" + + "github.com/iris-contrib/letsencrypt" + "github.com/kataras/go-errors" + "github.com/valyala/fasthttp" + "github.com/valyala/fasthttp/fasthttpadaptor" + "golang.org/x/crypto/acme/autocert" ) const ( @@ -1203,7 +1205,13 @@ func CERT(addr string, cert tls.Certificate) (net.Listener, error) { } // LETSENCRYPT returns a new Automatic TLS Listener using letsencrypt.org service -func LETSENCRYPT(addr string) (net.Listener, error) { +// receives two parameters, the first is the domain of the server +// and the second is optionally, the cache file, if you skip it then the cache directory is "./letsencrypt.cache" +// if you want to disable cache file then simple give it a value of emtpy string "" +// +// supports localhost domains for testing, +// but I recommend you to use the LETSENCRYPTPROD if you gonna to use it on production +func LETSENCRYPT(addr string, cacheFileOptional ...string) (net.Listener, error) { if portIdx := strings.IndexByte(addr, ':'); portIdx == -1 { addr += ":443" } @@ -1213,11 +1221,59 @@ func LETSENCRYPT(addr string) (net.Listener, error) { return nil, err } + cacheFile := "./letsencrypt.cache" + if len(cacheFileOptional) > 0 { + cacheFile = cacheFileOptional[0] + } + var m letsencrypt.Manager - if err = m.CacheFile("letsencrypt.cache"); err != nil { + + if cacheFile != "" { + if err = m.CacheFile(cacheFile); err != nil { + return nil, err + } + } + + tlsConfig := &tls.Config{GetCertificate: m.GetCertificate} + tlsLn := tls.NewListener(ln, tlsConfig) + + return tlsLn, nil +} + +// LETSENCRYPTPROD returns a new Automatic TLS Listener using letsencrypt.org service +// receives two parameters, the first is the domain of the server +// and the second is optionally, the cache directory, if you skip it then the cache directory is "./certcache" +// if you want to disable cache directory then simple give it a value of emtpy string "" +// +// does NOT supports localhost domains for testing, use LETSENCRYPT instead. +// +// this is the recommended function to use when you're ready for production state +func LETSENCRYPTPROD(addr string, cacheDirOptional ...string) (net.Listener, error) { + if portIdx := strings.IndexByte(addr, ':'); portIdx == -1 { + addr += ":443" + } + + ln, err := TCP4(addr) + if err != nil { return nil, err } + cacheDir := "./certcache" + if len(cacheDirOptional) > 0 { + cacheDir = cacheDirOptional[0] + } + + m := autocert.Manager{ + Prompt: autocert.AcceptTOS, + } // HostPolicy is missing, if user wants it, then she/he should manually + // configure the autocertmanager and use the `iris.Serve` to pass that listener + + if cacheDir == "" { + // then the user passed empty by own will, then I guess she/he doesnt' want any cache directory + } else { + m.Cache = autocert.DirCache(cacheDir) + } + tlsConfig := &tls.Config{GetCertificate: m.GetCertificate} tlsLn := tls.NewListener(ln, tlsConfig) diff --git a/iris.go b/iris.go index ae70da78..0d3e3418 100644 --- a/iris.go +++ b/iris.go @@ -11,12 +11,12 @@ // // func main() { // iris.Get("/hi_json", func(c *iris.Context) { -// c.JSON(200, iris.Map{ +// c.JSON(iris.StatusOK, iris.Map{ // "Name": "Iris", // "Released": "13 March 2016", // }) // }) -// iris.Listen(":8080") +// iris.ListenLETSENCRYPT("mydomain.com") // } // // ---------------------------------------------------------------------- @@ -149,7 +149,7 @@ type ( Serve(net.Listener) error Listen(string) ListenTLS(string, string, string) - ListenLETSENCRYPT(string) + ListenLETSENCRYPT(string, ...string) ListenUNIX(string, os.FileMode) Close() error Reserve() error @@ -551,22 +551,36 @@ func (s *Framework) ListenTLS(addr string, certFile, keyFile string) { // ListenLETSENCRYPT starts a server listening at the specific nat address // using key & certification taken from the letsencrypt.org 's servers // it's also starts a second 'http' server to redirect all 'http://$ADDR_HOSTNAME:80' to the' https://$ADDR' +// it creates a cache file to store the certifications, for performance reasons, this file by-default is "./letsencrypt.cache" +// if you skip the second parameter then the cache file is "./letsencrypt.cache" +// if you want to disable cache then simple pass as second argument an empty emtpy string "" +// // example: https://github.com/iris-contrib/examples/blob/master/letsencyrpt/main.go -func ListenLETSENCRYPT(addr string) { - Default.ListenLETSENCRYPT(addr) +// +// supports localhost domains for testing, +// NOTE: if you are ready for production then use `$app.Serve(iris.LETSENCRYPTPROD("mydomain.com"))` instead +func ListenLETSENCRYPT(addr string, cacheFileOptional ...string) { + Default.ListenLETSENCRYPT(addr, cacheFileOptional...) } // ListenLETSENCRYPT starts a server listening at the specific nat address // using key & certification taken from the letsencrypt.org 's servers // it's also starts a second 'http' server to redirect all 'http://$ADDR_HOSTNAME:80' to the' https://$ADDR' +// it creates a cache file to store the certifications, for performance reasons, this file by-default is "./letsencrypt.cache" +// if you skip the second parameter then the cache file is "./letsencrypt.cache" +// if you want to disable cache then simple pass as second argument an empty emtpy string "" +// // example: https://github.com/iris-contrib/examples/blob/master/letsencyrpt/main.go -func (s *Framework) ListenLETSENCRYPT(addr string) { +// +// supports localhost domains for testing, +// NOTE: if you are ready for production then use `$app.Serve(iris.LETSENCRYPTPROD("mydomain.com"))` instead +func (s *Framework) ListenLETSENCRYPT(addr string, cacheFileOptional ...string) { addr = ParseHost(addr) if s.Config.VHost == "" { s.Config.VHost = addr // this will be set as the front-end listening addr } - ln, err := LETSENCRYPT(addr) + ln, err := LETSENCRYPT(addr, cacheFileOptional...) if err != nil { s.Logger.Panic(err) }