2023-01-17 00:55:28 -06:00
|
|
|
package backy
|
|
|
|
|
|
|
|
import (
|
2023-02-01 23:45:23 -06:00
|
|
|
"bytes"
|
2023-02-18 22:42:15 -06:00
|
|
|
"text/template"
|
2023-02-01 23:45:23 -06:00
|
|
|
|
2025-01-14 09:42:43 -06:00
|
|
|
"strings"
|
|
|
|
|
2025-01-03 23:30:07 -06:00
|
|
|
"git.andrewnw.xyz/CyberShell/backy/pkg/pkgman"
|
2025-01-28 15:42:50 -06:00
|
|
|
"git.andrewnw.xyz/CyberShell/backy/pkg/remotefetcher"
|
2025-01-14 09:42:43 -06:00
|
|
|
"git.andrewnw.xyz/CyberShell/backy/pkg/usermanager"
|
2023-05-12 00:42:14 -05:00
|
|
|
vaultapi "github.com/hashicorp/vault/api"
|
2023-02-01 23:45:23 -06:00
|
|
|
"github.com/kevinburke/ssh_config"
|
2023-09-08 23:42:13 -05:00
|
|
|
"github.com/knadh/koanf/v2"
|
2023-02-01 23:45:23 -06:00
|
|
|
"github.com/nikoksr/notify"
|
2023-01-17 00:55:28 -06:00
|
|
|
"github.com/rs/zerolog"
|
2023-02-01 23:45:23 -06:00
|
|
|
"golang.org/x/crypto/ssh"
|
2023-01-17 00:55:28 -06:00
|
|
|
)
|
|
|
|
|
2023-02-18 22:42:15 -06:00
|
|
|
type (
|
|
|
|
|
|
|
|
// Host defines a host to which to connect.
|
|
|
|
// If not provided, the values will be looked up in the default ssh config files
|
|
|
|
Host struct {
|
2025-01-14 09:42:43 -06:00
|
|
|
OS string `yaml:"OS,omitempty"`
|
2023-09-08 23:42:13 -05:00
|
|
|
ConfigFilePath string `yaml:"config,omitempty"`
|
2023-02-18 22:42:15 -06:00
|
|
|
Host string `yaml:"host,omitempty"`
|
|
|
|
HostName string `yaml:"hostname,omitempty"`
|
|
|
|
KnownHostsFile string `yaml:"knownhostsfile,omitempty"`
|
|
|
|
ClientConfig *ssh.ClientConfig
|
|
|
|
SSHConfigFile *sshConfigFile
|
|
|
|
SshClient *ssh.Client
|
|
|
|
Port uint16 `yaml:"port,omitempty"`
|
|
|
|
ProxyJump string `yaml:"proxyjump,omitempty"`
|
|
|
|
Password string `yaml:"password,omitempty"`
|
|
|
|
PrivateKeyPath string `yaml:"privatekeypath,omitempty"`
|
|
|
|
PrivateKeyPassword string `yaml:"privatekeypassword,omitempty"`
|
|
|
|
useDefaultConfig bool
|
|
|
|
User string `yaml:"user,omitempty"`
|
2023-03-13 20:25:27 -05:00
|
|
|
isProxyHost bool
|
2023-02-18 22:42:15 -06:00
|
|
|
// ProxyHost holds the configuration for a ProxyJump host
|
|
|
|
ProxyHost []*Host
|
|
|
|
// CertPath string `yaml:"cert_path,omitempty"`
|
|
|
|
}
|
|
|
|
|
|
|
|
sshConfigFile struct {
|
|
|
|
SshConfigFile *ssh_config.Config
|
|
|
|
DefaultUserSettings *ssh_config.UserSettings
|
|
|
|
}
|
|
|
|
|
|
|
|
Command struct {
|
2024-11-11 22:44:28 -06:00
|
|
|
Name string `yaml:"name,omitempty"`
|
2023-02-18 22:42:15 -06:00
|
|
|
|
|
|
|
// command to run
|
|
|
|
Cmd string `yaml:"cmd"`
|
|
|
|
|
2023-05-12 00:42:14 -05:00
|
|
|
// Possible values: script, scriptFile
|
2024-11-11 22:44:28 -06:00
|
|
|
// If blank, it is regular command.
|
|
|
|
Type string `yaml:"type,omitempty"`
|
2023-05-12 00:42:14 -05:00
|
|
|
|
2023-02-18 22:42:15 -06:00
|
|
|
// host on which to run cmd
|
|
|
|
Host *string `yaml:"host,omitempty"`
|
|
|
|
|
2024-11-11 22:44:28 -06:00
|
|
|
// Hooks are for running commands on certain events
|
|
|
|
Hooks *Hooks `yaml:"hooks,omitempty"`
|
|
|
|
|
|
|
|
// hook refs are internal references of commands for each hook type
|
|
|
|
hookRefs map[string]map[string]*Command
|
|
|
|
|
2025-02-08 15:17:34 -06:00
|
|
|
// Shell specifies which shell to run the command in, if any.
|
2023-02-18 22:42:15 -06:00
|
|
|
Shell string `yaml:"shell,omitempty"`
|
|
|
|
|
|
|
|
RemoteHost *Host `yaml:"-"`
|
|
|
|
|
|
|
|
// Args is an array that holds the arguments to cmd
|
|
|
|
Args []string `yaml:"args,omitempty"`
|
|
|
|
|
|
|
|
/*
|
|
|
|
Dir specifies a directory in which to run the command.
|
|
|
|
Ignored if Host is set.
|
|
|
|
*/
|
|
|
|
Dir *string `yaml:"dir,omitempty"`
|
|
|
|
|
|
|
|
// Env points to a file containing env variables to be used with the command
|
|
|
|
Env string `yaml:"env,omitempty"`
|
|
|
|
|
|
|
|
// Environment holds env variables to be used with the command
|
|
|
|
Environment []string `yaml:"environment,omitempty"`
|
2023-05-12 00:42:14 -05:00
|
|
|
|
|
|
|
// Output determines if output is requested.
|
2025-02-08 15:17:34 -06:00
|
|
|
//
|
|
|
|
// Only for when command is in a list.
|
2023-07-01 21:46:54 -05:00
|
|
|
GetOutput bool `yaml:"getOutput,omitempty"`
|
2023-08-06 22:27:51 -05:00
|
|
|
|
|
|
|
ScriptEnvFile string `yaml:"scriptEnvFile"`
|
2025-01-03 23:30:07 -06:00
|
|
|
|
2025-02-08 15:17:34 -06:00
|
|
|
// BEGIN PACKAGE COMMAND FIELDS
|
|
|
|
|
2025-01-03 23:30:07 -06:00
|
|
|
PackageManager string `yaml:"packageManager,omitempty"`
|
|
|
|
|
|
|
|
PackageName string `yaml:"packageName,omitempty"`
|
|
|
|
|
|
|
|
// Version specifies the desired version for package execution
|
|
|
|
PackageVersion string `yaml:"packageVersion,omitempty"`
|
|
|
|
|
|
|
|
// PackageOperation specifies the action for package-related commands (e.g., "install" or "remove")
|
|
|
|
PackageOperation string `yaml:"packageOperation,omitempty"`
|
|
|
|
|
|
|
|
pkgMan pkgman.PackageManager
|
|
|
|
|
|
|
|
packageCmdSet bool
|
2025-02-08 15:17:34 -06:00
|
|
|
// END PACKAGE COMMAND FIELDS
|
2025-01-03 23:30:07 -06:00
|
|
|
|
|
|
|
// RemoteSource specifies a URL to fetch the command or configuration remotely
|
|
|
|
RemoteSource string `yaml:"remoteSource,omitempty"`
|
|
|
|
|
|
|
|
// FetchBeforeExecution determines if the remoteSource should be fetched before running
|
|
|
|
FetchBeforeExecution bool `yaml:"fetchBeforeExecution,omitempty"`
|
|
|
|
|
2025-02-08 15:17:34 -06:00
|
|
|
// BEGIN USER COMMAND FIELDS
|
|
|
|
|
2025-01-03 23:30:07 -06:00
|
|
|
// Username specifies the username for user creation or related operations
|
2025-02-08 15:17:34 -06:00
|
|
|
Username string `yaml:"userName,omitempty"`
|
|
|
|
|
|
|
|
UserID string `yaml:"userID,omitempty"`
|
2025-01-03 23:30:07 -06:00
|
|
|
|
2025-01-14 09:42:43 -06:00
|
|
|
// UserGroups specifies the groups to add the user to
|
|
|
|
UserGroups []string `yaml:"userGroups,omitempty"`
|
|
|
|
|
|
|
|
// UserHome specifies the home directory for the user
|
|
|
|
UserHome string `yaml:"userHome,omitempty"`
|
|
|
|
|
|
|
|
// UserShell specifies the shell for the user
|
|
|
|
UserShell string `yaml:"userShell,omitempty"`
|
|
|
|
|
|
|
|
// SystemUser specifies whether the user is a system account
|
|
|
|
SystemUser bool `yaml:"systemUser,omitempty"`
|
2025-01-03 23:30:07 -06:00
|
|
|
|
2025-01-14 09:42:43 -06:00
|
|
|
// UserPassword specifies the password for the user (can be file: or plain text)
|
|
|
|
UserPassword string `yaml:"userPassword,omitempty"`
|
2025-01-03 23:30:07 -06:00
|
|
|
|
2025-01-14 09:42:43 -06:00
|
|
|
userMan usermanager.UserManager
|
2025-01-03 23:30:07 -06:00
|
|
|
|
2025-01-14 09:42:43 -06:00
|
|
|
// OS for the command, only used when type is user
|
|
|
|
OS string `yaml:"OS,omitempty"`
|
2025-01-03 23:30:07 -06:00
|
|
|
|
2025-01-14 09:42:43 -06:00
|
|
|
// UserOperation specifies the action for user-related commands (e.g., "create" or "remove")
|
|
|
|
UserOperation string `yaml:"userOperation,omitempty"`
|
|
|
|
|
|
|
|
userCmdSet bool
|
|
|
|
|
2025-02-08 15:17:34 -06:00
|
|
|
// stdin only for userOperation = password (for now)
|
2025-01-14 09:42:43 -06:00
|
|
|
stdin *strings.Reader
|
2025-02-08 15:17:34 -06:00
|
|
|
|
|
|
|
// END USER STRUCT FIELDS
|
2025-01-03 23:30:07 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
RemoteSource struct {
|
|
|
|
URL string `yaml:"url"`
|
2025-02-08 15:17:34 -06:00
|
|
|
Type string `yaml:"type"` // e.g., s3, http
|
2025-01-03 23:30:07 -06:00
|
|
|
Auth struct {
|
|
|
|
AccessKey string `yaml:"accessKey"`
|
|
|
|
SecretKey string `yaml:"secretKey"`
|
|
|
|
} `yaml:"auth"`
|
2023-02-18 22:42:15 -06:00
|
|
|
}
|
|
|
|
|
2023-07-01 21:46:54 -05:00
|
|
|
BackyOptionFunc func(*ConfigOpts)
|
2023-02-18 22:42:15 -06:00
|
|
|
|
|
|
|
CmdList struct {
|
2024-08-28 15:06:25 -05:00
|
|
|
Name string `yaml:"name,omitempty"`
|
|
|
|
Cron string `yaml:"cron,omitempty"`
|
|
|
|
RunCmdOnFailure string `yaml:"runCmdOnFailure,omitempty"`
|
|
|
|
Order []string `yaml:"order,omitempty"`
|
|
|
|
Notifications []string `yaml:"notifications,omitempty"`
|
|
|
|
GetOutput bool `yaml:"getOutput,omitempty"`
|
|
|
|
NotifyOnSuccess bool `yaml:"notifyOnSuccess,omitempty"`
|
|
|
|
|
|
|
|
NotifyConfig *notify.Notify
|
2025-01-03 23:30:07 -06:00
|
|
|
Source string `yaml:"source"` // URL to fetch remote commands
|
|
|
|
Type string `yaml:"type"`
|
2023-02-18 22:42:15 -06:00
|
|
|
}
|
|
|
|
|
2023-09-08 23:42:13 -05:00
|
|
|
ConfigOpts struct {
|
2023-02-18 22:42:15 -06:00
|
|
|
// Cmds holds the commands for a list.
|
|
|
|
// Key is the name of the command,
|
|
|
|
Cmds map[string]*Command `yaml:"commands"`
|
|
|
|
|
|
|
|
// CmdConfigLists holds the lists of commands to be run in order.
|
|
|
|
// Key is the command list name.
|
2023-09-08 23:42:13 -05:00
|
|
|
CmdConfigLists map[string]*CmdList `yaml:"cmd-lists"`
|
2023-02-18 22:42:15 -06:00
|
|
|
|
|
|
|
// Hosts holds the Host config.
|
|
|
|
// key is the host.
|
|
|
|
Hosts map[string]*Host `yaml:"hosts"`
|
|
|
|
|
|
|
|
Logger zerolog.Logger
|
|
|
|
|
|
|
|
// Global log level
|
|
|
|
BackyLogLvl *string
|
2023-09-08 23:42:13 -05:00
|
|
|
|
2023-02-18 22:42:15 -06:00
|
|
|
// Holds config file
|
|
|
|
ConfigFilePath string
|
|
|
|
|
2025-01-14 09:42:43 -06:00
|
|
|
// Holds log file
|
|
|
|
LogFilePath string
|
|
|
|
|
2024-08-28 15:06:25 -05:00
|
|
|
// for command list file
|
|
|
|
CmdListFile string
|
2023-02-18 22:42:15 -06:00
|
|
|
|
|
|
|
// use command lists using cron
|
2024-11-11 22:44:28 -06:00
|
|
|
cronEnabled bool
|
2023-02-18 22:42:15 -06:00
|
|
|
// Holds commands to execute for the exec command
|
|
|
|
executeCmds []string
|
2023-07-01 21:46:54 -05:00
|
|
|
// Holds lists to execute for the backup command
|
2023-02-18 22:42:15 -06:00
|
|
|
executeLists []string
|
|
|
|
|
|
|
|
// Holds env vars from .env file
|
|
|
|
backyEnv map[string]string
|
|
|
|
|
2023-05-12 00:42:14 -05:00
|
|
|
vaultClient *vaultapi.Client
|
|
|
|
|
2023-09-08 23:42:13 -05:00
|
|
|
List ListConfig
|
|
|
|
|
2023-05-12 00:42:14 -05:00
|
|
|
VaultKeys []*VaultKey `yaml:"keys"`
|
|
|
|
|
2023-09-08 23:42:13 -05:00
|
|
|
koanf *koanf.Koanf
|
|
|
|
|
|
|
|
NotificationConf *Notifications `yaml:"notifications"`
|
2025-01-28 15:42:50 -06:00
|
|
|
|
|
|
|
Cache *remotefetcher.Cache
|
|
|
|
CachedData []*remotefetcher.CacheData
|
2023-02-18 22:42:15 -06:00
|
|
|
}
|
|
|
|
|
2023-05-12 00:42:14 -05:00
|
|
|
outStruct struct {
|
|
|
|
CmdName string
|
|
|
|
CmdExecuted string
|
|
|
|
Output []string
|
|
|
|
}
|
|
|
|
|
|
|
|
VaultKey struct {
|
|
|
|
Name string `yaml:"name"`
|
|
|
|
Path string `yaml:"path"`
|
|
|
|
ValueType string `yaml:"type"`
|
|
|
|
MountPath string `yaml:"mountpath"`
|
|
|
|
}
|
|
|
|
|
|
|
|
VaultConfig struct {
|
|
|
|
Token string `yaml:"token"`
|
|
|
|
Address string `yaml:"address"`
|
|
|
|
Enabled string `yaml:"enabled"`
|
|
|
|
Keys []*VaultKey `yaml:"keys"`
|
|
|
|
}
|
|
|
|
|
2023-09-08 23:42:13 -05:00
|
|
|
Notifications struct {
|
|
|
|
MailConfig map[string]MailConfig `yaml:"mail,omitempty"`
|
|
|
|
MatrixConfig map[string]MatrixStruct `yaml:"matrix,omitempty"`
|
2023-02-18 22:42:15 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
CmdOutput struct {
|
|
|
|
Err error
|
|
|
|
Output bytes.Buffer
|
|
|
|
}
|
|
|
|
|
|
|
|
environmentVars struct {
|
|
|
|
file string
|
|
|
|
env []string
|
|
|
|
}
|
|
|
|
|
|
|
|
msgTemplates struct {
|
|
|
|
success *template.Template
|
|
|
|
err *template.Template
|
|
|
|
}
|
2023-09-08 23:42:13 -05:00
|
|
|
|
|
|
|
ListConfig struct {
|
|
|
|
Lists []string
|
|
|
|
Commands []string
|
|
|
|
Hosts []string
|
|
|
|
}
|
2024-11-11 22:44:28 -06:00
|
|
|
|
|
|
|
Hooks struct {
|
2024-11-14 21:10:49 -06:00
|
|
|
Error []string `yaml:"error,omitempty"`
|
|
|
|
Success []string `yaml:"success,omitempty"`
|
|
|
|
Final []string `yaml:"final,omitempty"`
|
2024-11-11 22:44:28 -06:00
|
|
|
}
|
|
|
|
|
2025-01-14 09:42:43 -06:00
|
|
|
CmdResult struct {
|
|
|
|
CmdName string // Name of the command executed
|
|
|
|
ListName string // Name of the command list
|
|
|
|
Error error // Error encountered, if any
|
2024-11-11 22:44:28 -06:00
|
|
|
}
|
2023-02-18 22:42:15 -06:00
|
|
|
)
|