From 5c73405fba9ba4b75dbd882dc2c4f8fc03643326 Mon Sep 17 00:00:00 2001 From: Nick <117028104+HilkopterBob@users.noreply.github.com> Date: Wed, 21 Aug 2024 06:29:39 +0200 Subject: [PATCH 01/14] README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0c7891c..631d9ea 100644 --- a/README.md +++ b/README.md @@ -137,7 +137,8 @@ TODO: explain usage - [ ] Check Vars and Func-Names for naming convention - [ ] persistent storage - [ ] implement interfaces for external functions for easier mocking in tests - +- [ ] systemd service start/stop/enable/disable +- [ ] copy app file (.deb/rpm/binary) via SFTP to host and start stop TODO: create Issue template: From d2e108b2b19a9bd6ffebc6d214484861d5fb6787 Mon Sep 17 00:00:00 2001 From: Nick <117028104+HilkopterBob@users.noreply.github.com> Date: Wed, 21 Aug 2024 06:32:47 +0200 Subject: [PATCH 02/14] Aktualisieren von README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 631d9ea..b6c3691 100644 --- a/README.md +++ b/README.md @@ -139,6 +139,9 @@ TODO: explain usage - [ ] implement interfaces for external functions for easier mocking in tests - [ ] systemd service start/stop/enable/disable - [ ] copy app file (.deb/rpm/binary) via SFTP to host and start stop +- [ ] binary self-Update +- [ ] agent can run docker containers +- [ ] agent fetches running docker containers, updates, restarts etc TODO: create Issue template: From f80b77a984537ed5f9ef6b8b8009ef9c81c4aa12 Mon Sep 17 00:00:00 2001 From: Nick <117028104+HilkopterBob@users.noreply.github.com> Date: Wed, 21 Aug 2024 06:34:30 +0200 Subject: [PATCH 03/14] README.md --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b6c3691..aa18d79 100644 --- a/README.md +++ b/README.md @@ -140,8 +140,9 @@ TODO: explain usage - [ ] systemd service start/stop/enable/disable - [ ] copy app file (.deb/rpm/binary) via SFTP to host and start stop - [ ] binary self-Update -- [ ] agent can run docker containers -- [ ] agent fetches running docker containers, updates, restarts etc +- [ ] agent can run docker/podman containers +- [ ] agent fetches running docker/podman containers, updates, restarts etc + TODO: create Issue template: From 805a30b440ca953be27ffa025920162ca0b90b3a Mon Sep 17 00:00:00 2001 From: Nick <117028104+HilkopterBob@users.noreply.github.com> Date: Thu, 22 Aug 2024 07:04:13 +0200 Subject: [PATCH 04/14] README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index aa18d79..10b7e6d 100644 --- a/README.md +++ b/README.md @@ -142,6 +142,8 @@ TODO: explain usage - [ ] binary self-Update - [ ] agent can run docker/podman containers - [ ] agent fetches running docker/podman containers, updates, restarts etc +- [ ] user management & SSH keys +- [ ] system definition in mpackagelock file for easy recovery & scaling From fd0a3e72b04288696ec5aa8f1085fad4daae43a0 Mon Sep 17 00:00:00 2001 From: HilkopterBob Date: Thu, 22 Aug 2024 14:30:41 +0200 Subject: [PATCH 05/14] ci: update docker for cli interface --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index adcc0af..289120e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,7 +18,7 @@ RUN go mod download # Build ARG APP_VERSION="v0.1.0+hotfixes" RUN \ - CGO_ENABLED=0 GOOS=linux go build -ldflags "-X 'main.AppVersion=$APP_VERSION'" -o /app/packagelock + CGO_ENABLED=0 GOOS=linux go build -ldflags "-X 'main.AppVersion=$APP_VERSION'" -o /packagelock # Optional: # To bind to a TCP port, runtime parameters must be supplied to the docker command. @@ -28,4 +28,4 @@ RUN \ EXPOSE 8080 # Run -CMD ["/app/packagelock"] +CMD ["packagelock start"] From 5e85b4f94e10cbe4114b622e525ea66cda6d1489 Mon Sep 17 00:00:00 2001 From: HilkopterBob Date: Thu, 22 Aug 2024 14:38:56 +0200 Subject: [PATCH 06/14] ci: add exec path --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 2774f24..3512cc4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -28,5 +28,5 @@ RUN \ EXPOSE 8080 # Run -CMD ["packagelock start"] +CMD ["/packagelock start"] From 92dfca76bd2e0b870c47f29f0c3df7cdf4fe48f1 Mon Sep 17 00:00:00 2001 From: HilkopterBob Date: Fri, 23 Aug 2024 10:37:39 +0200 Subject: [PATCH 07/14] ci: update dockerfile cmd directive --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 3512cc4..40dd72e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -28,5 +28,5 @@ RUN \ EXPOSE 8080 # Run -CMD ["/packagelock start"] +CMD ["/packagelock", "start"] From e87a6ae8600fd3a4c850bbeab2250be633bbdd1e Mon Sep 17 00:00:00 2001 From: HilkopterBob Date: Fri, 23 Aug 2024 11:03:59 +0200 Subject: [PATCH 08/14] feat: packagelock generate certs|config command This enables the user to generate ether self signed certs or a default config directly with packagelock and thus not depending on the runtime execution to handle this. --- main.go | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/main.go b/main.go index 930619a..e2d6fc8 100644 --- a/main.go +++ b/main.go @@ -38,9 +38,46 @@ var startCmd = &cobra.Command{ }, } +// Generate command +var generateCmd = &cobra.Command{ + Use: "generate [certs|config]", + Short: "Generate certs or config files", + Long: "Generate certificates or configuration files required by the application.", + Args: cobra.MatchAll(cobra.ExactArgs(1), validGenerateArgs()), // Expect exactly one argument: either "certs" or "config" + ValidArgs: []string{"certs", "config"}, // Restrict arguments to these options + Run: func(cmd *cobra.Command, args []string) { + switch args[0] { + case "certs": + err := certs.CreateSelfSignedCert( + config.Config.GetString("network.ssl-config.certificatepath"), + config.Config.GetString("network.ssl-config.privatekeypath")) + if err != nil { + fmt.Println("There was an error generating the self signed certs: %w", err) + } + case "config": + config.CreateDefaultConfig(config.Config) + default: + fmt.Println("Invalid argument. Use 'certs' or 'config'.") + } + }, +} + +func validGenerateArgs() cobra.PositionalArgs { + return func(cmd *cobra.Command, args []string) error { + validArgs := []string{"certs", "config"} + for _, valid := range validArgs { + if args[0] == valid { + return nil + } + } + return fmt.Errorf("invalid argument: '%s'. Must be one of 'certs' or 'config'", args[0]) + } +} + func init() { // Add commands to rootCmd rootCmd.AddCommand(startCmd) + rootCmd.AddCommand(generateCmd) // Initialize Viper config cobra.OnInitialize(initConfig) From a3e54998a7f0a16252f61bb796c8cbb01248d27a Mon Sep 17 00:00:00 2001 From: HilkopterBob Date: Fri, 23 Aug 2024 11:05:53 +0200 Subject: [PATCH 09/14] chore: update config generation for new flags --- config/conf-init.go | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/config/conf-init.go b/config/conf-init.go index 3db2a00..8f07d7a 100644 --- a/config/conf-init.go +++ b/config/conf-init.go @@ -55,17 +55,17 @@ func CreateDefaultConfig(config ConfigProvider) { // TODO: Add default config yamlExample := []byte(` general: - debug: True - production: False - Port: 8080 - -Network: - FQDN: "packagelock.company.com" - ForceHTTP: False - SSL: - CertificatePath: "/etc/packagelock/ssl/cert.pem" - PrivateKeyPath: "/etc/packagelock/ssl/privkey.pem" - AllowSelfSigned: False + debug: true + production: false +network: + fqdn: 0.0.0.0 + port: 8080 + ssl: true + ssl-config: + redirecthttp: true + allowselfsigned: true + certificatepath: ./certs/testing.crt + privatekeypath: ./certs/testing.key `) err := config.ReadConfig(bytes.NewBuffer(yamlExample)) From c885ef57c0862c0112eae7689a594020ad3c3afb Mon Sep 17 00:00:00 2001 From: HilkopterBob Date: Fri, 23 Aug 2024 11:08:24 +0200 Subject: [PATCH 10/14] chore: ingore config.yaml --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index e339fd7..82921df 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ certs/** !certs/*.go +config.yaml +config.yml From 54eacfd561458c65c69d69e1d2b8c7fe77de87e6 Mon Sep 17 00:00:00 2001 From: HilkopterBob Date: Fri, 23 Aug 2024 11:09:21 +0200 Subject: [PATCH 11/14] rem: conf.yaml file This is done to force me to use the build-in config generator and thus needing to update the stored template to new flags if needed. --- config.yaml | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 config.yaml diff --git a/config.yaml b/config.yaml deleted file mode 100644 index 50f78fe..0000000 --- a/config.yaml +++ /dev/null @@ -1,12 +0,0 @@ -general: - debug: true - production: false -network: - fqdn: 0.0.0.0 - port: 8080 - ssl: true - ssl-config: - redirecthttp: true - allowselfsigned: true - certificatepath: ./certs/testing.crt - privatekeypath: ./certs/testing.key From e908c0a10d341d456c12c83e53b1f00d6a012619 Mon Sep 17 00:00:00 2001 From: HilkopterBob Date: Fri, 23 Aug 2024 13:04:26 +0200 Subject: [PATCH 12/14] README --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 10b7e6d..ca76ab5 100644 --- a/README.md +++ b/README.md @@ -144,6 +144,14 @@ TODO: explain usage - [ ] agent fetches running docker/podman containers, updates, restarts etc - [ ] user management & SSH keys - [ ] system definition in mpackagelock file for easy recovery & scaling +- [ ] CLI-Commands to add: + - [ ] sync now|timestamp - force sync the server with the Agents + - [ ] logs -s (severity) info|warning|error -d (date to start) 2024-08-23-10-00-00 (date-time) + - [ ] backup - Creates a backup from server, server config, database + - [ ] generate certs letsencrypt - lets encrypt certs + - [ ] generate certs letsencrypt renew - renews + - [ ] test - runs healthchecks on server + - [ ] test agents - runs healthchecks on agents From 7a7f1621a17d7fc7871c01ab3ee535cf76d46d9a Mon Sep 17 00:00:00 2001 From: HilkopterBob Date: Fri, 23 Aug 2024 13:06:24 +0200 Subject: [PATCH 13/14] feat: stop & restart This commit adds packagelock stop|restart to packagelock start. The start command now writes a pid file for the server. The stop command uses this pid to gracefully shut the server down and the restart command combines these two to create the "illusion" of restarting --- main.go | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 2 deletions(-) diff --git a/main.go b/main.go index e2d6fc8..763783a 100644 --- a/main.go +++ b/main.go @@ -8,6 +8,7 @@ import ( "packagelock/certs" "packagelock/config" "packagelock/server" + "strconv" "syscall" "time" @@ -38,6 +39,22 @@ var startCmd = &cobra.Command{ }, } +var restartCmd = &cobra.Command{ + Use: "restart", + Short: "Restart the running server", + Run: func(cmd *cobra.Command, args []string) { + restartServer() + }, +} + +var stopCmd = &cobra.Command{ + Use: "stop", + Short: "Stop the running server", + Run: func(cmd *cobra.Command, args []string) { + stopServer() + }, +} + // Generate command var generateCmd = &cobra.Command{ Use: "generate [certs|config]", @@ -78,6 +95,8 @@ func init() { // Add commands to rootCmd rootCmd.AddCommand(startCmd) rootCmd.AddCommand(generateCmd) + rootCmd.AddCommand(restartCmd) + rootCmd.AddCommand(stopCmd) // Initialize Viper config cobra.OnInitialize(initConfig) @@ -107,6 +126,13 @@ func initConfig() { // startServer starts the Fiber server with appropriate configuration func startServer() { + pid := os.Getpid() + err := os.WriteFile("packagelock.pid", []byte(strconv.Itoa(pid)), 0644) + if err != nil { + fmt.Printf("Failed to write PID file: %v\n", err) + return + } + fmt.Println(config.Config.AllSettings()) signal.Notify(quitChan, os.Interrupt, syscall.SIGTERM) @@ -123,11 +149,12 @@ func startServer() { go func() { if config.Config.GetBool("network.ssl") { fmt.Printf("Starting Fiber HTTPS server at https://%s...\n", serverAddr) - if err := server.ListenAndServeTLS( + err := server.ListenAndServeTLS( router.Router, config.Config.GetString("network.ssl-config.certificatepath"), config.Config.GetString("network.ssl-config.privatekeypath"), - serverAddr); err != nil { + serverAddr) + if err != nil { fmt.Printf("Server error: %s\n", err) } } else { @@ -149,6 +176,7 @@ func startServer() { } else { fmt.Println("Server stopped.") } + startServer() case <-quitChan: fmt.Println("Shutting down Fiber server...") @@ -177,6 +205,44 @@ func startServer() { fmt.Println("Main process exiting.") } +func restartServer() { + stopServer() + fmt.Println("Restarting the Server...") + time.Sleep(5 * time.Second) + startServer() +} + +func stopServer() { + // Read the PID from the file using os.ReadFile + data, err := os.ReadFile("packagelock.pid") + if err != nil { + fmt.Printf("Could not read PID file: %v\n", err) + return + } + + pid, err := strconv.Atoi(string(data)) + if err != nil { + fmt.Printf("Invalid PID found in file: %v\n", err) + return + } + + // Send SIGTERM to the process + fmt.Printf("Stopping the server with PID: %d\n", pid) + err = syscall.Kill(pid, syscall.SIGTERM) + if err != nil { + fmt.Printf("Failed to stop the server: %v\n", err) + } else { + fmt.Println("Server stopped.") + // After successful stop, remove the PID file + err = os.Remove("packagelock.pid") + if err != nil { + fmt.Printf("Failed to remove PID file: %v\n", err) + } else { + fmt.Println("PID file removed successfully.") + } + } +} + func main() { // Execute the Cobra root command if err := rootCmd.Execute(); err != nil { From 58aeb24f408e72ad2fc0a67d28e09965ce75c9d0 Mon Sep 17 00:00:00 2001 From: HilkopterBob Date: Fri, 23 Aug 2024 13:07:17 +0200 Subject: [PATCH 14/14] chore: ignore packagelock.pid file --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 82921df..79ea117 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ certs/** !certs/*.go config.yaml config.yml +packagelock.pid