-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
149 lines (124 loc) · 3.86 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package main
import (
"io/ioutil"
"os"
"path"
"ssh-manager/internal/app"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/secretsmanager"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
"github.com/spf13/viper"
)
const (
// AppDir contains an home dir for an application files
AppDir string = "/var/lib/ssh-manager"
// StateFile contains a filename of a state file
StateFile string = "state.json"
)
func init() {
// logger
log.SetReportCaller(false)
log.SetFormatter(&log.TextFormatter{
ForceColors: false,
FullTimestamp: true,
DisableLevelTruncation: true,
DisableTimestamp: true,
})
log.SetLevel(log.DebugLevel)
log.SetOutput(os.Stdout)
// config
viper.SetConfigName("ssh-manager.yml")
viper.SetConfigType("yml")
viper.AddConfigPath("/root")
if err := viper.ReadInConfig(); err != nil {
log.Fatal(errors.Wrap(err, "error reading configuration file"))
}
if len(viper.GetStringSlice("groups")) == 0 {
log.Fatal("configuration does not contain any groups")
}
if viper.GetString("secret_name") == "" {
log.Fatal("configuration does not contain an aws secret name")
}
// state
_, err := os.Stat(AppDir)
if os.IsNotExist(err) {
if err := os.MkdirAll(AppDir, 0777); err != nil {
log.Fatal(errors.Wrap(err, "error creating application directory"))
}
} else if err != nil {
log.Fatal(errors.Wrap(err, "error validating application directory"))
}
_, err = os.Stat(path.Join(AppDir, StateFile))
if os.IsNotExist(err) {
if err = ioutil.WriteFile(path.Join(AppDir, StateFile), []byte("{}"), 0666); err != nil {
log.Fatal(errors.Wrap(err, "error creating state file"))
}
} else if err != nil {
log.Fatal(errors.Wrap(err, "error validating state file"))
}
}
func main() {
log.Infof("ssh-manager v%v started", app.Version)
// validate groups
log.Info("validating users group")
if err := app.ValidateUsersGroup(); err != nil {
log.Fatal(err)
}
log.Info("validating sudoers group")
if err := app.ValidateSudoersGroup(); err != nil {
log.Fatal(err)
}
log.Info("validating sudoers group permission")
if err := app.ValidateSudoersPermissions(); err != nil {
log.Fatal(err)
}
state, err := app.LoadState(path.Join(AppDir, StateFile))
if err != nil {
log.Fatal(errors.Wrap(err, "error loading state"))
}
log.Info("configured server groups: ", app.SliceToString(viper.GetStringSlice("groups")))
// get members
region := viper.GetString("region")
if region == "" {
region = "us-east-1"
}
secretsManager := secretsmanager.New(session.Must(session.NewSession(&aws.Config{
Region: ®ion,
})))
log.Info("fetching remote configuration")
conf, err := app.GetConfig(secretsManager, viper.GetString("secret_name"))
if err != nil {
log.Fatal(errors.Wrap(err, "error fetching remote configuration"))
}
// warn about staled groups
for _, group := range viper.GetStringSlice("groups") {
if _, val := conf.ServerGroups[group]; !val {
log.Warnf("group %s does not exists on remote configuration", group)
}
}
// get unique members
users := conf.GetUsers(viper.GetStringSlice("groups"))
listOfUsers := []string{}
for username := range users {
listOfUsers = append(listOfUsers, username)
}
log.Info("configured users: ", app.SliceToString(listOfUsers))
sudoers := conf.GetSudoers(viper.GetStringSlice("groups"))
listOfSudoers := []string{}
for username := range sudoers {
listOfSudoers = append(listOfSudoers, username)
}
log.Info("configured sudoers: ", app.SliceToString(listOfSudoers))
// configure users
state.UsersLoop(users)
state.SudoersLoop(sudoers, listOfUsers)
state.DeleteUsers(listOfUsers, listOfSudoers)
// save state
state.Update(listOfUsers, listOfSudoers)
if err := state.Save(path.Join(AppDir, StateFile)); err != nil {
log.Fatal(errors.Wrap(err, "error saving the state"))
}
log.Info("ssh-manager finished")
}