diff --git a/cmd/dbg/main.go b/cmd/dbg/main.go index 401fb6b526..7b9657ab36 100644 --- a/cmd/dbg/main.go +++ b/cmd/dbg/main.go @@ -28,6 +28,7 @@ import ( const ( backendsPath = "/configuration/backends" generalPath = "/configuration/general" + certsPath = "/configuration/certs" ) func main() { @@ -70,6 +71,24 @@ func main() { } backendsCmd.AddCommand(backendsGetCmd) + certCmd := &cobra.Command{ + Use: "certs", + Short: "Inspect dynamic SSL certificates", + } + + certGetCmd := &cobra.Command{ + Use: "get [hostname]", + Short: "Get the dynamically-loaded certificate information for the given hostname", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + certGet(args[0]) + return nil + }, + } + certCmd.AddCommand(certGetCmd) + + rootCmd.AddCommand(certCmd) + generalCmd := &cobra.Command{ Use: "general", Short: "Output the general dynamic lua state", @@ -102,7 +121,7 @@ func backendsAll() { return } if statusCode != 200 { - fmt.Printf("Nginx returned code %v", statusCode) + fmt.Printf("Nginx returned code %v\n", statusCode) return } @@ -123,7 +142,7 @@ func backendsList() { return } if statusCode != 200 { - fmt.Printf("Nginx returned code %v", statusCode) + fmt.Printf("Nginx returned code %v\n", statusCode) return } @@ -148,7 +167,7 @@ func backendsGet(name string) { return } if statusCode != 200 { - fmt.Printf("Nginx returned code %v", statusCode) + fmt.Printf("Nginx returned code %v\n", statusCode) return } @@ -171,6 +190,25 @@ func backendsGet(name string) { fmt.Println("A backend of this name was not found.") } +func certGet(host string) { + statusCode, body, requestErr := nginx.NewGetStatusRequest(certsPath + "?hostname=" + host) + if requestErr != nil { + fmt.Println(requestErr) + return + } + + if statusCode == 200 { + fmt.Print(string(body)) + return + } else if statusCode != 404 { + fmt.Printf("Nginx returned code %v\n", statusCode) + fmt.Println(string(body)) + return + } + + fmt.Printf("No cert found for host %v\n", host) +} + func general() { statusCode, body, requestErr := nginx.NewGetStatusRequest(generalPath) if requestErr != nil { @@ -178,7 +216,7 @@ func general() { return } if statusCode != 200 { - fmt.Printf("Nginx returned code %v", statusCode) + fmt.Printf("Nginx returned code %v\n", statusCode) return } diff --git a/internal/nginx/main.go b/internal/nginx/main.go index 5d90e87a55..703f78dfb1 100644 --- a/internal/nginx/main.go +++ b/internal/nginx/main.go @@ -23,6 +23,7 @@ import ( "io/ioutil" "net/http" "os" + "strings" "time" "github.com/tv42/httpunix" @@ -88,15 +89,39 @@ func NewPostStatusRequest(path, contentType string, data interface{}) (int, []by return res.StatusCode, body, nil } +// GetServerBlock takes an nginx.conf file and a host and tries to find the server block for that host +func GetServerBlock(conf string, host string) (string, error) { + startMsg := fmt.Sprintf("## start server %v", host) + endMsg := fmt.Sprintf("## end server %v", host) + + blockStart := strings.Index(conf, startMsg) + if blockStart < 0 { + return "", fmt.Errorf("Host %v was not found in the controller's nginx.conf", host) + } + blockStart = blockStart + len(startMsg) + + blockEnd := strings.Index(conf, endMsg) + if blockEnd < 0 { + return "", fmt.Errorf("The end of the host server block could not be found, but the beginning was") + } + + return conf[blockStart:blockEnd], nil +} + // ReadNginxConf reads the nginx configuration file into a string func ReadNginxConf() (string, error) { - confFile, err := os.Open("/etc/nginx/nginx.conf") + return ReadFileToString("/etc/nginx/nginx.conf") +} + +// ReadFileToString reads any file into a string +func ReadFileToString(path string) (string, error) { + f, err := os.Open(path) if err != nil { return "", err } - defer confFile.Close() + defer f.Close() - contents, err := ioutil.ReadAll(confFile) + contents, err := ioutil.ReadAll(f) if err != nil { return "", err } diff --git a/rootfs/etc/nginx/lua/configuration.lua b/rootfs/etc/nginx/lua/configuration.lua index 346786476d..10f86eddc9 100644 --- a/rootfs/etc/nginx/lua/configuration.lua +++ b/rootfs/etc/nginx/lua/configuration.lua @@ -110,6 +110,32 @@ local function handle_general() ngx.status = ngx.HTTP_CREATED end +local function handle_certs() + if ngx.var.request_method ~= "GET" then + ngx.status = ngx.HTTP_BAD_REQUEST + ngx.print("Only GET requests are allowed!") + return + end + + local query = ngx.req.get_uri_args() + if not query["hostname"] then + ngx.status = ngx.HTTP_BAD_REQUEST + ngx.print("Hostname must be specified.") + return + end + + local key = _M.get_pem_cert_key(query["hostname"]) + if key then + ngx.status = ngx.HTTP_OK + ngx.print(key) + return + else + ngx.status = ngx.HTTP_NOT_FOUND + ngx.print("No key associated with this hostname.") + return + end +end + function _M.call() if ngx.var.request_method ~= "POST" and ngx.var.request_method ~= "GET" then ngx.status = ngx.HTTP_BAD_REQUEST @@ -127,6 +153,11 @@ function _M.call() return end + if ngx.var.uri == "/configuration/certs" then + handle_certs() + return + end + if ngx.var.request_uri ~= "/configuration/backends" then ngx.status = ngx.HTTP_NOT_FOUND ngx.print("Not found!")