remove commands "cscli config backup/restore" (#3158)

* remove "cscli config backup/restore"
* remove backup/restore calls from deb,rpm pre/postinst and wizard
* remove from prerm too
This commit is contained in:
mmetc 2025-01-16 14:02:39 +01:00 committed by GitHub
parent 6529215775
commit b582730d06
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 31 additions and 765 deletions

View file

@ -1,234 +1,18 @@
package main
import (
"encoding/json"
"errors"
"fmt"
"os"
"path/filepath"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/crowdsecurity/crowdsec/cmd/crowdsec-cli/require"
"github.com/crowdsecurity/crowdsec/pkg/cwhub"
)
func (cli *cliConfig) backupHub(dirPath string) error {
hub, err := require.Hub(cli.cfg(), nil)
if err != nil {
return err
}
for _, itemType := range cwhub.ItemTypes {
clog := log.WithField("type", itemType)
itemMap := hub.GetItemMap(itemType)
if itemMap == nil {
clog.Infof("No %s to backup.", itemType)
continue
}
itemDirectory := fmt.Sprintf("%s/%s/", dirPath, itemType)
if err = os.MkdirAll(itemDirectory, os.ModePerm); err != nil {
return fmt.Errorf("error while creating %s: %w", itemDirectory, err)
}
upstreamParsers := []string{}
for k, v := range itemMap {
clog = clog.WithField("file", v.Name)
if !v.State.Installed { // only backup installed ones
clog.Debugf("[%s]: not installed", k)
continue
}
// for the local/tainted ones, we back up the full file
if v.State.Tainted || v.State.IsLocal() || !v.State.UpToDate {
// we need to backup stages for parsers
if itemType == cwhub.PARSERS || itemType == cwhub.POSTOVERFLOWS {
fstagedir := fmt.Sprintf("%s%s", itemDirectory, v.Stage)
if err = os.MkdirAll(fstagedir, os.ModePerm); err != nil {
return fmt.Errorf("error while creating stage dir %s: %w", fstagedir, err)
}
}
clog.Debugf("[%s]: backing up file (tainted:%t local:%t up-to-date:%t)", k, v.State.Tainted, v.State.IsLocal(), v.State.UpToDate)
tfile := fmt.Sprintf("%s%s/%s", itemDirectory, v.Stage, v.FileName)
if err = CopyFile(v.State.LocalPath, tfile); err != nil {
return fmt.Errorf("failed copy %s %s to %s: %w", itemType, v.State.LocalPath, tfile, err)
}
clog.Infof("local/tainted saved %s to %s", v.State.LocalPath, tfile)
continue
}
clog.Debugf("[%s]: from hub, just backup name (up-to-date:%t)", k, v.State.UpToDate)
clog.Infof("saving, version:%s, up-to-date:%t", v.Version, v.State.UpToDate)
upstreamParsers = append(upstreamParsers, v.Name)
}
// write the upstream items
upstreamParsersFname := fmt.Sprintf("%s/upstream-%s.json", itemDirectory, itemType)
upstreamParsersContent, err := json.MarshalIndent(upstreamParsers, "", " ")
if err != nil {
return fmt.Errorf("failed to serialize upstream parsers: %w", err)
}
err = os.WriteFile(upstreamParsersFname, upstreamParsersContent, 0o644)
if err != nil {
return fmt.Errorf("unable to write to %s %s: %w", itemType, upstreamParsersFname, err)
}
clog.Infof("Wrote %d entries for %s to %s", len(upstreamParsers), itemType, upstreamParsersFname)
}
return nil
}
/*
Backup crowdsec configurations to directory <dirPath>:
- Main config (config.yaml)
- Profiles config (profiles.yaml)
- Simulation config (simulation.yaml)
- Backup of API credentials (local API and online API)
- List of scenarios, parsers, postoverflows and collections that are up-to-date
- Tainted/local/out-of-date scenarios, parsers, postoverflows and collections
- Acquisition files (acquis.yaml, acquis.d/*.yaml)
*/
func (cli *cliConfig) backup(dirPath string) error {
var err error
cfg := cli.cfg()
if dirPath == "" {
return errors.New("directory path can't be empty")
}
log.Infof("Starting configuration backup")
/*if parent directory doesn't exist, bail out. create final dir with Mkdir*/
parentDir := filepath.Dir(dirPath)
if _, err = os.Stat(parentDir); err != nil {
return fmt.Errorf("while checking parent directory %s existence: %w", parentDir, err)
}
if err = os.Mkdir(dirPath, 0o700); err != nil {
return fmt.Errorf("while creating %s: %w", dirPath, err)
}
if cfg.ConfigPaths.SimulationFilePath != "" {
backupSimulation := filepath.Join(dirPath, "simulation.yaml")
if err = CopyFile(cfg.ConfigPaths.SimulationFilePath, backupSimulation); err != nil {
return fmt.Errorf("failed copy %s to %s: %w", cfg.ConfigPaths.SimulationFilePath, backupSimulation, err)
}
log.Infof("Saved simulation to %s", backupSimulation)
}
/*
- backup AcquisitionFilePath
- backup the other files of acquisition directory
*/
if cfg.Crowdsec != nil && cfg.Crowdsec.AcquisitionFilePath != "" {
backupAcquisition := filepath.Join(dirPath, "acquis.yaml")
if err = CopyFile(cfg.Crowdsec.AcquisitionFilePath, backupAcquisition); err != nil {
return fmt.Errorf("failed copy %s to %s: %w", cfg.Crowdsec.AcquisitionFilePath, backupAcquisition, err)
}
}
acquisBackupDir := filepath.Join(dirPath, "acquis")
if err = os.Mkdir(acquisBackupDir, 0o700); err != nil {
return fmt.Errorf("error while creating %s: %w", acquisBackupDir, err)
}
if cfg.Crowdsec != nil && len(cfg.Crowdsec.AcquisitionFiles) > 0 {
for _, acquisFile := range cfg.Crowdsec.AcquisitionFiles {
/*if it was the default one, it was already backup'ed*/
if cfg.Crowdsec.AcquisitionFilePath == acquisFile {
continue
}
targetFname, err := filepath.Abs(filepath.Join(acquisBackupDir, filepath.Base(acquisFile)))
if err != nil {
return fmt.Errorf("while saving %s to %s: %w", acquisFile, acquisBackupDir, err)
}
if err = CopyFile(acquisFile, targetFname); err != nil {
return fmt.Errorf("failed copy %s to %s: %w", acquisFile, targetFname, err)
}
log.Infof("Saved acquis %s to %s", acquisFile, targetFname)
}
}
if ConfigFilePath != "" {
backupMain := fmt.Sprintf("%s/config.yaml", dirPath)
if err = CopyFile(ConfigFilePath, backupMain); err != nil {
return fmt.Errorf("failed copy %s to %s: %w", ConfigFilePath, backupMain, err)
}
log.Infof("Saved default yaml to %s", backupMain)
}
if cfg.API != nil && cfg.API.Server != nil && cfg.API.Server.OnlineClient != nil && cfg.API.Server.OnlineClient.CredentialsFilePath != "" {
backupCAPICreds := fmt.Sprintf("%s/online_api_credentials.yaml", dirPath)
if err = CopyFile(cfg.API.Server.OnlineClient.CredentialsFilePath, backupCAPICreds); err != nil {
return fmt.Errorf("failed copy %s to %s: %w", cfg.API.Server.OnlineClient.CredentialsFilePath, backupCAPICreds, err)
}
log.Infof("Saved online API credentials to %s", backupCAPICreds)
}
if cfg.API != nil && cfg.API.Client != nil && cfg.API.Client.CredentialsFilePath != "" {
backupLAPICreds := fmt.Sprintf("%s/local_api_credentials.yaml", dirPath)
if err = CopyFile(cfg.API.Client.CredentialsFilePath, backupLAPICreds); err != nil {
return fmt.Errorf("failed copy %s to %s: %w", cfg.API.Client.CredentialsFilePath, backupLAPICreds, err)
}
log.Infof("Saved local API credentials to %s", backupLAPICreds)
}
if cfg.API != nil && cfg.API.Server != nil && cfg.API.Server.ProfilesPath != "" {
backupProfiles := fmt.Sprintf("%s/profiles.yaml", dirPath)
if err = CopyFile(cfg.API.Server.ProfilesPath, backupProfiles); err != nil {
return fmt.Errorf("failed copy %s to %s: %w", cfg.API.Server.ProfilesPath, backupProfiles, err)
}
log.Infof("Saved profiles to %s", backupProfiles)
}
if err = cli.backupHub(dirPath); err != nil {
return fmt.Errorf("failed to backup hub config: %w", err)
}
return nil
}
func (cli *cliConfig) newBackupCmd() *cobra.Command {
cmd := &cobra.Command{
Use: `backup "directory"`,
Short: "Backup current config",
Long: `Backup the current crowdsec configuration including :
- Main config (config.yaml)
- Simulation config (simulation.yaml)
- Profiles config (profiles.yaml)
- List of scenarios, parsers, postoverflows and collections that are up-to-date
- Tainted/local/out-of-date scenarios, parsers, postoverflows and collections
- Backup of API credentials (local API and online API)`,
Example: `cscli config backup ./my-backup`,
Args: cobra.ExactArgs(1),
Use: "backup",
DisableAutoGenTag: true,
RunE: func(_ *cobra.Command, args []string) error {
if err := cli.backup(args[0]); err != nil {
return fmt.Errorf("failed to backup config: %w", err)
}
return nil
RunE: func(_ *cobra.Command, _ []string) error {
configDir := cli.cfg().ConfigPaths.ConfigDir
return fmt.Errorf("'cscli config backup' has been removed, you can manually backup/restore %s instead", configDir)
},
}

View file

@ -1,285 +1,18 @@
package main
import (
"context"
"encoding/json"
"fmt"
"os"
"path/filepath"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/crowdsecurity/crowdsec/cmd/crowdsec-cli/require"
"github.com/crowdsecurity/crowdsec/pkg/cwhub"
"github.com/crowdsecurity/crowdsec/pkg/hubops"
)
func (cli *cliConfig) restoreHub(ctx context.Context, dirPath string) error {
cfg := cli.cfg()
hub, err := require.Hub(cfg, nil)
if err != nil {
return err
}
contentProvider := require.HubDownloader(ctx, cfg)
for _, itype := range cwhub.ItemTypes {
itemDirectory := fmt.Sprintf("%s/%s/", dirPath, itype)
if _, err = os.Stat(itemDirectory); err != nil {
log.Infof("no %s in backup", itype)
continue
}
/*restore the upstream items*/
upstreamListFN := fmt.Sprintf("%s/upstream-%s.json", itemDirectory, itype)
file, err := os.ReadFile(upstreamListFN)
if err != nil {
return fmt.Errorf("error while opening %s: %w", upstreamListFN, err)
}
var upstreamList []string
err = json.Unmarshal(file, &upstreamList)
if err != nil {
return fmt.Errorf("error parsing %s: %w", upstreamListFN, err)
}
for _, toinstall := range upstreamList {
item := hub.GetItem(itype, toinstall)
if item == nil {
log.Errorf("Item %s/%s not found in hub", itype, toinstall)
continue
}
plan := hubops.NewActionPlan(hub)
if err = plan.AddCommand(hubops.NewDownloadCommand(item, contentProvider, false)); err != nil {
return err
}
if err = plan.AddCommand(hubops.NewEnableCommand(item, false)); err != nil {
return err
}
if err = plan.Execute(ctx, true, false, false); err != nil {
log.Errorf("Error while installing %s : %s", toinstall, err)
}
}
/*restore the local and tainted items*/
files, err := os.ReadDir(itemDirectory)
if err != nil {
return fmt.Errorf("failed enumerating files of %s: %w", itemDirectory, err)
}
for _, file := range files {
// this was the upstream data
if file.Name() == fmt.Sprintf("upstream-%s.json", itype) {
continue
}
if itype == cwhub.PARSERS || itype == cwhub.POSTOVERFLOWS {
// we expect a stage here
if !file.IsDir() {
continue
}
stage := file.Name()
stagedir := fmt.Sprintf("%s/%s/%s/", cfg.ConfigPaths.ConfigDir, itype, stage)
log.Debugf("Found stage %s in %s, target directory : %s", stage, itype, stagedir)
if err = os.MkdirAll(stagedir, os.ModePerm); err != nil {
return fmt.Errorf("error while creating stage directory %s: %w", stagedir, err)
}
// find items
ifiles, err := os.ReadDir(itemDirectory + "/" + stage + "/")
if err != nil {
return fmt.Errorf("failed enumerating files of %s: %w", itemDirectory+"/"+stage, err)
}
// finally copy item
for _, tfile := range ifiles {
log.Infof("Going to restore local/tainted [%s]", tfile.Name())
sourceFile := fmt.Sprintf("%s/%s/%s", itemDirectory, stage, tfile.Name())
destinationFile := fmt.Sprintf("%s%s", stagedir, tfile.Name())
if err = CopyFile(sourceFile, destinationFile); err != nil {
return fmt.Errorf("failed copy %s %s to %s: %w", itype, sourceFile, destinationFile, err)
}
log.Infof("restored %s to %s", sourceFile, destinationFile)
}
} else {
log.Infof("Going to restore local/tainted [%s]", file.Name())
sourceFile := fmt.Sprintf("%s/%s", itemDirectory, file.Name())
destinationFile := fmt.Sprintf("%s/%s/%s", cfg.ConfigPaths.ConfigDir, itype, file.Name())
if err = CopyFile(sourceFile, destinationFile); err != nil {
return fmt.Errorf("failed copy %s %s to %s: %w", itype, sourceFile, destinationFile, err)
}
log.Infof("restored %s to %s", sourceFile, destinationFile)
}
}
}
return nil
}
/*
Restore crowdsec configurations to directory <dirPath>:
- Main config (config.yaml)
- Profiles config (profiles.yaml)
- Simulation config (simulation.yaml)
- Backup of API credentials (local API and online API)
- List of scenarios, parsers, postoverflows and collections that are up-to-date
- Tainted/local/out-of-date scenarios, parsers, postoverflows and collections
- Acquisition files (acquis.yaml, acquis.d/*.yaml)
*/
func (cli *cliConfig) restore(ctx context.Context, dirPath string) error {
var err error
cfg := cli.cfg()
backupMain := fmt.Sprintf("%s/config.yaml", dirPath)
if _, err = os.Stat(backupMain); err == nil {
if cfg.ConfigPaths != nil && cfg.ConfigPaths.ConfigDir != "" {
if err = CopyFile(backupMain, fmt.Sprintf("%s/config.yaml", cfg.ConfigPaths.ConfigDir)); err != nil {
return fmt.Errorf("failed copy %s to %s: %w", backupMain, cfg.ConfigPaths.ConfigDir, err)
}
}
}
// Now we have config.yaml, we should regenerate config struct to have rights paths etc
ConfigFilePath = fmt.Sprintf("%s/config.yaml", cfg.ConfigPaths.ConfigDir)
log.Debug("Reloading configuration")
csConfig, _, err = loadConfigFor("config")
if err != nil {
return fmt.Errorf("failed to reload configuration: %w", err)
}
cfg = cli.cfg()
backupCAPICreds := fmt.Sprintf("%s/online_api_credentials.yaml", dirPath)
if _, err = os.Stat(backupCAPICreds); err == nil {
if err = CopyFile(backupCAPICreds, cfg.API.Server.OnlineClient.CredentialsFilePath); err != nil {
return fmt.Errorf("failed copy %s to %s: %w", backupCAPICreds, cfg.API.Server.OnlineClient.CredentialsFilePath, err)
}
}
backupLAPICreds := fmt.Sprintf("%s/local_api_credentials.yaml", dirPath)
if _, err = os.Stat(backupLAPICreds); err == nil {
if err = CopyFile(backupLAPICreds, cfg.API.Client.CredentialsFilePath); err != nil {
return fmt.Errorf("failed copy %s to %s: %w", backupLAPICreds, cfg.API.Client.CredentialsFilePath, err)
}
}
backupProfiles := fmt.Sprintf("%s/profiles.yaml", dirPath)
if _, err = os.Stat(backupProfiles); err == nil {
if err = CopyFile(backupProfiles, cfg.API.Server.ProfilesPath); err != nil {
return fmt.Errorf("failed copy %s to %s: %w", backupProfiles, cfg.API.Server.ProfilesPath, err)
}
}
backupSimulation := fmt.Sprintf("%s/simulation.yaml", dirPath)
if _, err = os.Stat(backupSimulation); err == nil {
if err = CopyFile(backupSimulation, cfg.ConfigPaths.SimulationFilePath); err != nil {
return fmt.Errorf("failed copy %s to %s: %w", backupSimulation, cfg.ConfigPaths.SimulationFilePath, err)
}
}
/*if there is a acquisition dir, restore its content*/
if cfg.Crowdsec.AcquisitionDirPath != "" {
if err = os.MkdirAll(cfg.Crowdsec.AcquisitionDirPath, 0o700); err != nil {
return fmt.Errorf("error while creating %s: %w", cfg.Crowdsec.AcquisitionDirPath, err)
}
}
// if there was a single one
backupAcquisition := fmt.Sprintf("%s/acquis.yaml", dirPath)
if _, err = os.Stat(backupAcquisition); err == nil {
log.Debugf("restoring backup'ed %s", backupAcquisition)
if err = CopyFile(backupAcquisition, cfg.Crowdsec.AcquisitionFilePath); err != nil {
return fmt.Errorf("failed copy %s to %s: %w", backupAcquisition, cfg.Crowdsec.AcquisitionFilePath, err)
}
}
// if there are files in the acquis backup dir, restore them
acquisBackupDir := filepath.Join(dirPath, "acquis", "*.yaml")
if acquisFiles, err := filepath.Glob(acquisBackupDir); err == nil {
for _, acquisFile := range acquisFiles {
targetFname, err := filepath.Abs(cfg.Crowdsec.AcquisitionDirPath + "/" + filepath.Base(acquisFile))
if err != nil {
return fmt.Errorf("while saving %s to %s: %w", acquisFile, targetFname, err)
}
log.Debugf("restoring %s to %s", acquisFile, targetFname)
if err = CopyFile(acquisFile, targetFname); err != nil {
return fmt.Errorf("failed copy %s to %s: %w", acquisFile, targetFname, err)
}
}
}
if cfg.Crowdsec != nil && len(cfg.Crowdsec.AcquisitionFiles) > 0 {
for _, acquisFile := range cfg.Crowdsec.AcquisitionFiles {
log.Infof("backup filepath from dir -> %s", acquisFile)
// if it was the default one, it has already been backed up
if cfg.Crowdsec.AcquisitionFilePath == acquisFile {
log.Infof("skip this one")
continue
}
targetFname, err := filepath.Abs(filepath.Join(acquisBackupDir, filepath.Base(acquisFile)))
if err != nil {
return fmt.Errorf("while saving %s to %s: %w", acquisFile, acquisBackupDir, err)
}
if err = CopyFile(acquisFile, targetFname); err != nil {
return fmt.Errorf("failed copy %s to %s: %w", acquisFile, targetFname, err)
}
log.Infof("Saved acquis %s to %s", acquisFile, targetFname)
}
}
if err = cli.restoreHub(ctx, dirPath); err != nil {
return fmt.Errorf("failed to restore hub config: %w", err)
}
return nil
}
func (cli *cliConfig) newRestoreCmd() *cobra.Command {
cmd := &cobra.Command{
Use: `restore "directory"`,
Short: `Restore config in backup "directory"`,
Long: `Restore the crowdsec configuration from specified backup "directory" including:
- Main config (config.yaml)
- Simulation config (simulation.yaml)
- Profiles config (profiles.yaml)
- List of scenarios, parsers, postoverflows and collections that are up-to-date
- Tainted/local/out-of-date scenarios, parsers, postoverflows and collections
- Backup of API credentials (local API and online API)`,
Args: cobra.ExactArgs(1),
Use: "restore",
DisableAutoGenTag: true,
RunE: func(cmd *cobra.Command, args []string) error {
dirPath := args[0]
if err := cli.restore(cmd.Context(), dirPath); err != nil {
return fmt.Errorf("failed to restore config from %s: %w", dirPath, err)
}
return nil
RunE: func(cmd *cobra.Command, _ []string) error {
configDir := cli.cfg().ConfigPaths.ConfigDir
return fmt.Errorf("'cscli config restore' has been removed, you can manually backup/restore %s instead", configDir)
},
}

View file

@ -1,82 +0,0 @@
package main
import (
"fmt"
"io"
"os"
"path/filepath"
log "github.com/sirupsen/logrus"
)
/*help to copy the file, ioutil doesn't offer the feature*/
func copyFileContents(src, dst string) (err error) {
in, err := os.Open(src)
if err != nil {
return
}
defer in.Close()
out, err := os.Create(dst)
if err != nil {
return
}
defer func() {
cerr := out.Close()
if err == nil {
err = cerr
}
}()
if _, err = io.Copy(out, in); err != nil {
return
}
err = out.Sync()
return
}
/*copy the file, ioutile doesn't offer the feature*/
func CopyFile(sourceSymLink, destinationFile string) error {
sourceFile, err := filepath.EvalSymlinks(sourceSymLink)
if err != nil {
log.Infof("Not a symlink : %s", err)
sourceFile = sourceSymLink
}
sourceFileStat, err := os.Stat(sourceFile)
if err != nil {
return err
}
if !sourceFileStat.Mode().IsRegular() {
// cannot copy non-regular files (e.g., directories,
// symlinks, devices, etc.)
return fmt.Errorf("copyFile: non-regular source file %s (%q)", sourceFileStat.Name(), sourceFileStat.Mode().String())
}
destinationFileStat, err := os.Stat(destinationFile)
if err != nil {
if !os.IsNotExist(err) {
return err
}
} else {
if !(destinationFileStat.Mode().IsRegular()) {
return fmt.Errorf("copyFile: non-regular destination file %s (%q)", destinationFileStat.Name(), destinationFileStat.Mode().String())
}
if os.SameFile(sourceFileStat, destinationFileStat) {
return err
}
}
if err = os.Link(sourceFile, destinationFile); err != nil {
err = copyFileContents(sourceFile, destinationFile)
}
return err
}

16
debian/postinst vendored
View file

@ -11,14 +11,6 @@ if [ "$1" = configure ]; then
mkdir -p /var/lib/crowdsec/data
fi
if [[ -d /var/lib/crowdsec/backup ]]; then
cscli config restore /var/lib/crowdsec/backup/backup.config
rm -rf /var/lib/crowdsec/backup
/usr/bin/cscli hub update
/usr/bin/cscli hub upgrade
systemctl start crowdsec
fi
. /usr/share/crowdsec/wizard.sh -n
if ! [[ -f /etc/crowdsec/acquis.yaml ]]; then
echo Creating /etc/crowdsec/acquis.yaml
@ -82,12 +74,6 @@ if [ "$1" = configure ]; then
set -e
fi
if [[ -f /var/lib/crowdsec/data/crowdsec.db.backup ]]; then
cp /var/lib/crowdsec/data/crowdsec.db.backup /var/lib/crowdsec/data/crowdsec.db
rm -f /var/lib/crowdsec/data/crowdsec.db.backup
fi
systemctl --quiet is-enabled crowdsec || systemctl unmask crowdsec && systemctl enable crowdsec
API=$(cscli config show --key "Config.API.Server")
@ -107,8 +93,6 @@ if [ "$1" = configure ]; then
echo " * Detailed guides are available in our documentation: https://docs.crowdsec.net"
echo " * Configuration items created by the community can be found at the Hub: https://hub.crowdsec.net"
echo " * Gain insights into your use of CrowdSec with the help of the console https://app.crowdsec.net"
fi
echo "You can always run the configuration again interactively by using '/usr/share/crowdsec/wizard.sh -c'"

35
debian/preinst vendored
View file

@ -5,39 +5,4 @@ set -e
# Source debconf library.
. /usr/share/debconf/confmodule
OLD_MAJOR_VERSION=$(echo $2 | cut -d'.' -f1)
OLD_MINOR_VERSION=$(echo $2 | cut -d'.' -f2)
OLD_PATCH_VERSION=$(echo $2 | cut -d'.' -f3|cut -d'-' -f1)
NEW_MAJOR_VERSION=$(echo $3 | cut -d'.' -f1)
NEW_MINOR_VERSION=$(echo $3 | cut -d'.' -f2)
NEW_PATCH_VERSION=$(echo $3 | cut -d'.' -f3|cut -d'-' -f1)
if [ "$1" = upgrade ]; then
OLD_MAJOR_VERSION=$(echo $2 | cut -d'.' -f1)
OLD_MINOR_VERSION=$(echo $2 | cut -d'.' -f2)
OLD_PATCH_VERSION=$(echo $2 | cut -d'.' -f3|cut -d'-' -f1)
NEW_MAJOR_VERSION=$(echo $3 | cut -d'.' -f1)
NEW_MINOR_VERSION=$(echo $3 | cut -d'.' -f2)
NEW_PATCH_VERSION=$(echo $3 | cut -d'.' -f3|cut -d'-' -f1)
if [[ $OLD_MAJOR_VERSION -eq "1" ]] && [[ $OLD_MINOR_VERSION -eq "0" ]] && [[ $OLD_PATCH_VERSION -lt "9" ]]; then
if [[ -f /var/lib/crowdsec/data/crowdsec.db ]]; then
cp /var/lib/crowdsec/data/crowdsec.db /var/lib/crowdsec/data/crowdsec.db.backup
fi
fi
if [[ $NEW_MAJOR_VERSION -gt $OLD_MAJOR_VERSION ]]; then
echo "Stopping crowdsec"
systemctl stop crowdsec || true
cscli config backup /var/lib/crowdsec/backup
fi
fi
echo "You can always run the configuration again interactively by using '/usr/share/crowdsec/wizard.sh -c'"

3
debian/prerm vendored
View file

@ -1,9 +1,8 @@
if [ "$1" = "remove" ]; then
cscli dashboard remove -f -y --error || echo "Ignore the above error if you never installed the local dashboard."
systemctl stop crowdsec
systemctl disable crowdsec
fi
if [ "$1" = "upgrade" ]; then
systemctl stop crowdsec
fi
fi

View file

@ -143,18 +143,15 @@ rm -rf %{buildroot}
#systemctl stop crowdsec || true
if [ $1 == 2 ];then
if [[ ! -d /var/lib/crowdsec/backup ]]; then
cscli config backup /var/lib/crowdsec/backup
fi
fi
#if [ $1 == 2 ]; then
# upgrade pre-install here
#fi
%post -p /bin/bash
#install
if [ $1 == 1 ]; then
if [ ! -f "/var/lib/crowdsec/data/crowdsec.db" ] ; then
touch /var/lib/crowdsec/data/crowdsec.db
fi
@ -185,21 +182,6 @@ if [ $1 == 1 ]; then
echo " * Detailed guides are available in our documentation: https://docs.crowdsec.net"
echo " * Configuration items created by the community can be found at the Hub: https://hub.crowdsec.net"
echo " * Gain insights into your use of CrowdSec with the help of the console https://app.crowdsec.net"
#upgrade
elif [ $1 == 2 ] && [ -d /var/lib/crowdsec/backup ]; then
cscli config restore /var/lib/crowdsec/backup
if [ $? == 0 ]; then
rm -rf /var/lib/crowdsec/backup
fi
if [[ -f %{_sysconfdir}/crowdsec/online_api_credentials.yaml ]] ; then
chmod 600 %{_sysconfdir}/crowdsec/online_api_credentials.yaml
fi
if [[ -f %{_sysconfdir}/crowdsec/local_api_credentials.yaml ]] ; then
chmod 600 %{_sysconfdir}/crowdsec/local_api_credentials.yaml
fi
fi
%systemd_post %{name}.service

View file

@ -172,41 +172,13 @@ teardown() {
}
@test "cscli config backup / restore" {
# test that we need a valid path
# disabled because in CI, the empty string is not passed as a parameter
#rune -1 cscli config backup ""
#assert_stderr --partial "failed to backup config: directory path can't be empty"
CONFIG_DIR=$(config_get '.config_paths.config_dir')
rune -1 cscli config backup "/dev/null/blah"
assert_stderr --partial "failed to backup config: while creating /dev/null/blah: mkdir /dev/null/blah: not a directory"
assert_stderr --partial "'cscli config backup' has been removed, you can manually backup/restore $CONFIG_DIR instead"
# pick a dirpath
backupdir=$(TMPDIR="$BATS_TEST_TMPDIR" mktemp -u)
# succeed the first time
rune -0 cscli config backup "$backupdir"
assert_stderr --partial "Starting configuration backup"
# don't overwrite an existing backup
rune -1 cscli config backup "$backupdir"
assert_stderr --partial "failed to backup config"
assert_stderr --partial "file exists"
SIMULATION_YAML="$(config_get '.config_paths.simulation_path')"
# restore
rm "$SIMULATION_YAML"
rune -0 cscli config restore "$backupdir"
assert_file_exists "$SIMULATION_YAML"
# cleanup
rm -rf -- "${backupdir:?}"
# backup: detect missing files
rm "$SIMULATION_YAML"
rune -1 cscli config backup "$backupdir"
assert_stderr --regexp "failed to backup config: failed copy .* to .*: stat .*: no such file or directory"
rm -rf -- "${backupdir:?}"
rune -1 cscli config restore "/dev/null/blah"
assert_stderr --partial "'cscli config restore' has been removed, you can manually backup/restore $CONFIG_DIR instead"
}
@test "'cscli completion' with or without configuration file" {

View file

@ -66,18 +66,6 @@ teardown() {
refute_output --partial "Local API Server"
}
@test "cscli config backup" {
config_disable_lapi
backupdir=$(TMPDIR="$BATS_TEST_TMPDIR" mktemp -u)
rune -0 cscli config backup "$backupdir"
assert_stderr --partial "Starting configuration backup"
rune -1 cscli config backup "$backupdir"
rm -rf -- "${backupdir:?}"
assert_stderr --partial "failed to backup config"
assert_stderr --partial "file exists"
}
@test "lapi status shouldn't be ok without api.server" {
config_disable_lapi
rune -1 cscli machines list

View file

@ -60,18 +60,6 @@ teardown() {
refute_output --partial "Crowdsec"
}
@test "no agent: cscli config backup" {
config_disable_agent
backupdir=$(TMPDIR="$BATS_TEST_TMPDIR" mktemp -u)
rune -0 cscli config backup "$backupdir"
assert_stderr --partial "Starting configuration backup"
rune -1 cscli config backup "$backupdir"
assert_stderr --partial "failed to backup config"
assert_stderr --partial "file exists"
rm -rf -- "${backupdir:?}"
}
@test "no agent: lapi status should be ok" {
config_disable_agent
./instance-crowdsec start

View file

@ -51,17 +51,6 @@ teardown() {
assert_output --regexp "Global:.*Crowdsec.*cscli:.*Local API Server:"
}
@test "no agent: cscli config backup" {
config_disable_capi
backupdir=$(TMPDIR="$BATS_TEST_TMPDIR" mktemp -u)
rune -0 cscli config backup "$backupdir"
assert_stderr --partial "Starting configuration backup"
rune -1 cscli config backup "$backupdir"
assert_stderr --partial "failed to backup config"
assert_stderr --partial "file exists"
rm -rf -- "${backupdir:?}"
}
@test "without capi: cscli lapi status -> success" {
config_disable_capi
./instance-crowdsec start

View file

@ -21,11 +21,8 @@ DOCKER_MODE="false"
CROWDSEC_LIB_DIR="/var/lib/crowdsec"
CROWDSEC_USR_DIR="/usr/local/lib/crowdsec"
CROWDSEC_DATA_DIR="${CROWDSEC_LIB_DIR}/data"
CROWDSEC_DB_PATH="${CROWDSEC_DATA_DIR}/crowdsec.db"
CROWDSEC_PATH="/etc/crowdsec"
CROWDSEC_CONFIG_PATH="${CROWDSEC_PATH}"
CROWDSEC_LOG_FILE="/var/log/crowdsec.log"
LAPI_LOG_FILE="/var/log/crowdsec_api.log"
CROWDSEC_PLUGIN_DIR="${CROWDSEC_USR_DIR}/plugins"
CROWDSEC_CONSOLE_DIR="${CROWDSEC_PATH}/console"
@ -35,8 +32,6 @@ CSCLI_BIN="./cmd/crowdsec-cli/cscli"
CLIENT_SECRETS="local_api_credentials.yaml"
LAPI_SECRETS="online_api_credentials.yaml"
CONSOLE_FILE="console.yaml"
BIN_INSTALL_PATH="/usr/local/bin"
CROWDSEC_BIN_INSTALLED="${BIN_INSTALL_PATH}/crowdsec"
@ -91,9 +86,6 @@ SENTINEL_PLUGIN_CONFIG="./cmd/notification-sentinel/sentinel.yaml"
FILE_PLUGIN_CONFIG="./cmd/notification-file/file.yaml"
BACKUP_DIR=$(mktemp -d)
rm -rf -- "$BACKUP_DIR"
log_info() {
msg=$1
date=$(date "+%Y-%m-%d %H:%M:%S")
@ -426,27 +418,20 @@ install_crowdsec() {
mkdir -p "${CROWDSEC_CONFIG_PATH}/contexts" || exit
mkdir -p "${CROWDSEC_CONSOLE_DIR}" || exit
# tmp
mkdir -p /tmp/data
mkdir -p /etc/crowdsec/hub/
install -v -m 600 -D "./config/${CLIENT_SECRETS}" "${CROWDSEC_CONFIG_PATH}" 1> /dev/null || exit
install -v -m 600 -D "./config/${LAPI_SECRETS}" "${CROWDSEC_CONFIG_PATH}" 1> /dev/null || exit
## end tmp
# Don't overwrite existing files
[[ ! -f "${CROWDSEC_CONFIG_PATH}/${CLIENT_SECRETS}" ]] && install -v -m 600 -D "./config/${CLIENT_SECRETS}" "${CROWDSEC_CONFIG_PATH}" >/dev/null || exit
[[ ! -f "${CROWDSEC_CONFIG_PATH}/${LAPI_SECRETS}" ]] && install -v -m 600 -D "./config/${LAPI_SECRETS}" "${CROWDSEC_CONFIG_PATH}" > /dev/null || exit
[[ ! -f "${CROWDSEC_CONFIG_PATH}/config.yaml" ]] && install -v -m 600 -D ./config/config.yaml "${CROWDSEC_CONFIG_PATH}" > /dev/null || exit
[[ ! -f "${CROWDSEC_CONFIG_PATH}/dev.yaml" ]] && install -v -m 644 -D ./config/dev.yaml "${CROWDSEC_CONFIG_PATH}" > /dev/null || exit
[[ ! -f "${CROWDSEC_CONFIG_PATH}/user.yaml" ]] && install -v -m 644 -D ./config/user.yaml "${CROWDSEC_CONFIG_PATH}" > /dev/null || exit
[[ ! -f "${CROWDSEC_CONFIG_PATH}/acquis.yaml" ]] && install -v -m 644 -D ./config/acquis.yaml "${CROWDSEC_CONFIG_PATH}" > /dev/null || exit
[[ ! -f "${CROWDSEC_CONFIG_PATH}/profiles.yaml" ]] && install -v -m 644 -D ./config/profiles.yaml "${CROWDSEC_CONFIG_PATH}" > /dev/null || exit
[[ ! -f "${CROWDSEC_CONFIG_PATH}/simulation.yaml" ]] && install -v -m 644 -D ./config/simulation.yaml "${CROWDSEC_CONFIG_PATH}" > /dev/null || exit
[[ ! -f "${CROWDSEC_CONFIG_PATH}/console.yaml" ]] && install -v -m 644 -D ./config/console.yaml "${CROWDSEC_CONFIG_PATH}" > /dev/null || exit
[[ ! -f "${CROWDSEC_CONFIG_PATH}/context.yaml" ]] && install -v -m 644 -D ./config/context.yaml "${CROWDSEC_CONSOLE_DIR}" > /dev/null || exit
install -v -m 600 -D ./config/config.yaml "${CROWDSEC_CONFIG_PATH}" 1> /dev/null || exit
install -v -m 644 -D ./config/dev.yaml "${CROWDSEC_CONFIG_PATH}" 1> /dev/null || exit
install -v -m 644 -D ./config/user.yaml "${CROWDSEC_CONFIG_PATH}" 1> /dev/null || exit
install -v -m 644 -D ./config/acquis.yaml "${CROWDSEC_CONFIG_PATH}" 1> /dev/null || exit
install -v -m 644 -D ./config/profiles.yaml "${CROWDSEC_CONFIG_PATH}" 1> /dev/null || exit
install -v -m 644 -D ./config/simulation.yaml "${CROWDSEC_CONFIG_PATH}" 1> /dev/null || exit
install -v -m 644 -D ./config/"${CONSOLE_FILE}" "${CROWDSEC_CONFIG_PATH}" 1> /dev/null || exit
install -v -m 644 -D ./config/context.yaml "${CROWDSEC_CONSOLE_DIR}" 1> /dev/null || exit
DATA=${CROWDSEC_DATA_DIR} CFG=${CROWDSEC_CONFIG_PATH} envsubst '$CFG $DATA' < ./config/user.yaml > ${CROWDSEC_CONFIG_PATH}"/user.yaml" || log_fatal "unable to generate user configuration file"
if [[ ${DOCKER_MODE} == "false" ]]; then
CFG=${CROWDSEC_CONFIG_PATH} BIN=${CROWDSEC_BIN_INSTALLED} envsubst '$CFG $BIN' < ./config/crowdsec.service > "${SYSTEMD_PATH_FILE}" || log_fatal "unable to crowdsec systemd file"
fi
install_bins
if [[ ${DOCKER_MODE} == "false" ]]; then
@ -471,23 +456,12 @@ update_full() {
log_err "Cscli binary '$CSCLI_BIN' not found. Please build it with 'make build'" && exit
fi
log_info "Backing up existing configuration"
${CSCLI_BIN_INSTALLED} config backup ${BACKUP_DIR}
log_info "Saving default database content if exist"
if [[ -f "/var/lib/crowdsec/data/crowdsec.db" ]]; then
cp /var/lib/crowdsec/data/crowdsec.db ${BACKUP_DIR}/crowdsec.db
fi
log_info "Cleanup existing crowdsec configuration"
log_info "Removing old binaries"
uninstall_crowdsec
log_info "Installing crowdsec"
install_crowdsec
log_info "Restoring configuration"
log_info "Updating hub"
${CSCLI_BIN_INSTALLED} hub update
${CSCLI_BIN_INSTALLED} config restore ${BACKUP_DIR}
log_info "Restoring saved database if exist"
if [[ -f "${BACKUP_DIR}/crowdsec.db" ]]; then
cp ${BACKUP_DIR}/crowdsec.db /var/lib/crowdsec/data/crowdsec.db
fi
log_info "Finished, restarting"
systemctl restart crowdsec || log_fatal "Failed to restart crowdsec"
}
@ -565,15 +539,6 @@ uninstall_crowdsec() {
${CSCLI_BIN} dashboard remove -f -y >/dev/null
delete_bins
# tmp
rm -rf /tmp/data/
## end tmp
find /etc/crowdsec -maxdepth 1 -mindepth 1 | grep -v "bouncer" | xargs rm -rf || echo ""
rm -f ${CROWDSEC_LOG_FILE} || echo ""
rm -f ${LAPI_LOG_FILE} || echo ""
rm -f ${CROWDSEC_DB_PATH} || echo ""
rm -rf ${CROWDSEC_LIB_DIR} || echo ""
rm -rf ${CROWDSEC_USR_DIR} || echo ""
rm -f ${SYSTEMD_PATH_FILE} || echo ""
log_info "crowdsec successfully uninstalled"
@ -765,12 +730,11 @@ usage() {
echo " ./wizard.sh --unattended Install in unattended mode, no question will be asked and defaults will be followed"
echo " ./wizard.sh --docker-mode Will install crowdsec without systemd and generate random machine-id"
echo " ./wizard.sh -n|--noop Do nothing"
exit 0
}
if [[ $# -eq 0 ]]; then
usage
usage
exit 0
fi
while [[ $# -gt 0 ]]