diff options
author | Mike Crute <mcrute@gmail.com> | 2017-06-30 03:17:00 +0000 |
---|---|---|
committer | Mike Crute <mcrute@gmail.com> | 2017-06-30 03:19:07 +0000 |
commit | 6688238bd28fdc596d8bc4a2e9707702dceb1db2 (patch) | |
tree | 02586abf42d9ca5bf26dae52f415ab2a73957248 | |
parent | 75c8945bc92a4c055887c7c5b29563e27ae6ac0f (diff) | |
download | mmds-6688238bd28fdc596d8bc4a2e9707702dceb1db2.tar.bz2 mmds-6688238bd28fdc596d8bc4a2e9707702dceb1db2.tar.xz mmds-6688238bd28fdc596d8bc4a2e9707702dceb1db2.zip |
-rw-r--r-- | main.go | 44 |
1 files changed, 41 insertions, 3 deletions
@@ -9,6 +9,7 @@ import ( | |||
9 | "errors" | 9 | "errors" |
10 | "flag" | 10 | "flag" |
11 | "fmt" | 11 | "fmt" |
12 | "io" | ||
12 | "io/ioutil" | 13 | "io/ioutil" |
13 | "net" | 14 | "net" |
14 | "net/http" | 15 | "net/http" |
@@ -29,6 +30,17 @@ var ( | |||
29 | DEFAULT_VALUES map[string]*string | 30 | DEFAULT_VALUES map[string]*string |
30 | ) | 31 | ) |
31 | 32 | ||
33 | const ( | ||
34 | METADATA_FILE = "/etc/mmds/bootstrap-cred.json" | ||
35 | ) | ||
36 | |||
37 | type FileLike interface { | ||
38 | io.Reader | ||
39 | io.Writer | ||
40 | io.Seeker | ||
41 | Truncate(int64) error | ||
42 | } | ||
43 | |||
32 | func init() { | 44 | func init() { |
33 | DEFAULT_VALUES = map[string]*string{ | 45 | DEFAULT_VALUES = map[string]*string{ |
34 | "domain": StringPtr("amazonaws.com"), | 46 | "domain": StringPtr("amazonaws.com"), |
@@ -60,6 +72,7 @@ type appContext struct { | |||
60 | RoleARN *string | 72 | RoleARN *string |
61 | BootstrapSecret *string | 73 | BootstrapSecret *string |
62 | CredentialHandler CredentialHandler | 74 | CredentialHandler CredentialHandler |
75 | CredentialFile FileLike | ||
63 | } | 76 | } |
64 | 77 | ||
65 | func (c *appContext) FormatAZ() string { | 78 | func (c *appContext) FormatAZ() string { |
@@ -139,6 +152,7 @@ func BootstrapCredentialHandler(w http.ResponseWriter, r *http.Request) { | |||
139 | if err != nil { | 152 | if err != nil { |
140 | jww.ERROR.Printf("Error decoding bootstrap JSON: %s", err) | 153 | jww.ERROR.Printf("Error decoding bootstrap JSON: %s", err) |
141 | http.Error(w, err.Error(), http.StatusInternalServerError) | 154 | http.Error(w, err.Error(), http.StatusInternalServerError) |
155 | return | ||
142 | } | 156 | } |
143 | 157 | ||
144 | if !validateSignature(&cred, ctx.BootstrapSecret) { | 158 | if !validateSignature(&cred, ctx.BootstrapSecret) { |
@@ -149,6 +163,19 @@ func BootstrapCredentialHandler(w http.ResponseWriter, r *http.Request) { | |||
149 | 163 | ||
150 | creds := credentials.NewStaticCredentials(cred.AccessKeyId, cred.SecretAccessKey, cred.Token) | 164 | creds := credentials.NewStaticCredentials(cred.AccessKeyId, cred.SecretAccessKey, cred.Token) |
151 | ctx.CredentialHandler.SetBootstrapCredential(creds) | 165 | ctx.CredentialHandler.SetBootstrapCredential(creds) |
166 | |||
167 | jd, err := json.MarshalIndent(cred, "", " ") | ||
168 | if err != nil { | ||
169 | jww.ERROR.Printf("Unable to marshal credential for writing to file") | ||
170 | http.Error(w, err.Error(), http.StatusInternalServerError) | ||
171 | return | ||
172 | } | ||
173 | |||
174 | // Truncate credential file and update with new credentials | ||
175 | // TODO: Should validate the the credentials worked first | ||
176 | ctx.CredentialFile.Seek(0, 0) | ||
177 | ctx.CredentialFile.Truncate(0) | ||
178 | ctx.CredentialFile.Write(jd) | ||
152 | } | 179 | } |
153 | 180 | ||
154 | func IAMInfoHandler(w http.ResponseWriter, r *http.Request) { | 181 | func IAMInfoHandler(w http.ResponseWriter, r *http.Request) { |
@@ -295,8 +322,8 @@ func parseArgs() (*UserArgs, error) { | |||
295 | return a, nil | 322 | return a, nil |
296 | } | 323 | } |
297 | 324 | ||
298 | func initialBootstrap(file string, handler CredentialHandler) { | 325 | func initialBootstrap(file FileLike, handler CredentialHandler) { |
299 | bd, err := ioutil.ReadFile(file) | 326 | bd, err := ioutil.ReadAll(file) |
300 | if err != nil { | 327 | if err != nil { |
301 | jww.ERROR.Printf("Error reading bootstrap file: %s", err.Error()) | 328 | jww.ERROR.Printf("Error reading bootstrap file: %s", err.Error()) |
302 | return | 329 | return |
@@ -330,6 +357,16 @@ func main() { | |||
330 | return | 357 | return |
331 | } | 358 | } |
332 | 359 | ||
360 | // Open this before dropping privileges because only root can update the | ||
361 | // file but the service may need to update it at some future point if a new | ||
362 | // credential is provided. | ||
363 | credfile, err := os.OpenFile(METADATA_FILE, os.O_RDWR, 0600) | ||
364 | if err != nil { | ||
365 | jww.FATAL.Printf("Unable to open bootstrap credential file") | ||
366 | return | ||
367 | } | ||
368 | defer credfile.Close() | ||
369 | |||
333 | if err := drop.DropPrivileges(args.User); err != nil { | 370 | if err := drop.DropPrivileges(args.User); err != nil { |
334 | jww.FATAL.Printf("Unable to drop privileges") | 371 | jww.FATAL.Printf("Unable to drop privileges") |
335 | return | 372 | return |
@@ -362,9 +399,10 @@ func main() { | |||
362 | RoleARN: &args.RoleARN, | 399 | RoleARN: &args.RoleARN, |
363 | BootstrapSecret: &args.BootstrapSecret, | 400 | BootstrapSecret: &args.BootstrapSecret, |
364 | CredentialHandler: credHandler, | 401 | CredentialHandler: credHandler, |
402 | CredentialFile: credfile, | ||
365 | } | 403 | } |
366 | 404 | ||
367 | initialBootstrap("/etc/mmds/bootstrap-cred.json", credHandler) | 405 | initialBootstrap(credfile, credHandler) |
368 | 406 | ||
369 | go credHandler.Start() | 407 | go credHandler.Start() |
370 | go http.ListenAndServe(":8000", buildAdminHandler(ctx)) | 408 | go http.ListenAndServe(":8000", buildAdminHandler(ctx)) |