From 8ed69c8eaff86d845f027f2ecc37889f1780b370 Mon Sep 17 00:00:00 2001 From: Ryan Huber Date: Tue, 19 Nov 2019 18:55:02 +0000 Subject: [PATCH 1/5] make nebula a service that can install itself --- Makefile | 38 +++++++----- cmd/nebula-service/main.go | 49 ++++++++++++++++ cmd/nebula-service/service.go | 106 ++++++++++++++++++++++++++++++++++ go.mod | 1 + go.sum | 2 + 5 files changed, 181 insertions(+), 15 deletions(-) create mode 100644 cmd/nebula-service/main.go create mode 100644 cmd/nebula-service/service.go diff --git a/Makefile b/Makefile index c4bd709..0034099 100644 --- a/Makefile +++ b/Makefile @@ -1,55 +1,56 @@ +NEBULA_CMD_PATH = "./cmd/nebula" BUILD_NUMBER ?= dev+$(shell date -u '+%Y%m%d%H%M%S') GO111MODULE = on export GO111MODULE all: - make bin-linux - make bin-arm - make bin-arm6 - make bin-arm64 - make bin-darwin - make bin-windows + make NEBULA_CMD_PATH=${NEBULA_CMD_PATH} bin-linux + make NEBULA_CMD_PATH=${NEBULA_CMD_PATH} bin-arm + make NEBULA_CMD_PATH=${NEBULA_CMD_PATH} bin-arm6 + make NEBULA_CMD_PATH=${NEBULA_CMD_PATH} bin-arm64 + make NEBULA_CMD_PATH=${NEBULA_CMD_PATH} bin-darwin + make NEBULA_CMD_PATH=${NEBULA_CMD_PATH} bin-windows bin: go build -ldflags "-X main.Build=$(BUILD_NUMBER)" -o ./nebula ./cmd/nebula go build -ldflags "-X main.Build=$(BUILD_NUMBER)" -o ./nebula-cert ./cmd/nebula-cert install: - go install -ldflags "-X main.Build=$(BUILD_NUMBER)" ./cmd/nebula + go install -ldflags "-X main.Build=$(BUILD_NUMBER)" ${NEBULA_CMD_PATH} go install -ldflags "-X main.Build=$(BUILD_NUMBER)" ./cmd/nebula-cert bin-arm: mkdir -p build/arm - GOARCH=arm GOOS=linux go build -o build/arm/nebula -ldflags "-X main.Build=$(BUILD_NUMBER)" ./cmd/nebula + GOARCH=arm GOOS=linux go build -o build/arm/nebula -ldflags "-X main.Build=$(BUILD_NUMBER)" ${NEBULA_CMD_PATH} GOARCH=arm GOOS=linux go build -o build/arm/nebula-cert -ldflags "-X main.Build=$(BUILD_NUMBER)" ./cmd/nebula-cert bin-arm6: mkdir -p build/arm6 - GOARCH=arm GOARM=6 GOOS=linux go build -o build/arm6/nebula -ldflags "-X main.Build=$(BUILD_NUMBER)" ./cmd/nebula + GOARCH=arm GOARM=6 GOOS=linux go build -o build/arm6/nebula -ldflags "-X main.Build=$(BUILD_NUMBER)" ${NEBULA_CMD_PATH} GOARCH=arm GOARM=6 GOOS=linux go build -o build/arm6/nebula-cert -ldflags "-X main.Build=$(BUILD_NUMBER)" ./cmd/nebula-cert bin-arm64: mkdir -p build/arm64 - GOARCH=arm64 GOOS=linux go build -o build/arm64/nebula -ldflags "-X main.Build=$(BUILD_NUMBER)" ./cmd/nebula + GOARCH=arm64 GOOS=linux go build -o build/arm64/nebula -ldflags "-X main.Build=$(BUILD_NUMBER)" ${NEBULA_CMD_PATH} GOARCH=arm64 GOOS=linux go build -o build/arm64/nebula-cert -ldflags "-X main.Build=$(BUILD_NUMBER)" ./cmd/nebula-cert bin-vagrant: - GOARCH=amd64 GOOS=linux go build -o nebula -ldflags "-X main.Build=$(BUILD_NUMBER)" ./cmd/nebula + GOARCH=amd64 GOOS=linux go build -o nebula -ldflags "-X main.Build=$(BUILD_NUMBER)" ${NEBULA_CMD_PATH} GOARCH=amd64 GOOS=linux go build -ldflags "-X main.Build=$(BUILD_NUMBER)" -o ./nebula-cert ./cmd/nebula-cert bin-darwin: mkdir -p build/darwin - GOARCH=amd64 GOOS=darwin go build -o build/darwin/nebula -ldflags "-X main.Build=$(BUILD_NUMBER)" ./cmd/nebula + GOARCH=amd64 GOOS=darwin go build -o build/darwin/nebula -ldflags "-X main.Build=$(BUILD_NUMBER)" ${NEBULA_CMD_PATH} GOARCH=amd64 GOOS=darwin go build -o build/darwin/nebula-cert -ldflags "-X main.Build=$(BUILD_NUMBER)" ./cmd/nebula-cert bin-windows: mkdir -p build/windows - GOARCH=amd64 GOOS=windows go build -o build/windows/nebula.exe -ldflags "-X main.Build=$(BUILD_NUMBER)" ./cmd/nebula + GOARCH=amd64 GOOS=windows go build -o build/windows/nebula.exe -ldflags "-X main.Build=$(BUILD_NUMBER)" ${NEBULA_CMD_PATH} GOARCH=amd64 GOOS=windows go build -o build/windows/nebula-cert.exe -ldflags "-X main.Build=$(BUILD_NUMBER)" ./cmd/nebula-cert bin-linux: mkdir -p build/linux - GOARCH=amd64 GOOS=linux go build -o build/linux/nebula -ldflags "-X main.Build=$(BUILD_NUMBER)" ./cmd/nebula + GOARCH=amd64 GOOS=linux go build -o build/linux/nebula -ldflags "-X main.Build=$(BUILD_NUMBER)" ${NEBULA_CMD_PATH} GOARCH=amd64 GOOS=linux go build -o build/linux/nebula-cert -ldflags "-X main.Build=$(BUILD_NUMBER)" ./cmd/nebula-cert release: all @@ -91,6 +92,13 @@ nebula.pb.go: nebula.proto .FORCE cert/cert.pb.go: cert/cert.proto .FORCE $(MAKE) -C cert cert.pb.go +service: + @echo > /dev/null + $(eval NEBULA_CMD_PATH := "./cmd/nebula-service") +ifeq ($(words $(MAKECMDGOALS)),1) + $(MAKE) service ${.DEFAULT_GOAL} --no-print-directory +endif + .FORCE: -.PHONY: test test-cov-html bench bench-cpu bench-cpu-long bin proto release +.PHONY: test test-cov-html bench bench-cpu bench-cpu-long bin proto release service .DEFAULT_GOAL := bin diff --git a/cmd/nebula-service/main.go b/cmd/nebula-service/main.go new file mode 100644 index 0000000..8b999fd --- /dev/null +++ b/cmd/nebula-service/main.go @@ -0,0 +1,49 @@ +package main + +import ( + "flag" + "fmt" + "os" + + "github.com/slackhq/nebula" +) + +// A version string that can be set with +// +// -ldflags "-X main.Build=SOMEVERSION" +// +// at compile-time. +var Build string + +func main() { + serviceFlag := flag.String("service", "", "Control the system service.") + configPath := flag.String("config", "", "Path to either a file or directory to load configuration from") + configTest := flag.Bool("test", false, "Test the config and print the end result. Non zero exit indicates a faulty config") + printVersion := flag.Bool("version", false, "Print version") + printUsage := flag.Bool("help", false, "Print command line usage") + + flag.Parse() + + if *printVersion { + fmt.Printf("Build: %s\n", Build) + os.Exit(0) + } + + if *printUsage { + flag.Usage() + os.Exit(0) + } + + if *serviceFlag != "" { + doService(configPath, configTest, Build, serviceFlag) + os.Exit(1) + } + + if *configPath == "" { + fmt.Println("-config flag must be set") + flag.Usage() + os.Exit(1) + } + + nebula.Main(*configPath, *configTest, Build) +} diff --git a/cmd/nebula-service/service.go b/cmd/nebula-service/service.go new file mode 100644 index 0000000..ed42933 --- /dev/null +++ b/cmd/nebula-service/service.go @@ -0,0 +1,106 @@ +package main + +import ( + "log" + "os" + "path/filepath" + + "github.com/kardianos/service" + "github.com/slackhq/nebula" +) + +var logger service.Logger + +type program struct { + exit chan struct{} + configPath *string + configTest *bool + build string +} + +func (p *program) Start(s service.Service) error { + if service.Interactive() { + logger.Info("Running in terminal.") + } else { + logger.Info("Running under service manager.") + } + p.exit = make(chan struct{}) + + // Start should not block. Do the actual work async. + go p.run() + return nil +} + +func (p *program) run() error { + nebula.Main(*p.configPath, *p.configTest, Build) + return nil +} + +func (p *program) Stop(s service.Service) error { + // Any work in Stop should be quick, usually a few seconds at most. + logger.Info("I'm Stopping!") + close(p.exit) + return nil +} + +func doService(configPath *string, configTest *bool, build string, serviceFlag *string) { + + if *configPath == "" { + ex, err := os.Executable() + if err != nil { + panic(err) + } + *configPath = filepath.Dir(ex) + "/config.yaml" + } + + svcConfig := &service.Config{ + Name: "Nebula", + DisplayName: "Nebula Network Service", + Description: "Nebula network connectivity daemon for encrypted communications", + Arguments: []string{"-service", "run", "-config", *configPath}, + } + + prg := &program{ + configPath: configPath, + configTest: configTest, + build: build, + } + + s, err := service.New(prg, svcConfig) + if err != nil { + log.Fatal(err) + } + + errs := make(chan error, 5) + logger, err = s.Logger(errs) + if err != nil { + log.Fatal(err) + } + + go func() { + for { + err := <-errs + if err != nil { + log.Print(err) + } + } + }() + + //if len(*serviceFlag) != 0 { + switch *serviceFlag { + case "run": + err = s.Run() + if err != nil { + logger.Error(err) + } + default: + err := service.Control(s, *serviceFlag) + if err != nil { + log.Printf("Valid actions: %q\n", service.ControlAction) + log.Fatal(err) + } + return + //} + } + +} diff --git a/go.mod b/go.mod index 5a44be8..1a07997 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6 github.com/golang/protobuf v1.3.1 github.com/imdario/mergo v0.3.7 + github.com/kardianos/service v1.0.0 github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect github.com/kr/pretty v0.1.0 // indirect github.com/miekg/dns v1.1.12 diff --git a/go.sum b/go.sum index 376506f..4186d74 100644 --- a/go.sum +++ b/go.sum @@ -30,6 +30,7 @@ github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/imdario/mergo v0.3.7 h1:Y+UAYTZ7gDEuOfhxKWy+dvb5dRQ6rJjFSdX2HZY1/gI= github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/kardianos/service v1.0.0/go.mod h1:8CzDhVuCuugtsHyZoTvsOBuvonN/UDBvl0kH+BUxvbo= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -97,6 +98,7 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= From 00d6973e2785e11d62c886e25b0be06cf0d03b0a Mon Sep 17 00:00:00 2001 From: Ryan Huber Date: Sat, 23 Nov 2019 15:32:10 +0000 Subject: [PATCH 2/5] remove some boilerplate + better messages --- cmd/nebula-service/service.go | 8 ++------ go.sum | 1 + 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/cmd/nebula-service/service.go b/cmd/nebula-service/service.go index ed42933..912202c 100644 --- a/cmd/nebula-service/service.go +++ b/cmd/nebula-service/service.go @@ -19,11 +19,7 @@ type program struct { } func (p *program) Start(s service.Service) error { - if service.Interactive() { - logger.Info("Running in terminal.") - } else { - logger.Info("Running under service manager.") - } + logger.Info("Nebula service starting.") p.exit = make(chan struct{}) // Start should not block. Do the actual work async. @@ -38,7 +34,7 @@ func (p *program) run() error { func (p *program) Stop(s service.Service) error { // Any work in Stop should be quick, usually a few seconds at most. - logger.Info("I'm Stopping!") + logger.Info("Nebula service stopping.") close(p.exit) return nil } diff --git a/go.sum b/go.sum index 4186d74..4d1f789 100644 --- a/go.sum +++ b/go.sum @@ -30,6 +30,7 @@ github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/imdario/mergo v0.3.7 h1:Y+UAYTZ7gDEuOfhxKWy+dvb5dRQ6rJjFSdX2HZY1/gI= github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/kardianos/service v1.0.0 h1:HgQS3mFfOlyntWX8Oke98JcJLqt1DBcHR4kxShpYef0= github.com/kardianos/service v1.0.0/go.mod h1:8CzDhVuCuugtsHyZoTvsOBuvonN/UDBvl0kH+BUxvbo= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= From 3fe99aa0659397e8625a8b78371ab770aa7d913c Mon Sep 17 00:00:00 2001 From: Ryan Huber Date: Sat, 23 Nov 2019 15:33:02 +0000 Subject: [PATCH 3/5] change bin target to use variable for cmd path --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 0034099..1c8e51c 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ all: make NEBULA_CMD_PATH=${NEBULA_CMD_PATH} bin-windows bin: - go build -ldflags "-X main.Build=$(BUILD_NUMBER)" -o ./nebula ./cmd/nebula + go build -ldflags "-X main.Build=$(BUILD_NUMBER)" -o ./nebula ${NEBULA_CMD_PATH} go build -ldflags "-X main.Build=$(BUILD_NUMBER)" -o ./nebula-cert ./cmd/nebula-cert install: From a5814be1ca3c3a45d53191c1468c1a4f4e54406b Mon Sep 17 00:00:00 2001 From: Slack Security Team Date: Thu, 28 Nov 2019 16:25:34 +0000 Subject: [PATCH 4/5] clean up code and print Version instead of Build --- cmd/nebula-service/main.go | 2 +- cmd/nebula-service/service.go | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/cmd/nebula-service/main.go b/cmd/nebula-service/main.go index 8b999fd..7e0634e 100644 --- a/cmd/nebula-service/main.go +++ b/cmd/nebula-service/main.go @@ -25,7 +25,7 @@ func main() { flag.Parse() if *printVersion { - fmt.Printf("Build: %s\n", Build) + fmt.Printf("Version: %s\n", Build) os.Exit(0) } diff --git a/cmd/nebula-service/service.go b/cmd/nebula-service/service.go index 912202c..5d88160 100644 --- a/cmd/nebula-service/service.go +++ b/cmd/nebula-service/service.go @@ -21,8 +21,7 @@ type program struct { func (p *program) Start(s service.Service) error { logger.Info("Nebula service starting.") p.exit = make(chan struct{}) - - // Start should not block. Do the actual work async. + // Start should not block. go p.run() return nil } @@ -33,7 +32,6 @@ func (p *program) run() error { } func (p *program) Stop(s service.Service) error { - // Any work in Stop should be quick, usually a few seconds at most. logger.Info("Nebula service stopping.") close(p.exit) return nil @@ -82,7 +80,6 @@ func doService(configPath *string, configTest *bool, build string, serviceFlag * } }() - //if len(*serviceFlag) != 0 { switch *serviceFlag { case "run": err = s.Run() @@ -96,7 +93,6 @@ func doService(configPath *string, configTest *bool, build string, serviceFlag * log.Fatal(err) } return - //} } } From 2bff0b266e4cce11b17baef9069a0cc0f31964a0 Mon Sep 17 00:00:00 2001 From: Ryan Huber Date: Mon, 2 Dec 2019 15:26:48 +0000 Subject: [PATCH 5/5] clean up makefile per wadey comment --- Makefile | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 1c8e51c..7a85625 100644 --- a/Makefile +++ b/Makefile @@ -3,13 +3,7 @@ BUILD_NUMBER ?= dev+$(shell date -u '+%Y%m%d%H%M%S') GO111MODULE = on export GO111MODULE -all: - make NEBULA_CMD_PATH=${NEBULA_CMD_PATH} bin-linux - make NEBULA_CMD_PATH=${NEBULA_CMD_PATH} bin-arm - make NEBULA_CMD_PATH=${NEBULA_CMD_PATH} bin-arm6 - make NEBULA_CMD_PATH=${NEBULA_CMD_PATH} bin-arm64 - make NEBULA_CMD_PATH=${NEBULA_CMD_PATH} bin-darwin - make NEBULA_CMD_PATH=${NEBULA_CMD_PATH} bin-windows +all: bin-linux bin-arm bin-arm6 bin-arm64 bin-darwin bin-windows bin: go build -ldflags "-X main.Build=$(BUILD_NUMBER)" -o ./nebula ${NEBULA_CMD_PATH}