Merge pull request #558 from TuncTaylan/main

Added dependency of crowdsec to traefik and relaxed its health check
This commit is contained in:
Owen Schwartz 2025-04-28 20:29:17 -04:00 committed by GitHub
commit eed6081ade
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 128 additions and 137 deletions

View file

@ -9,6 +9,9 @@ services:
PARSERS: crowdsecurity/whitelists PARSERS: crowdsecurity/whitelists
ENROLL_TAGS: docker ENROLL_TAGS: docker
healthcheck: healthcheck:
interval: 10s
retries: 15
timeout: 10s
test: ["CMD", "cscli", "capi", "status"] test: ["CMD", "cscli", "capi", "status"]
labels: labels:
- "traefik.enable=false" # Disable traefik for crowdsec - "traefik.enable=false" # Disable traefik for crowdsec

View file

@ -3,9 +3,12 @@ package main
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"log"
"os" "os"
"os/exec" "os/exec"
"strings" "strings"
"gopkg.in/yaml.v3"
) )
func installCrowdsec(config Config) error { func installCrowdsec(config Config) error {
@ -63,6 +66,12 @@ func installCrowdsec(config Config) error {
os.Exit(1) os.Exit(1)
} }
// check and add the service dependency of crowdsec to traefik
if err := CheckAndAddCrowdsecDependency("docker-compose.yml"); err != nil {
fmt.Printf("Error adding crowdsec dependency to traefik: %v\n", err)
os.Exit(1)
}
if err := startContainers(); err != nil { if err := startContainers(); err != nil {
return fmt.Errorf("failed to start containers: %v", err) return fmt.Errorf("failed to start containers: %v", err)
} }
@ -135,3 +144,58 @@ func checkIfTextInFile(file, text string) bool {
// Check for text // Check for text
return bytes.Contains(content, []byte(text)) return bytes.Contains(content, []byte(text))
} }
func CheckAndAddCrowdsecDependency(composePath string) error {
// Read the docker-compose.yml file
data, err := os.ReadFile(composePath)
if err != nil {
return fmt.Errorf("error reading compose file: %w", err)
}
// Parse YAML into a generic map
var compose map[string]interface{}
if err := yaml.Unmarshal(data, &compose); err != nil {
return fmt.Errorf("error parsing compose file: %w", err)
}
// Get services section
services, ok := compose["services"].(map[string]interface{})
if !ok {
return fmt.Errorf("services section not found or invalid")
}
// Get traefik service
traefik, ok := services["traefik"].(map[string]interface{})
if !ok {
return fmt.Errorf("traefik service not found or invalid")
}
// Get dependencies
dependsOn, ok := traefik["depends_on"].(map[string]interface{})
if ok {
// Append the new block for crowdsec
dependsOn["crowdsec"] = map[string]interface{}{
"condition": "service_healthy",
}
} else {
// No dependencies exist, create it
traefik["depends_on"] = map[string]interface{}{
"crowdsec": map[string]interface{}{
"condition": "service_healthy",
},
}
}
// Marshal the modified data back to YAML with indentation
modifiedData, err := MarshalYAMLWithIndent(compose, 2) // Set indentation to 2 spaces
if err != nil {
log.Fatalf("error marshaling YAML: %v", err)
}
if err := os.WriteFile(composePath, modifiedData, 0644); err != nil {
return fmt.Errorf("error writing updated compose file: %w", err)
}
fmt.Println("Added dependency of crowdsec to traefik")
return nil
}

View file

@ -3,7 +3,8 @@ module installer
go 1.23.0 go 1.23.0
require ( require (
golang.org/x/sys v0.29.0 // indirect golang.org/x/term v0.28.0
golang.org/x/term v0.28.0 // indirect gopkg.in/yaml.v3 v3.0.1
gopkg.in/yaml.v3 v3.0.1 // indirect
) )
require golang.org/x/sys v0.29.0 // indirect

View file

@ -2,6 +2,7 @@ golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg= golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View file

@ -87,7 +87,15 @@ func main() {
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() if err := pullContainers(); err != nil {
fmt.Println("Error: ", err)
return
}
if err := startContainers(); err != nil {
fmt.Println("Error: ", err)
return
}
} }
} }
} else { } else {
@ -427,24 +435,24 @@ func installDocker() error {
apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
`, dockerArch)) `, dockerArch))
case strings.Contains(osRelease, "ID=fedora"): case strings.Contains(osRelease, "ID=fedora"):
installCmd = exec.Command("bash", "-c", fmt.Sprintf(` installCmd = exec.Command("bash", "-c", `
dnf -y install dnf-plugins-core && dnf -y install dnf-plugins-core &&
dnf config-manager --add-repo https://download.docker.com/linux/fedora/docker-ce.repo && dnf config-manager --add-repo https://download.docker.com/linux/fedora/docker-ce.repo &&
dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
`)) `)
case strings.Contains(osRelease, "ID=opensuse") || strings.Contains(osRelease, "ID=\"opensuse-"): case strings.Contains(osRelease, "ID=opensuse") || strings.Contains(osRelease, "ID=\"opensuse-"):
installCmd = exec.Command("bash", "-c", ` installCmd = exec.Command("bash", "-c", `
zypper install -y docker docker-compose && zypper install -y docker docker-compose &&
systemctl enable docker systemctl enable docker
`) `)
case strings.Contains(osRelease, "ID=rhel") || strings.Contains(osRelease, "ID=\"rhel"): case strings.Contains(osRelease, "ID=rhel") || strings.Contains(osRelease, "ID=\"rhel"):
installCmd = exec.Command("bash", "-c", fmt.Sprintf(` installCmd = exec.Command("bash", "-c", `
dnf remove -y runc && dnf remove -y runc &&
dnf -y install yum-utils && dnf -y install yum-utils &&
dnf config-manager --add-repo https://download.docker.com/linux/rhel/docker-ce.repo && dnf config-manager --add-repo https://download.docker.com/linux/rhel/docker-ce.repo &&
dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin && dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin &&
systemctl enable docker systemctl enable docker
`)) `)
case strings.Contains(osRelease, "ID=amzn"): case strings.Contains(osRelease, "ID=amzn"):
installCmd = exec.Command("bash", "-c", ` installCmd = exec.Command("bash", "-c", `
yum update -y && yum update -y &&
@ -468,162 +476,76 @@ func isDockerInstalled() bool {
return true return true
} }
func getCommandString(useNewStyle bool) string { // executeDockerComposeCommandWithArgs executes the appropriate docker command with arguments supplied
if useNewStyle { func executeDockerComposeCommandWithArgs(args ...string) error {
return "'docker compose'" var cmd *exec.Cmd
}
return "'docker-compose'"
}
func pullAndStartContainers() error {
fmt.Println("Starting containers...")
// Check which docker compose command is available
var useNewStyle bool var useNewStyle bool
if !isDockerInstalled() {
return fmt.Errorf("docker is not installed")
}
checkCmd := exec.Command("docker", "compose", "version") checkCmd := exec.Command("docker", "compose", "version")
if err := checkCmd.Run(); err == nil { if err := checkCmd.Run(); err == nil {
useNewStyle = true useNewStyle = true
} else { } else {
// Check if docker-compose (old style) is available
checkCmd = exec.Command("docker-compose", "version") checkCmd = exec.Command("docker-compose", "version")
if err := checkCmd.Run(); err != nil { if err := checkCmd.Run(); err == nil {
return fmt.Errorf("neither 'docker compose' nor 'docker-compose' command is available: %v", err) useNewStyle = false
}
}
// Helper function to execute docker compose commands
executeCommand := func(args ...string) error {
var cmd *exec.Cmd
if useNewStyle {
cmd = exec.Command("docker", append([]string{"compose"}, args...)...)
} else { } else {
cmd = exec.Command("docker-compose", args...) return fmt.Errorf("neither 'docker compose' nor 'docker-compose' command is available")
} }
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd.Run()
} }
// Pull containers if useNewStyle {
fmt.Printf("Using %s command to pull containers...\n", getCommandString(useNewStyle)) cmd = exec.Command("docker", append([]string{"compose"}, args...)...)
if err := executeCommand("-f", "docker-compose.yml", "pull"); err != nil { } else {
return fmt.Errorf("failed to pull containers: %v", err) cmd = exec.Command("docker-compose", args...)
} }
// Start containers cmd.Stdout = os.Stdout
fmt.Printf("Using %s command to start containers...\n", getCommandString(useNewStyle)) cmd.Stderr = os.Stderr
if err := executeCommand("-f", "docker-compose.yml", "up", "-d"); err != nil { return cmd.Run()
}
// pullContainers pulls the containers using the appropriate command.
func pullContainers() error {
fmt.Println("Pulling the container images...")
if err := executeDockerComposeCommandWithArgs("-f", "docker-compose.yml", "pull", "--policy", "always"); err != nil {
return fmt.Errorf("failed to pull the containers: %v", err)
}
return nil
}
// startContainers starts the containers using the appropriate command.
func startContainers() error {
fmt.Println("Starting containers...")
if err := executeDockerComposeCommandWithArgs("-f", "docker-compose.yml", "up", "-d", "--force-recreate"); err != nil {
return fmt.Errorf("failed to start containers: %v", err) return fmt.Errorf("failed to start containers: %v", err)
} }
return nil return nil
} }
// bring containers down // stopContainers stops the containers using the appropriate command.
func stopContainers() error { func stopContainers() error {
fmt.Println("Stopping containers...") fmt.Println("Stopping containers...")
// Check which docker compose command is available if err := executeDockerComposeCommandWithArgs("-f", "docker-compose.yml", "down"); err != nil {
var useNewStyle bool
checkCmd := exec.Command("docker", "compose", "version")
if err := checkCmd.Run(); err == nil {
useNewStyle = true
} else {
// Check if docker-compose (old style) is available
checkCmd = exec.Command("docker-compose", "version")
if err := checkCmd.Run(); err != nil {
return fmt.Errorf("neither 'docker compose' nor 'docker-compose' command is available: %v", err)
}
}
// Helper function to execute docker compose commands
executeCommand := func(args ...string) error {
var cmd *exec.Cmd
if useNewStyle {
cmd = exec.Command("docker", append([]string{"compose"}, args...)...)
} else {
cmd = exec.Command("docker-compose", args...)
}
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd.Run()
}
if err := executeCommand("-f", "docker-compose.yml", "down"); err != nil {
return fmt.Errorf("failed to stop containers: %v", err) return fmt.Errorf("failed to stop containers: %v", err)
} }
return nil return nil
} }
// just start containers // restartContainer restarts a specific container using the appropriate command.
func startContainers() error {
fmt.Println("Starting containers...")
// Check which docker compose command is available
var useNewStyle bool
checkCmd := exec.Command("docker", "compose", "version")
if err := checkCmd.Run(); err == nil {
useNewStyle = true
} else {
// Check if docker-compose (old style) is available
checkCmd = exec.Command("docker-compose", "version")
if err := checkCmd.Run(); err != nil {
return fmt.Errorf("neither 'docker compose' nor 'docker-compose' command is available: %v", err)
}
}
// Helper function to execute docker compose commands
executeCommand := func(args ...string) error {
var cmd *exec.Cmd
if useNewStyle {
cmd = exec.Command("docker", append([]string{"compose"}, args...)...)
} else {
cmd = exec.Command("docker-compose", args...)
}
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd.Run()
}
if err := executeCommand("-f", "docker-compose.yml", "up", "-d"); err != nil {
return fmt.Errorf("failed to start containers: %v", err)
}
return nil
}
func restartContainer(container string) error { func restartContainer(container string) error {
fmt.Printf("Restarting %s container...\n", container) fmt.Println("Restarting containers...")
// Check which docker compose command is available if err := executeDockerComposeCommandWithArgs("-f", "docker-compose.yml", "restart", container); err != nil {
var useNewStyle bool return fmt.Errorf("failed to stop the container \"%s\": %v", container, err)
checkCmd := exec.Command("docker", "compose", "version")
if err := checkCmd.Run(); err == nil {
useNewStyle = true
} else {
// Check if docker-compose (old style) is available
checkCmd = exec.Command("docker-compose", "version")
if err := checkCmd.Run(); err != nil {
return fmt.Errorf("neither 'docker compose' nor 'docker-compose' command is available: %v", err)
}
}
// Helper function to execute docker compose commands
executeCommand := func(args ...string) error {
var cmd *exec.Cmd
if useNewStyle {
cmd = exec.Command("docker", append([]string{"compose"}, args...)...)
} else {
cmd = exec.Command("docker-compose", args...)
}
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd.Run()
}
if err := executeCommand("-f", "docker-compose.yml", "restart", container); err != nil {
return fmt.Errorf("failed to restart %s container: %v", container, err)
} }
return nil return nil