add crowdsec warning to installer

This commit is contained in:
miloschwartz 2025-03-19 21:16:53 -04:00
parent af68aa692c
commit 1c2ba4076a
No known key found for this signature in database

View file

@ -2,19 +2,19 @@ package main
import ( import (
"bufio" "bufio"
"bytes"
"embed" "embed"
"fmt" "fmt"
"io" "io"
"io/fs" "io/fs"
"os" "os"
"time"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"runtime" "runtime"
"strings" "strings"
"syscall" "syscall"
"bytes"
"text/template" "text/template"
"time"
"unicode" "unicode"
"golang.org/x/term" "golang.org/x/term"
@ -48,8 +48,8 @@ type Config struct {
EmailSMTPPass string EmailSMTPPass string
EmailNoReply string EmailNoReply string
InstallGerbil bool InstallGerbil bool
TraefikBouncerKey string TraefikBouncerKey string
DoCrowdsecInstall bool DoCrowdsecInstall bool
} }
func main() { func main() {
@ -84,7 +84,7 @@ func main() {
} }
fmt.Println("\n=== Starting installation ===") fmt.Println("\n=== Starting installation ===")
if isDockerInstalled() { if isDockerInstalled() {
if readBool(reader, "Would you like to install and start the containers?", true) { if readBool(reader, "Would you like to install and start the containers?", true) {
pullAndStartContainers() pullAndStartContainers()
@ -95,33 +95,35 @@ func main() {
} }
if !checkIsCrowdsecInstalledInCompose() { if !checkIsCrowdsecInstalledInCompose() {
fmt.Println("\n=== Crowdsec Install ===") fmt.Println("\n=== CrowdSec Install ===")
// check if crowdsec is installed // check if crowdsec is installed
if readBool(reader, "Would you like to install Crowdsec?", true) { if readBool(reader, "Would you like to install CrowdSec?", false) {
fmt.Println("This installer constitutes a minimal viable CrowdSec deployment. CrowdSec will add extra complexity to your Pangolin installation and may not work to the best of its abilities out of the box. Users are expected to implement configuration adjustments on their own to achieve the best security posture. Consult the CrowdSec documentation for detailed configuration instructions.")
if readBool(reader, "Are you willing to manage CrowdSec?", true) {
if config.DashboardDomain == "" {
traefikConfig, err := ReadTraefikConfig("config/traefik/traefik_config.yml", "config/traefik/dynamic_config.yml")
if err != nil {
fmt.Printf("Error reading config: %v\n", err)
return
}
config.DashboardDomain = traefikConfig.DashboardDomain
config.LetsEncryptEmail = traefikConfig.LetsEncryptEmail
config.BadgerVersion = traefikConfig.BadgerVersion
if config.DashboardDomain == "" { // print the values and check if they are right
traefikConfig, err := ReadTraefikConfig("config/traefik/traefik_config.yml", "config/traefik/dynamic_config.yml") fmt.Println("Detected values:")
if err != nil { fmt.Printf("Dashboard Domain: %s\n", config.DashboardDomain)
fmt.Printf("Error reading config: %v\n", err) fmt.Printf("Let's Encrypt Email: %s\n", config.LetsEncryptEmail)
return fmt.Printf("Badger Version: %s\n", config.BadgerVersion)
}
config.DashboardDomain = traefikConfig.DashboardDomain
config.LetsEncryptEmail = traefikConfig.LetsEncryptEmail
config.BadgerVersion = traefikConfig.BadgerVersion
// print the values and check if they are right
fmt.Println("Detected values:")
fmt.Printf("Dashboard Domain: %s\n", config.DashboardDomain)
fmt.Printf("Let's Encrypt Email: %s\n", config.LetsEncryptEmail)
fmt.Printf("Badger Version: %s\n", config.BadgerVersion)
if !readBool(reader, "Are these values correct?", true) { if !readBool(reader, "Are these values correct?", true) {
config = collectUserInput(reader) config = collectUserInput(reader)
}
} }
config.DoCrowdsecInstall = true
installCrowdsec(config)
} }
config.DoCrowdsecInstall = true
installCrowdsec(config)
} }
} }
@ -143,23 +145,23 @@ func readString(reader *bufio.Reader, prompt string, defaultValue string) string
} }
func readPassword(prompt string, reader *bufio.Reader) string { func readPassword(prompt string, reader *bufio.Reader) string {
if term.IsTerminal(int(syscall.Stdin)) { if term.IsTerminal(int(syscall.Stdin)) {
fmt.Print(prompt + ": ") fmt.Print(prompt + ": ")
// Read password without echo if we're in a terminal // Read password without echo if we're in a terminal
password, err := term.ReadPassword(int(syscall.Stdin)) password, err := term.ReadPassword(int(syscall.Stdin))
fmt.Println() // Add a newline since ReadPassword doesn't add one fmt.Println() // Add a newline since ReadPassword doesn't add one
if err != nil { if err != nil {
return "" return ""
} }
input := strings.TrimSpace(string(password)) input := strings.TrimSpace(string(password))
if input == "" { if input == "" {
return readPassword(prompt, reader) return readPassword(prompt, reader)
} }
return input return input
} else { } else {
// Fallback to reading from stdin if not in a terminal // Fallback to reading from stdin if not in a terminal
return readString(reader, prompt, "") return readString(reader, prompt, "")
} }
} }
func readBool(reader *bufio.Reader, prompt string, defaultValue bool) bool { func readBool(reader *bufio.Reader, prompt string, defaultValue bool) bool {
@ -319,15 +321,15 @@ func createConfigFiles(config Config) error {
if !config.DoCrowdsecInstall && strings.Contains(path, "crowdsec") { if !config.DoCrowdsecInstall && strings.Contains(path, "crowdsec") {
return nil return nil
} }
if config.DoCrowdsecInstall && !strings.Contains(path, "crowdsec") { if config.DoCrowdsecInstall && !strings.Contains(path, "crowdsec") {
return nil return nil
} }
// skip .DS_Store // skip .DS_Store
if strings.Contains(path, ".DS_Store") { if strings.Contains(path, ".DS_Store") {
return nil return nil
} }
if d.IsDir() { if d.IsDir() {
// Create directory // Create directory
@ -376,7 +378,6 @@ func createConfigFiles(config Config) error {
return nil return nil
} }
func installDocker() error { func installDocker() error {
// Detect Linux distribution // Detect Linux distribution
cmd := exec.Command("cat", "/etc/os-release") cmd := exec.Command("cat", "/etc/os-release")
@ -654,29 +655,29 @@ func moveFile(src, dst string) error {
} }
func waitForContainer(containerName string) error { func waitForContainer(containerName string) error {
maxAttempts := 30 maxAttempts := 30
retryInterval := time.Second * 2 retryInterval := time.Second * 2
for attempt := 0; attempt < maxAttempts; attempt++ { for attempt := 0; attempt < maxAttempts; attempt++ {
// Check if container is running // Check if container is running
cmd := exec.Command("docker", "container", "inspect", "-f", "{{.State.Running}}", containerName) cmd := exec.Command("docker", "container", "inspect", "-f", "{{.State.Running}}", containerName)
var out bytes.Buffer var out bytes.Buffer
cmd.Stdout = &out cmd.Stdout = &out
if err := cmd.Run(); err != nil {
// If the container doesn't exist or there's another error, wait and retry
time.Sleep(retryInterval)
continue
}
isRunning := strings.TrimSpace(out.String()) == "true" if err := cmd.Run(); err != nil {
if isRunning { // If the container doesn't exist or there's another error, wait and retry
return nil time.Sleep(retryInterval)
} continue
}
// Container exists but isn't running yet, wait and retry isRunning := strings.TrimSpace(out.String()) == "true"
time.Sleep(retryInterval) if isRunning {
} return nil
}
return fmt.Errorf("container %s did not start within %v seconds", containerName, maxAttempts*int(retryInterval.Seconds())) // Container exists but isn't running yet, wait and retry
} time.Sleep(retryInterval)
}
return fmt.Errorf("container %s did not start within %v seconds", containerName, maxAttempts*int(retryInterval.Seconds()))
}