bitbucket.org/Aishee/synsec@v0.0.0-20210414005726-236fc01a153d/cmd/synsec-cli/config.go (about)

     1  package main
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"os"
     8  	"path/filepath"
     9  
    10  	"github.com/pkg/errors"
    11  
    12  	"bitbucket.org/Aishee/synsec/pkg/cwhub"
    13  	"bitbucket.org/Aishee/synsec/pkg/types"
    14  	log "github.com/sirupsen/logrus"
    15  	"github.com/spf13/cobra"
    16  	"gopkg.in/yaml.v2"
    17  )
    18  
    19  type OldAPICfg struct {
    20  	MachineID string `json:"machine_id"`
    21  	Password  string `json:"password"`
    22  }
    23  
    24  /* Backup synsec configurations to directory <dirPath> :
    25  
    26  - Main config (config.yaml)
    27  - Profiles config (profiles.yaml)
    28  - Simulation config (simulation.yaml)
    29  - Backup of API credentials (local API and online API)
    30  - List of scenarios, parsers, postoverflows and collections that are up-to-date
    31  - Tainted/local/out-of-date scenarios, parsers, postoverflows and collections
    32  */
    33  func backupConfigToDirectory(dirPath string) error {
    34  	var err error
    35  
    36  	if dirPath == "" {
    37  		return fmt.Errorf("directory path can't be empty")
    38  	}
    39  	log.Infof("Starting configuration backup")
    40  	/*if parent directory doesn't exist, bail out. create final dir with Mkdir*/
    41  	parentDir := filepath.Dir(dirPath)
    42  	if _, err := os.Stat(parentDir); err != nil {
    43  		return errors.Wrapf(err, "while checking parent directory %s existence", parentDir)
    44  	}
    45  
    46  	if err = os.Mkdir(dirPath, 0700); err != nil {
    47  		return fmt.Errorf("error while creating %s : %s", dirPath, err)
    48  	}
    49  
    50  	if csConfig.ConfigPaths.SimulationFilePath != "" {
    51  		backupSimulation := fmt.Sprintf("%s/simulation.yaml", dirPath)
    52  		if err = types.CopyFile(csConfig.ConfigPaths.SimulationFilePath, backupSimulation); err != nil {
    53  			return fmt.Errorf("failed copy %s to %s : %s", csConfig.ConfigPaths.SimulationFilePath, backupSimulation, err)
    54  		}
    55  		log.Infof("Saved simulation to %s", backupSimulation)
    56  	}
    57  
    58  	/*
    59  	   - backup AcquisitionFilePath
    60  	   - backup the other files of acquisition directory
    61  	*/
    62  	if csConfig.Synsec != nil && csConfig.Synsec.AcquisitionFilePath != "" {
    63  		backupAcquisition := fmt.Sprintf("%s/acquis.yaml", dirPath)
    64  		if err = types.CopyFile(csConfig.Synsec.AcquisitionFilePath, backupAcquisition); err != nil {
    65  			return fmt.Errorf("failed copy %s to %s : %s", csConfig.Synsec.AcquisitionFilePath, backupAcquisition, err)
    66  		}
    67  	}
    68  
    69  	acquisBackupDir := dirPath + "/acquis/"
    70  	if err = os.Mkdir(acquisBackupDir, 0700); err != nil {
    71  		return fmt.Errorf("error while creating %s : %s", acquisBackupDir, err)
    72  	}
    73  
    74  	if csConfig.Synsec != nil && len(csConfig.Synsec.AcquisitionFiles) > 0 {
    75  		for _, acquisFile := range csConfig.Synsec.AcquisitionFiles {
    76  			/*if it was the default one, it was already backup'ed*/
    77  			if csConfig.Synsec.AcquisitionFilePath == acquisFile {
    78  				continue
    79  			}
    80  			targetFname, err := filepath.Abs(acquisBackupDir + filepath.Base(acquisFile))
    81  			if err != nil {
    82  				return errors.Wrapf(err, "while saving %s to %s", acquisFile, acquisBackupDir)
    83  			}
    84  			if err = types.CopyFile(acquisFile, targetFname); err != nil {
    85  				return fmt.Errorf("failed copy %s to %s : %s", acquisFile, targetFname, err)
    86  			}
    87  			log.Infof("Saved acquis %s to %s", acquisFile, targetFname)
    88  		}
    89  	}
    90  
    91  	if ConfigFilePath != "" {
    92  		backupMain := fmt.Sprintf("%s/config.yaml", dirPath)
    93  		if err = types.CopyFile(ConfigFilePath, backupMain); err != nil {
    94  			return fmt.Errorf("failed copy %s to %s : %s", ConfigFilePath, backupMain, err)
    95  		}
    96  		log.Infof("Saved default yaml to %s", backupMain)
    97  	}
    98  	if csConfig.API != nil && csConfig.API.Server != nil && csConfig.API.Server.OnlineClient != nil && csConfig.API.Server.OnlineClient.CredentialsFilePath != "" {
    99  		backupCAPICreds := fmt.Sprintf("%s/online_api_credentials.yaml", dirPath)
   100  		if err = types.CopyFile(csConfig.API.Server.OnlineClient.CredentialsFilePath, backupCAPICreds); err != nil {
   101  			return fmt.Errorf("failed copy %s to %s : %s", csConfig.API.Server.OnlineClient.CredentialsFilePath, backupCAPICreds, err)
   102  		}
   103  		log.Infof("Saved online API credentials to %s", backupCAPICreds)
   104  	}
   105  	if csConfig.API != nil && csConfig.API.Client != nil && csConfig.API.Client.CredentialsFilePath != "" {
   106  		backupLAPICreds := fmt.Sprintf("%s/local_api_credentials.yaml", dirPath)
   107  		if err = types.CopyFile(csConfig.API.Client.CredentialsFilePath, backupLAPICreds); err != nil {
   108  			return fmt.Errorf("failed copy %s to %s : %s", csConfig.API.Client.CredentialsFilePath, backupLAPICreds, err)
   109  		}
   110  		log.Infof("Saved local API credentials to %s", backupLAPICreds)
   111  	}
   112  	if csConfig.API != nil && csConfig.API.Server != nil && csConfig.API.Server.ProfilesPath != "" {
   113  		backupProfiles := fmt.Sprintf("%s/profiles.yaml", dirPath)
   114  		if err = types.CopyFile(csConfig.API.Server.ProfilesPath, backupProfiles); err != nil {
   115  			return fmt.Errorf("failed copy %s to %s : %s", csConfig.API.Server.ProfilesPath, backupProfiles, err)
   116  		}
   117  		log.Infof("Saved profiles to %s", backupProfiles)
   118  	}
   119  
   120  	if err = BackupHub(dirPath); err != nil {
   121  		return fmt.Errorf("failed to backup hub config : %s", err)
   122  	}
   123  
   124  	return nil
   125  }
   126  
   127  /* Restore synsec configurations to directory <dirPath> :
   128  
   129  - Main config (config.yaml)
   130  - Profiles config (profiles.yaml)
   131  - Simulation config (simulation.yaml)
   132  - Backup of API credentials (local API and online API)
   133  - List of scenarios, parsers, postoverflows and collections that are up-to-date
   134  - Tainted/local/out-of-date scenarios, parsers, postoverflows and collections
   135  */
   136  func restoreConfigFromDirectory(dirPath string) error {
   137  	var err error
   138  
   139  	if !restoreOldBackup {
   140  		backupMain := fmt.Sprintf("%s/config.yaml", dirPath)
   141  		if _, err = os.Stat(backupMain); err == nil {
   142  			if csConfig.ConfigPaths != nil && csConfig.ConfigPaths.ConfigDir != "" {
   143  				if err = types.CopyFile(backupMain, fmt.Sprintf("%s/config.yaml", csConfig.ConfigPaths.ConfigDir)); err != nil {
   144  					return fmt.Errorf("failed copy %s to %s : %s", backupMain, csConfig.ConfigPaths.ConfigDir, err)
   145  				}
   146  			}
   147  		}
   148  
   149  		// Now we have config.yaml, we should regenerate config struct to have rights paths etc
   150  		ConfigFilePath = fmt.Sprintf("%s/config.yaml", csConfig.ConfigPaths.ConfigDir)
   151  		initConfig()
   152  
   153  		backupCAPICreds := fmt.Sprintf("%s/online_api_credentials.yaml", dirPath)
   154  		if _, err = os.Stat(backupCAPICreds); err == nil {
   155  			if err = types.CopyFile(backupCAPICreds, csConfig.API.Server.OnlineClient.CredentialsFilePath); err != nil {
   156  				return fmt.Errorf("failed copy %s to %s : %s", backupCAPICreds, csConfig.API.Server.OnlineClient.CredentialsFilePath, err)
   157  			}
   158  		}
   159  
   160  		backupLAPICreds := fmt.Sprintf("%s/local_api_credentials.yaml", dirPath)
   161  		if _, err = os.Stat(backupLAPICreds); err == nil {
   162  			if err = types.CopyFile(backupLAPICreds, csConfig.API.Client.CredentialsFilePath); err != nil {
   163  				return fmt.Errorf("failed copy %s to %s : %s", backupLAPICreds, csConfig.API.Client.CredentialsFilePath, err)
   164  			}
   165  		}
   166  
   167  		backupProfiles := fmt.Sprintf("%s/profiles.yaml", dirPath)
   168  		if _, err = os.Stat(backupProfiles); err == nil {
   169  			if err = types.CopyFile(backupProfiles, csConfig.API.Server.ProfilesPath); err != nil {
   170  				return fmt.Errorf("failed copy %s to %s : %s", backupProfiles, csConfig.API.Server.ProfilesPath, err)
   171  			}
   172  		}
   173  	} else {
   174  		var oldAPICfg OldAPICfg
   175  		backupOldAPICfg := fmt.Sprintf("%s/api_creds.json", dirPath)
   176  
   177  		jsonFile, err := os.Open(backupOldAPICfg)
   178  		if err != nil {
   179  			log.Warningf("failed to open %s : %s", backupOldAPICfg, err)
   180  		} else {
   181  			byteValue, _ := ioutil.ReadAll(jsonFile)
   182  			err = json.Unmarshal(byteValue, &oldAPICfg)
   183  			if err != nil {
   184  				return fmt.Errorf("failed to load json file %s : %s", backupOldAPICfg, err)
   185  			}
   186  		}
   187  	}
   188  
   189  	backupSimulation := fmt.Sprintf("%s/simulation.yaml", dirPath)
   190  	if _, err = os.Stat(backupSimulation); err == nil {
   191  		if err = types.CopyFile(backupSimulation, csConfig.ConfigPaths.SimulationFilePath); err != nil {
   192  			return fmt.Errorf("failed copy %s to %s : %s", backupSimulation, csConfig.ConfigPaths.SimulationFilePath, err)
   193  		}
   194  	}
   195  
   196  	/*if there is a acquisition dir, restore its content*/
   197  	if csConfig.Synsec.AcquisitionDirPath != "" {
   198  		if err = os.Mkdir(csConfig.Synsec.AcquisitionDirPath, 0700); err != nil {
   199  			return fmt.Errorf("error while creating %s : %s", csConfig.Synsec.AcquisitionDirPath, err)
   200  		}
   201  
   202  	}
   203  
   204  	//if there was a single one
   205  	backupAcquisition := fmt.Sprintf("%s/acquis.yaml", dirPath)
   206  	if _, err = os.Stat(backupAcquisition); err == nil {
   207  		log.Debugf("restoring backup'ed %s", backupAcquisition)
   208  		if err = types.CopyFile(backupAcquisition, csConfig.Synsec.AcquisitionFilePath); err != nil {
   209  			return fmt.Errorf("failed copy %s to %s : %s", backupAcquisition, csConfig.Synsec.AcquisitionFilePath, err)
   210  		}
   211  	}
   212  
   213  	//if there is files in the acquis backup dir, restore them
   214  	acquisBackupDir := dirPath + "/acquis/*.yaml"
   215  	if acquisFiles, err := filepath.Glob(acquisBackupDir); err == nil {
   216  		for _, acquisFile := range acquisFiles {
   217  			targetFname, err := filepath.Abs(csConfig.Synsec.AcquisitionDirPath + "/" + filepath.Base(acquisFile))
   218  			if err != nil {
   219  				return errors.Wrapf(err, "while saving %s to %s", acquisFile, targetFname)
   220  			}
   221  			log.Debugf("restoring %s to %s", acquisFile, targetFname)
   222  			if err = types.CopyFile(acquisFile, targetFname); err != nil {
   223  				return fmt.Errorf("failed copy %s to %s : %s", acquisFile, targetFname, err)
   224  			}
   225  		}
   226  	}
   227  
   228  	if csConfig.Synsec != nil && len(csConfig.Synsec.AcquisitionFiles) > 0 {
   229  		for _, acquisFile := range csConfig.Synsec.AcquisitionFiles {
   230  			log.Infof("backup filepath from dir -> %s", acquisFile)
   231  			/*if it was the default one, it was already backup'ed*/
   232  			if csConfig.Synsec.AcquisitionFilePath == acquisFile {
   233  				log.Infof("skip this one")
   234  				continue
   235  			}
   236  			targetFname, err := filepath.Abs(acquisBackupDir + filepath.Base(acquisFile))
   237  			if err != nil {
   238  				return errors.Wrapf(err, "while saving %s to %s", acquisFile, acquisBackupDir)
   239  			}
   240  			if err = types.CopyFile(acquisFile, targetFname); err != nil {
   241  				return fmt.Errorf("failed copy %s to %s : %s", acquisFile, targetFname, err)
   242  			}
   243  			log.Infof("Saved acquis %s to %s", acquisFile, targetFname)
   244  		}
   245  	}
   246  
   247  	if err = RestoreHub(dirPath); err != nil {
   248  		return fmt.Errorf("failed to restore hub config : %s", err)
   249  	}
   250  
   251  	return nil
   252  }
   253  
   254  func NewConfigCmd() *cobra.Command {
   255  
   256  	var cmdConfig = &cobra.Command{
   257  		Use:   "config [command]",
   258  		Short: "Allows to view current config",
   259  		Args:  cobra.ExactArgs(0),
   260  	}
   261  	var cmdConfigShow = &cobra.Command{
   262  		Use:   "show",
   263  		Short: "Displays current config",
   264  		Long:  `Displays the current cli configuration.`,
   265  		Args:  cobra.ExactArgs(0),
   266  		Run: func(cmd *cobra.Command, args []string) {
   267  			switch csConfig.Cscli.Output {
   268  			case "human":
   269  				fmt.Printf("Global:\n")
   270  				if csConfig.ConfigPaths != nil {
   271  					fmt.Printf("   - Configuration Folder   : %s\n", csConfig.ConfigPaths.ConfigDir)
   272  					fmt.Printf("   - Data Folder            : %s\n", csConfig.ConfigPaths.DataDir)
   273  					fmt.Printf("   - Hub Folder             : %s\n", csConfig.ConfigPaths.HubDir)
   274  					fmt.Printf("   - Simulation File        : %s\n", csConfig.ConfigPaths.SimulationFilePath)
   275  				}
   276  				if csConfig.Common != nil {
   277  					fmt.Printf("   - Log Folder             : %s\n", csConfig.Common.LogDir)
   278  					fmt.Printf("   - Log level              : %s\n", csConfig.Common.LogLevel)
   279  					fmt.Printf("   - Log Media              : %s\n", csConfig.Common.LogMedia)
   280  				}
   281  				if csConfig.Synsec != nil {
   282  					fmt.Printf("Synsec:\n")
   283  					fmt.Printf("  - Acquisition File        : %s\n", csConfig.Synsec.AcquisitionFilePath)
   284  					fmt.Printf("  - Parsers routines        : %d\n", csConfig.Synsec.ParserRoutinesCount)
   285  				}
   286  				if csConfig.Cscli != nil {
   287  					fmt.Printf("ccscli:\n")
   288  					fmt.Printf("  - Output                  : %s\n", csConfig.Cscli.Output)
   289  					fmt.Printf("  - Hub Branch              : %s\n", csConfig.Cscli.HubBranch)
   290  					fmt.Printf("  - Hub Folder              : %s\n", csConfig.Cscli.HubDir)
   291  				}
   292  				if csConfig.API != nil {
   293  					if csConfig.API.Client != nil && csConfig.API.Client.Credentials != nil {
   294  						fmt.Printf("API Client:\n")
   295  						fmt.Printf("  - URL                     : %s\n", csConfig.API.Client.Credentials.URL)
   296  						fmt.Printf("  - Login                   : %s\n", csConfig.API.Client.Credentials.Login)
   297  						fmt.Printf("  - Credentials File        : %s\n", csConfig.API.Client.CredentialsFilePath)
   298  					}
   299  					if csConfig.API.Server != nil {
   300  						fmt.Printf("Local API Server:\n")
   301  						fmt.Printf("  - Listen URL              : %s\n", csConfig.API.Server.ListenURI)
   302  						fmt.Printf("  - Profile File            : %s\n", csConfig.API.Server.ProfilesPath)
   303  						if csConfig.API.Server.TLS != nil {
   304  							if csConfig.API.Server.TLS.CertFilePath != "" {
   305  								fmt.Printf("  - Cert File : %s\n", csConfig.API.Server.TLS.CertFilePath)
   306  							}
   307  							if csConfig.API.Server.TLS.KeyFilePath != "" {
   308  								fmt.Printf("  - Key File  : %s\n", csConfig.API.Server.TLS.KeyFilePath)
   309  							}
   310  						}
   311  						if csConfig.API.Server.OnlineClient != nil && csConfig.API.Server.OnlineClient.Credentials != nil {
   312  							fmt.Printf("Central API:\n")
   313  							fmt.Printf("  - URL                     : %s\n", csConfig.API.Server.OnlineClient.Credentials.URL)
   314  							fmt.Printf("  - Login                   : %s\n", csConfig.API.Server.OnlineClient.Credentials.Login)
   315  							fmt.Printf("  - Credentials File        : %s\n", csConfig.API.Server.OnlineClient.CredentialsFilePath)
   316  						}
   317  					}
   318  				}
   319  				if csConfig.DbConfig != nil {
   320  					fmt.Printf("  - Database:\n")
   321  					fmt.Printf("      - Type                : %s\n", csConfig.DbConfig.Type)
   322  					switch csConfig.DbConfig.Type {
   323  					case "sqlite":
   324  						fmt.Printf("      - Path                : %s\n", csConfig.DbConfig.DbPath)
   325  					case "mysql", "postgresql", "postgres":
   326  						fmt.Printf("      - Host                : %s\n", csConfig.DbConfig.Host)
   327  						fmt.Printf("      - Port                : %d\n", csConfig.DbConfig.Port)
   328  						fmt.Printf("      - User                : %s\n", csConfig.DbConfig.User)
   329  						fmt.Printf("      - DB Name             : %s\n", csConfig.DbConfig.DbName)
   330  					}
   331  					if csConfig.DbConfig.Flush != nil {
   332  						if *csConfig.DbConfig.Flush.MaxAge != "" {
   333  							fmt.Printf("      - Flush age           : %s\n", *csConfig.DbConfig.Flush.MaxAge)
   334  						}
   335  						if *csConfig.DbConfig.Flush.MaxItems != 0 {
   336  							fmt.Printf("      - Flush size          : %d\n", *csConfig.DbConfig.Flush.MaxItems)
   337  						}
   338  					}
   339  				}
   340  			case "json":
   341  				data, err := json.MarshalIndent(csConfig, "", "  ")
   342  				if err != nil {
   343  					log.Fatalf("failed to marshal configuration: %s", err)
   344  				}
   345  				fmt.Printf("%s\n", string(data))
   346  			case "raw":
   347  				data, err := yaml.Marshal(csConfig)
   348  				if err != nil {
   349  					log.Fatalf("failed to marshal configuration: %s", err)
   350  				}
   351  				fmt.Printf("%s\n", string(data))
   352  			}
   353  		},
   354  	}
   355  	cmdConfig.AddCommand(cmdConfigShow)
   356  
   357  	var cmdConfigBackup = &cobra.Command{
   358  		Use:   "backup <directory>",
   359  		Short: "Backup current config",
   360  		Long: `Backup the current synsec configuration including :
   361  
   362  - Main config (config.yaml)
   363  - Simulation config (simulation.yaml)
   364  - Profiles config (profiles.yaml)
   365  - List of scenarios, parsers, postoverflows and collections that are up-to-date
   366  - Tainted/local/out-of-date scenarios, parsers, postoverflows and collections
   367  - Backup of API credentials (local API and online API)`,
   368  		Example: `ccscli config backup ./my-backup`,
   369  		Args:    cobra.ExactArgs(1),
   370  		Run: func(cmd *cobra.Command, args []string) {
   371  			var err error
   372  			if err := csConfig.LoadHub(); err != nil {
   373  				log.Fatalf(err.Error())
   374  			}
   375  			if err = cwhub.GetHubIdx(csConfig.Hub); err != nil {
   376  				log.Fatalf("Failed to get Hub index : %v", err)
   377  				log.Infoln("Run 'sudo ccscli hub update' to get the hub index")
   378  			}
   379  			if err = backupConfigToDirectory(args[0]); err != nil {
   380  				log.Fatalf("Failed to backup configurations: %s", err)
   381  			}
   382  		},
   383  	}
   384  	cmdConfig.AddCommand(cmdConfigBackup)
   385  
   386  	var cmdConfigRestore = &cobra.Command{
   387  		Use:   "restore <directory>",
   388  		Short: "Restore config in backup <directory>",
   389  		Long: `Restore the synsec configuration from specified backup <directory> including:
   390  
   391  - Main config (config.yaml)
   392  - Simulation config (simulation.yaml)
   393  - Profiles config (profiles.yaml)
   394  - List of scenarios, parsers, postoverflows and collections that are up-to-date
   395  - Tainted/local/out-of-date scenarios, parsers, postoverflows and collections
   396  - Backup of API credentials (local API and online API)`,
   397  		Args: cobra.ExactArgs(1),
   398  		Run: func(cmd *cobra.Command, args []string) {
   399  			var err error
   400  			if err = cwhub.GetHubIdx(csConfig.Hub); err != nil {
   401  				log.Fatalf("Failed to get Hub index : %v", err)
   402  				log.Infoln("Run 'sudo ccscli hub update' to get the hub index")
   403  			}
   404  			if err := restoreConfigFromDirectory(args[0]); err != nil {
   405  				log.Fatalf("failed restoring configurations from %s : %s", args[0], err)
   406  			}
   407  		},
   408  	}
   409  	cmdConfigRestore.PersistentFlags().BoolVar(&restoreOldBackup, "old-backup", false, "To use when you are upgrading synsec v0.X to v1.X and you need to restore backup from v0.X")
   410  	cmdConfig.AddCommand(cmdConfigRestore)
   411  
   412  	return cmdConfig
   413  }