func (h *HandlersTLS) CarveInitHandler(w http.ResponseWriter, r *http.Request) {
	h.Inc(metricInitReq)
	vars := mux.Vars(r)
	envVar, ok := vars["environment"]
	if !ok {
		h.Inc(metricInitErr)
		log.Println("Environment is missing")
		return
	}
	if !h.Envs.Exists(envVar) {
		h.Inc(metricInitErr)
		log.Printf("error unknown environment (%s)", envVar)
		return
	}
	env, err := h.Envs.Get(envVar)
	if err != nil {
		h.Inc(metricEnrollErr)
		log.Printf("error getting environment %v", err)
		return
	}
	utils.DebugHTTPDump(r, (*h.EnvsMap)[env.Name].DebugHTTP, true)
	var t types.CarveInitRequest
	if err := json.NewDecoder(r.Body).Decode(&t); err != nil {
		h.Inc(metricInitErr)
		log.Printf("error parsing POST body %v", err)
		return
	}
	initCarve := false
	var carveSessionID string
	if h.Nodes.CheckByKey(t.NodeKey) {
		if err := h.Nodes.UpdateIPAddressByKey(r.Header.Get("X-Real-IP"), t.NodeKey); err != nil {
			h.Inc(metricInitErr)
			log.Printf("error updating IP Address %v", err)
		}
		initCarve = true
		carveSessionID = generateCarveSessionID()
		if err := h.ProcessCarveInit(t, carveSessionID, env.Name); err != nil {
			h.Inc(metricInitErr)
			log.Printf("error procesing carve init %v", err)
			initCarve = false
		}
	}
	response := types.CarveInitResponse{Success: initCarve, SessionID: carveSessionID}
	if (*h.EnvsMap)[env.Name].DebugHTTP {
		log.Printf("Response: %+v", response)
	}
	utils.HTTPResponse(w, utils.JSONApplicationUTF8, http.StatusOK, response)
	h.Inc(metricInitOK)
}
CarveInitHandler - Function to handle the initialization of the file carver
This function does not use go routines to handle requests because the session_id returned
must be already created in the DB, otherwise block requests will fail.
package handlers
import (
	"compress/gzip"
	"encoding/json"
	"log"
	"net/http"
	"strings"
	"time"
	"github.com/gorilla/mux"
	"github.com/jmpsec/osctrl/carves"
	"github.com/jmpsec/osctrl/environments"
	"github.com/jmpsec/osctrl/logging"
	"github.com/jmpsec/osctrl/metrics"
	"github.com/jmpsec/osctrl/nodes"
	"github.com/jmpsec/osctrl/queries"
	"github.com/jmpsec/osctrl/settings"
	"github.com/jmpsec/osctrl/tags"
	"github.com/jmpsec/osctrl/types"
	"github.com/jmpsec/osctrl/utils"
)
const (
	metricEnrollReq   = "enroll-req"
	metricEnrollErr   = "enroll-err"
	metricEnrollOK    = "enroll-ok"
	metricLogReq      = "log-req"
	metricLogErr      = "log-err"
	metricLogOK       = "log-ok"
	metricConfigReq   = "config-req"
	metricConfigErr   = "config-err"
	metricConfigOK    = "config-ok"
	metricReadReq     = "read-req"
	metricReadErr     = "read-err"
	metricReadOK      = "read-ok"
	metricWriteReq    = "write-req"
	metricWriteErr    = "write-err"
	metricWriteOK     = "write-ok"
	metricInitReq     = "init-req"
	metricInitErr     = "init-err"
	metricInitOK      = "init-ok"
	metricBlockReq    = "block-req"
	metricBlockErr    = "block-err"
	metricBlockOK     = "block-ok"
	metricHealthReq   = "health-req"
	metricHealthOK    = "health-ok"
	metricOnelinerReq = "oneliner-req"
	metricOnelinerErr = "oneliner-err"
	metricOnelinerOk  = "oneliner-ok"
)
type HandlersTLS struct {
	Envs        *environments.Environment
	EnvsMap     *environments.MapEnvironments
	Nodes       *nodes.NodeManager
	Tags        *tags.TagManager
	Queries     *queries.Queries
	Carves      *carves.Carves
	Settings    *settings.Settings
	SettingsMap *settings.MapSettings
	Metrics     *metrics.Metrics
	Logs        *logging.LoggerTLS
}
type HandlersOption func(*HandlersTLS)
func WithEnvs(envs *environments.Environment) HandlersOption {
	return func(h *HandlersTLS) {
		h.Envs = envs
	}
}
func WithEnvsMap(envsmap *environments.MapEnvironments) HandlersOption {
	return func(h *HandlersTLS) {
		h.EnvsMap = envsmap
	}
}
func WithSettings(settings *settings.Settings) HandlersOption {
	return func(h *HandlersTLS) {
		h.Settings = settings
	}
}
func WithSettingsMap(settingsmap *settings.MapSettings) HandlersOption {
	return func(h *HandlersTLS) {
		h.SettingsMap = settingsmap
	}
}
func WithNodes(nodes *nodes.NodeManager) HandlersOption {
	return func(h *HandlersTLS) {
		h.Nodes = nodes
	}
}
func WithTags(tags *tags.TagManager) HandlersOption {
	return func(h *HandlersTLS) {
		h.Tags = tags
	}
}
func WithQueries(queries *queries.Queries) HandlersOption {
	return func(h *HandlersTLS) {
		h.Queries = queries
	}
}
func WithCarves(carves *carves.Carves) HandlersOption {
	return func(h *HandlersTLS) {
		h.Carves = carves
	}
}
func WithMetrics(metrics *metrics.Metrics) HandlersOption {
	return func(h *HandlersTLS) {
		h.Metrics = metrics
	}
}
func WithLogs(logs *logging.LoggerTLS) HandlersOption {
	return func(h *HandlersTLS) {
		h.Logs = logs
	}
}
func CreateHandlersTLS(opts ...HandlersOption) *HandlersTLS {
	h := &HandlersTLS{}
	for _, opt := range opts {
		opt(h)
	}
	return h
}
func (h *HandlersTLS) Inc(name string) {
	if h.Metrics != nil && h.Settings.ServiceMetrics(settings.ServiceTLS) {
		h.Metrics.Inc(name)
	}
}
func (h *HandlersTLS) RootHandler(w http.ResponseWriter, r *http.Request) {
	utils.HTTPResponse(w, "", http.StatusOK, []byte("💥"))
}
func (h *HandlersTLS) HealthHandler(w http.ResponseWriter, r *http.Request) {
	h.Inc(metricHealthReq)
	utils.HTTPResponse(w, "", http.StatusOK, []byte("✅"))
	h.Inc(metricHealthOK)
}
func (h *HandlersTLS) ErrorHandler(w http.ResponseWriter, r *http.Request) {
	utils.HTTPResponse(w, "", http.StatusInternalServerError, []byte("uh oh..."))
}
func (h *HandlersTLS) EnrollHandler(w http.ResponseWriter, r *http.Request) {
	h.Inc(metricEnrollReq)
	vars := mux.Vars(r)
	envVar, ok := vars["environment"]
	if !ok {
		h.Inc(metricEnrollErr)
		log.Println("Environment is missing")
		return
	}
	if !h.Envs.Exists(envVar) {
		h.Inc(metricEnrollErr)
		log.Printf("error unknown environment (%s)", envVar)
		return
	}
	env, err := h.Envs.Get(envVar)
	if err != nil {
		h.Inc(metricEnrollErr)
		log.Printf("error getting environment %v", err)
		return
	}
	utils.DebugHTTPDump(r, (*h.EnvsMap)[env.Name].DebugHTTP, true)
	var t types.EnrollRequest
	if err := json.NewDecoder(r.Body).Decode(&t); err != nil {
		h.Inc(metricEnrollErr)
		log.Printf("error parsing POST body %v", err)
		return
	}
	var nodeKey string
	var newNode nodes.OsqueryNode
	nodeInvalid := true
	if h.checkValidSecret(t.EnrollSecret, env.Name) {
		nodeKey = generateNodeKey(t.HostIdentifier, time.Now())
		newNode = nodeFromEnroll(t, env.Name, r.Header.Get("X-Real-IP"), nodeKey)
		if h.Nodes.CheckByUUIDEnv(t.HostIdentifier, env.Name) {
			if err := h.Nodes.Archive(t.HostIdentifier, "exists"); err != nil {
				h.Inc(metricEnrollErr)
				log.Printf("error archiving node %v", err)
			}
			if err := h.Nodes.UpdateByUUID(newNode, t.HostIdentifier); err != nil {
				h.Inc(metricEnrollErr)
				log.Printf("error updating existing node %v", err)
			} else {
				nodeInvalid = false
			}
		} else {  
			if err := h.Nodes.Create(&newNode); err != nil {
				h.Inc(metricEnrollErr)
				log.Printf("error creating node %v", err)
			} else {
				nodeInvalid = false
				if err := h.Tags.TagNode(env.Name, newNode); err != nil {
					h.Inc(metricEnrollErr)
					log.Printf("error tagging node %v", err)
				}
			}
		}
	} else {
		h.Inc(metricEnrollErr)
		log.Printf("error invalid enrolling secret %s", t.EnrollSecret)
	}
	response := types.EnrollResponse{NodeKey: nodeKey, NodeInvalid: nodeInvalid}
	if (*h.EnvsMap)[env.Name].DebugHTTP {
		log.Printf("Response: %+v", response)
	}
	utils.HTTPResponse(w, utils.JSONApplicationUTF8, http.StatusOK, response)
	h.Inc(metricEnrollOK)
}
func (h *HandlersTLS) ConfigHandler(w http.ResponseWriter, r *http.Request) {
	h.Inc(metricConfigReq)
	var response interface{}
	vars := mux.Vars(r)
	envVar, ok := vars["environment"]
	if !ok {
		h.Inc(metricConfigErr)
		log.Println("Environment is missing")
		return
	}
	if !h.Envs.Exists(envVar) {
		h.Inc(metricConfigErr)
		log.Printf("error unknown environment (%s)", envVar)
		return
	}
	env, err := h.Envs.Get(envVar)
	if err != nil {
		h.Inc(metricEnrollErr)
		log.Printf("error getting environment %v", err)
		return
	}
	utils.DebugHTTPDump(r, (*h.EnvsMap)[env.Name].DebugHTTP, true)
	var t types.ConfigRequest
	err = json.NewDecoder(r.Body).Decode(&t)
	if err != nil {
		h.Inc(metricConfigErr)
		log.Printf("error parsing POST body %v", err)
		return
	}
	if h.Nodes.CheckByKey(t.NodeKey) {
		err = h.Nodes.UpdateIPAddressByKey(r.Header.Get("X-Real-IP"), t.NodeKey)
		if err != nil {
			h.Inc(metricConfigErr)
			log.Printf("error updating IP address %v", err)
		}
		err = h.Nodes.RefreshLastConfig(t.NodeKey)
		if err != nil {
			h.Inc(metricConfigErr)
			log.Printf("error refreshing last config %v", err)
		}
		response = []byte(env.Configuration)
	} else {
		response = types.ConfigResponse{NodeInvalid: true}
	}
	if (*h.EnvsMap)[env.Name].DebugHTTP {
		if x, ok := response.([]byte); ok {
			log.Printf("Configuration: %s", string(x))
		} else {
			log.Printf("Configuration: %+v", response)
		}
	}
	utils.HTTPResponse(w, utils.JSONApplicationUTF8, http.StatusOK, response)
	h.Inc(metricConfigOK)
}
func (h *HandlersTLS) LogHandler(w http.ResponseWriter, r *http.Request) {
	h.Inc(metricLogReq)
	vars := mux.Vars(r)
	envVar, ok := vars["environment"]
	if !ok {
		h.Inc(metricLogErr)
		log.Println("Environment is missing")
		return
	}
	if !h.Envs.Exists(envVar) {
		h.Inc(metricLogErr)
		log.Printf("error unknown environment (%s)", envVar)
		return
	}
	env, err := h.Envs.Get(envVar)
	if err != nil {
		h.Inc(metricEnrollErr)
		log.Printf("error getting environment %v", err)
		return
	}
	if r.Header.Get("Content-Encoding") == "gzip" {
		r.Body, err = gzip.NewReader(r.Body)
		if err != nil {
			h.Inc(metricLogErr)
			log.Printf("error decoding gzip body %v", err)
		}
		defer func() {
			if err := r.Body.Close(); err != nil {
				h.Inc(metricLogErr)
				log.Printf("Failed to close body %v", err)
			}
		}()
	}
	utils.DebugHTTPDump(r, (*h.EnvsMap)[env.Name].DebugHTTP, true)
	var t types.LogRequest
	err = json.NewDecoder(r.Body).Decode(&t)
	if err != nil {
		h.Inc(metricLogErr)
		log.Printf("error parsing POST body %v", err)
		return
	}
	defer func() {
		if err := r.Body.Close(); err != nil {
			h.Inc(metricLogErr)
			log.Printf("Failed to close body %v", err)
		}
	}()
	var nodeInvalid bool
	if h.Nodes.CheckByKey(t.NodeKey) {
		nodeInvalid = false
		h.Logs.ProcessLogs(t.Data, t.LogType, env.Name, r.Header.Get("X-Real-IP"), (*h.EnvsMap)[env.Name].DebugHTTP)
	} else {
		nodeInvalid = true
	}
	response := types.LogResponse{NodeInvalid: nodeInvalid}
	if (*h.EnvsMap)[env.Name].DebugHTTP {
		log.Printf("Response: %+v", response)
	}
	utils.HTTPResponse(w, utils.JSONApplicationUTF8, http.StatusOK, response)
	h.Inc(metricLogOK)
}
func (h *HandlersTLS) QueryReadHandler(w http.ResponseWriter, r *http.Request) {
	h.Inc(metricReadReq)
	vars := mux.Vars(r)
	envVar, ok := vars["environment"]
	if !ok {
		h.Inc(metricReadErr)
		log.Println("Environment is missing")
		return
	}
	if !h.Envs.Exists(envVar) {
		h.Inc(metricReadErr)
		log.Printf("error unknown environment (%s)", envVar)
		return
	}
	env, err := h.Envs.Get(envVar)
	if err != nil {
		h.Inc(metricEnrollErr)
		log.Printf("error getting environment %v", err)
		return
	}
	utils.DebugHTTPDump(r, (*h.EnvsMap)[env.Name].DebugHTTP, true)
	var t types.QueryReadRequest
	if err := json.NewDecoder(r.Body).Decode(&t); err != nil {
		h.Inc(metricReadErr)
		log.Printf("error parsing POST body %v", err)
		return
	}
	var nodeInvalid, accelerate bool
	qs := make(queries.QueryReadQueries)
	node, err := h.Nodes.GetByKey(t.NodeKey)
	if err == nil {
		err = h.Nodes.UpdateIPAddress(r.Header.Get("X-Real-IP"), node)
		if err != nil {
			h.Inc(metricReadErr)
			log.Printf("error updating IP Address %v", err)
		}
		nodeInvalid = false
		qs, accelerate, err = h.Queries.NodeQueries(node)
		if err != nil {
			h.Inc(metricReadErr)
			log.Printf("error getting queries from db %v", err)
		}
		err = h.Nodes.RefreshLastQueryRead(t.NodeKey)
		if err != nil {
			h.Inc(metricReadErr)
			log.Printf("error refreshing last query read %v", err)
		}
	} else {
		nodeInvalid = true
		accelerate = false
	}
	var response interface{}
	if accelerate {
		sAccelerate := int((*h.SettingsMap)[settings.AcceleratedSeconds].Integer)
		response = types.AcceleratedQueryReadResponse{Queries: qs, Accelerate: sAccelerate, NodeInvalid: nodeInvalid}
	} else {
		response = types.QueryReadResponse{Queries: qs, NodeInvalid: nodeInvalid}
	}
	if (*h.EnvsMap)[env.Name].DebugHTTP {
		log.Printf("Response: %+v", response)
	}
	utils.HTTPResponse(w, utils.JSONApplicationUTF8, http.StatusOK, response)
	h.Inc(metricReadOK)
}
func (h *HandlersTLS) QueryWriteHandler(w http.ResponseWriter, r *http.Request) {
	h.Inc(metricWriteReq)
	vars := mux.Vars(r)
	envVar, ok := vars["environment"]
	if !ok {
		h.Inc(metricWriteErr)
		log.Println("Environment is missing")
		return
	}
	if !h.Envs.Exists(envVar) {
		h.Inc(metricWriteErr)
		log.Printf("error unknown environment (%s)", envVar)
		return
	}
	env, err := h.Envs.Get(envVar)
	if err != nil {
		h.Inc(metricEnrollErr)
		log.Printf("error getting environment %v", err)
		return
	}
	utils.DebugHTTPDump(r, (*h.EnvsMap)[env.Name].DebugHTTP, true)
	var t types.QueryWriteRequest
	if err := json.NewDecoder(r.Body).Decode(&t); err != nil {
		h.Inc(metricWriteErr)
		log.Printf("error parsing POST body %v", err)
		return
	}
	var nodeInvalid bool
	if h.Nodes.CheckByKey(t.NodeKey) {
		if err := h.Nodes.UpdateIPAddressByKey(r.Header.Get("X-Real-IP"), t.NodeKey); err != nil {
			h.Inc(metricWriteErr)
			log.Printf("error updating IP Address %v", err)
		}
		nodeInvalid = false
		go h.Logs.ProcessLogQueryResult(t.Queries, t.Statuses, t.NodeKey, env.Name, (*h.EnvsMap)[env.Name].DebugHTTP)
	} else {
		nodeInvalid = true
	}
	response := types.QueryWriteResponse{NodeInvalid: nodeInvalid}
	if (*h.EnvsMap)[env.Name].DebugHTTP {
		log.Printf("Response: %+v", response)
	}
	utils.HTTPResponse(w, utils.JSONApplicationUTF8, http.StatusOK, response)
	h.Inc(metricWriteOK)
}
func (h *HandlersTLS) QuickEnrollHandler(w http.ResponseWriter, r *http.Request) {
	h.Inc(metricOnelinerReq)
	vars := mux.Vars(r)
	envVar, ok := vars["environment"]
	if !ok {
		h.Inc(metricOnelinerErr)
		log.Println("Environment is missing")
		return
	}
	if !h.Envs.Exists(envVar) {
		h.Inc(metricOnelinerErr)
		log.Printf("error unknown environment (%s)", envVar)
		return
	}
	env, err := h.Envs.Get(envVar)
	if err != nil {
		h.Inc(metricEnrollErr)
		log.Printf("error getting environment %v", err)
		return
	}
	utils.DebugHTTPDump(r, (*h.EnvsMap)[env.Name].DebugHTTP, true)
	script, ok := vars["script"]
	if !ok {
		h.Inc(metricOnelinerErr)
		log.Println("Script is missing")
		return
	}
	secretPath, ok := vars["secretpath"]
	if !ok {
		h.Inc(metricOnelinerErr)
		log.Println("Path is missing")
		return
	}
	if strings.HasPrefix(script, "enroll") {
		if !h.checkValidEnrollSecretPath(env.Name, secretPath) {
			h.Inc(metricOnelinerErr)
			log.Println("Invalid secret path for enrolling")
			return
		}
	} else if strings.HasPrefix(script, "remove") {
		if !h.checkValidRemoveSecretPath(env.Name, secretPath) {
			h.Inc(metricOnelinerErr)
			log.Println("Invalid secret path for removing")
			return
		}
	}
	quickScript, err := environments.QuickAddScript("osctrl-"+env.Name, script, env)
	if err != nil {
		h.Inc(metricOnelinerErr)
		log.Printf("error getting script %v", err)
		return
	}
	utils.HTTPResponse(w, utils.TextPlainUTF8, http.StatusOK, []byte(quickScript))
	h.Inc(metricOnelinerOk)
}