Skip to content

Commit

Permalink
Fix some backup/restore bugs + improve MySQL support
Browse files Browse the repository at this point in the history
  • Loading branch information
moul committed Dec 1, 2017
1 parent 5114700 commit 3c10578
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 28 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
* Connection history
* Audit log
* Add dynamic strict host key checking (learning on the first time, strict on the next ones)
* Add-back MySQL support (experimental)
* Fix some backup/restore bugs

## v1.4.0 (2017-11-24)

Expand Down
20 changes: 11 additions & 9 deletions db.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ type Config struct {
HostGroups []*HostGroup `json:"host_groups"`
ACLs []*ACL `json:"acls"`
Settings []*Setting `json:"settings"`
Events []*Event `json:"events"`
Sessions []*Session `json:"sessions"`
Date time.Time `json:"date"`
// FIXME: add latest migration
Date time.Time `json:"date"`
}

type Setting struct {
Expand Down Expand Up @@ -118,14 +120,14 @@ type ACL struct {

type Session struct {
gorm.Model
StoppedAt time.Time `valid:"optional"`
Status string `valid:"required"`
User *User `gorm:"ForeignKey:UserID"`
Host *Host `gorm:"ForeignKey:HostID"`
UserID uint `valid:"optional"`
HostID uint `valid:"optional"`
ErrMsg string `valid:"optional"`
Comment string `valid:"optional"`
StoppedAt *time.Time `sql:"index" valid:"optional"`
Status string `valid:"required"`
User *User `gorm:"ForeignKey:UserID"`
Host *Host `gorm:"ForeignKey:HostID"`
UserID uint `valid:"optional"`
HostID uint `valid:"optional"`
ErrMsg string `valid:"optional"`
Comment string `valid:"optional"`
}

type Event struct {
Expand Down
39 changes: 39 additions & 0 deletions dbinit.go
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,45 @@ func dbInit(db *gorm.DB) error {
Rollback: func(tx *gorm.DB) error {
return fmt.Errorf("not implemented")
},
}, {
ID: "26",
Migrate: func(tx *gorm.DB) error {
type Session struct {
gorm.Model
StoppedAt *time.Time `sql:"index" valid:"optional"`
Status string `valid:"required"`
User *User `gorm:"ForeignKey:UserID"`
Host *Host `gorm:"ForeignKey:HostID"`
UserID uint `valid:"optional"`
HostID uint `valid:"optional"`
ErrMsg string `valid:"optional"`
Comment string `valid:"optional"`
}
return tx.AutoMigrate(&Session{}).Error
},
Rollback: func(tx *gorm.DB) error {
return fmt.Errorf("not implemented")
},
}, {
ID: "27",
Migrate: func(tx *gorm.DB) error {
var sessions []Session
if err := db.Find(&sessions).Error; err != nil {
return err
}

for _, session := range sessions {
if session.StoppedAt != nil && session.StoppedAt.IsZero() {
if err := db.Model(&session).Updates(map[string]interface{}{"stopped_at": nil}).Error; err != nil {
return err
}
}
}
return nil
},
Rollback: func(tx *gorm.DB) error {
return fmt.Errorf("not implemented")
},
},
})
if err := m.Migrate(); err != nil {
Expand Down
3 changes: 2 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,8 @@ func server(c *cli.Context) error {
}
}
sessUpdate.Status = SessionStatusClosed
sessUpdate.StoppedAt = time.Now()
now := time.Now()
sessUpdate.StoppedAt = &now
db.Model(&sess).Updates(&sessUpdate)
case "deny":
fmt.Fprintf(s, "You don't have permission to that host.\n")
Expand Down
84 changes: 66 additions & 18 deletions shell.go
Original file line number Diff line number Diff line change
Expand Up @@ -286,11 +286,11 @@ GLOBAL OPTIONS:
}

config := Config{}
if err := db.Find(&config.Hosts).Error; err != nil {
if err := HostsPreload(db).Find(&config.Hosts).Error; err != nil {
return err
}

if err := db.Find(&config.SSHKeys).Error; err != nil {
if err := SSHKeysPreload(db).Find(&config.SSHKeys).Error; err != nil {
return err
}
for _, key := range config.SSHKeys {
Expand All @@ -304,7 +304,7 @@ GLOBAL OPTIONS:
}
}

if err := db.Find(&config.Hosts).Error; err != nil {
if err := HostsPreload(db).Find(&config.Hosts).Error; err != nil {
return err
}
for _, host := range config.Hosts {
Expand All @@ -318,24 +318,30 @@ GLOBAL OPTIONS:
}
}

if err := db.Find(&config.UserKeys).Error; err != nil {
if err := UserKeysPreload(db).Find(&config.UserKeys).Error; err != nil {
return err
}
if err := db.Find(&config.Users).Error; err != nil {
if err := UsersPreload(db).Find(&config.Users).Error; err != nil {
return err
}
if err := db.Find(&config.UserGroups).Error; err != nil {
if err := UserGroupsPreload(db).Find(&config.UserGroups).Error; err != nil {
return err
}
if err := db.Find(&config.HostGroups).Error; err != nil {
if err := HostGroupsPreload(db).Find(&config.HostGroups).Error; err != nil {
return err
}
if err := db.Find(&config.ACLs).Error; err != nil {
if err := ACLsPreload(db).Find(&config.ACLs).Error; err != nil {
return err
}
if err := db.Find(&config.Settings).Error; err != nil {
return err
}
if err := SessionsPreload(db).Find(&config.Sessions).Error; err != nil {
return err
}
if err := EventsPreload(db).Find(&config.Events).Error; err != nil {
return err
}
config.Date = time.Now()
enc := json.NewEncoder(s)
if c.Bool("indent") {
Expand Down Expand Up @@ -372,6 +378,8 @@ GLOBAL OPTIONS:
fmt.Fprintf(s, "* %d Userkeys\n", len(config.UserKeys))
fmt.Fprintf(s, "* %d Users\n", len(config.Users))
fmt.Fprintf(s, "* %d Settings\n", len(config.Settings))
fmt.Fprintf(s, "* %d Sessions\n", len(config.Sessions))
fmt.Fprintf(s, "* %d Events\n", len(config.Events))

if !c.Bool("confirm") {
fmt.Fprintf(s, "restore will erase and replace everything in the database.\nIf you are ok, add the '--confirm' to the restore command\n")
Expand All @@ -380,8 +388,36 @@ GLOBAL OPTIONS:

tx := db.Begin()

// FIXME: handle different migrations:
// 1. drop tables
// 2. apply migrations `1` to `<backup-migration-id>`
// 3. restore data
// 4. continues migrations

// FIXME: tell the administrator to restart the server
// if the master host key changed

// FIXME: do everything in a transaction
for _, tableName := range []string{"hosts", "users", "acls", "host_groups", "user_groups", "ssh_keys", "user_keys", "settings"} {
tableNames := []string{
"acls",
"events",
"host_group_acls",
"host_groups",
"host_host_groups",
"hosts",
//"migrations",
"sessions",
"settings",
"ssh_keys",
"user_group_acls",
"user_groups",
"user_keys",
"user_roles",
"user_user_groups",
"user_user_roles",
"users",
}
for _, tableName := range tableNames {
if err := tx.Exec(fmt.Sprintf("DELETE FROM %s;", tableName)).Error; err != nil {
tx.Rollback()
return err
Expand All @@ -394,31 +430,31 @@ GLOBAL OPTIONS:
return err
}
}
if err := tx.Create(&host).Error; err != nil {
if err := tx.FirstOrCreate(&host).Error; err != nil {
tx.Rollback()
return err
}
}
for _, user := range config.Users {
if err := tx.Create(&user).Error; err != nil {
if err := tx.FirstOrCreate(&user).Error; err != nil {
tx.Rollback()
return err
}
}
for _, acl := range config.ACLs {
if err := tx.Create(&acl).Error; err != nil {
if err := tx.FirstOrCreate(&acl).Error; err != nil {
tx.Rollback()
return err
}
}
for _, hostGroup := range config.HostGroups {
if err := tx.Create(&hostGroup).Error; err != nil {
if err := tx.FirstOrCreate(&hostGroup).Error; err != nil {
tx.Rollback()
return err
}
}
for _, userGroup := range config.UserGroups {
if err := tx.Create(&userGroup).Error; err != nil {
if err := tx.FirstOrCreate(&userGroup).Error; err != nil {
tx.Rollback()
return err
}
Expand All @@ -430,19 +466,31 @@ GLOBAL OPTIONS:
return err
}
}
if err := tx.Create(&sshKey).Error; err != nil {
if err := tx.FirstOrCreate(&sshKey).Error; err != nil {
tx.Rollback()
return err
}
}
for _, userKey := range config.UserKeys {
if err := tx.Create(&userKey).Error; err != nil {
if err := tx.FirstOrCreate(&userKey).Error; err != nil {
tx.Rollback()
return err
}
}
for _, setting := range config.Settings {
if err := tx.Create(&setting).Error; err != nil {
if err := tx.FirstOrCreate(&setting).Error; err != nil {
tx.Rollback()
return err
}
}
for _, session := range config.Sessions {
if err := tx.FirstOrCreate(&session).Error; err != nil {
tx.Rollback()
return err
}
}
for _, event := range config.Events {
if err := tx.FirstOrCreate(&event).Error; err != nil {
tx.Rollback()
return err
}
Expand Down Expand Up @@ -1560,7 +1608,7 @@ GLOBAL OPTIONS:
if session.StoppedAt.IsZero() {
duration = humanize.RelTime(session.CreatedAt, time.Now(), "", "")
} else {
duration = humanize.RelTime(session.CreatedAt, session.StoppedAt, "", "")
duration = humanize.RelTime(session.CreatedAt, *session.StoppedAt, "", "")
}
duration = strings.Replace(duration, "now", "1 second", 1)
table.Append([]string{
Expand Down

0 comments on commit 3c10578

Please sign in to comment.