Skip to content

Commit

Permalink
Bugfixes, code cleanup and added check of AWS environment
Browse files Browse the repository at this point in the history
  • Loading branch information
otm committed Feb 21, 2016
1 parent e93a1f7 commit 183e883
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 19 deletions.
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ mv limes.conf.example config

Use your favorite text editor to update the configuration file



## Security
The service should be configured on the loop back device, and only accessible from the host it is running on.

Expand Down
18 changes: 13 additions & 5 deletions cli-client.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func StartService(args *Start) {
log.Fatalf("Could not read from config file. The error was: %s\n", configErr.Error())
}

configParseErr := yaml.Unmarshal(configContents, config.profiles)
configParseErr := yaml.Unmarshal(configContents, &config.profiles)
if configParseErr != nil {
log.Fatalf("Error in parsing config file: %s\n", configParseErr.Error())
}
Expand All @@ -68,7 +68,7 @@ func StartService(args *Start) {

defer func() {
log.Debug("Removing UNIX socket.\n")
os.Remove("./ims.sock")
os.Remove(args.Adress)
}()

// Startup the HTTP server and respond to requests.
Expand All @@ -93,7 +93,7 @@ func StartService(args *Start) {
mds.Start()

stop := make(chan struct{})
agentServer := NewCliHandler("./ims.sock", credsManager, stop)
agentServer := NewCliHandler(args.Adress, credsManager, stop)
err = agentServer.Start()
if err != nil {
log.Fatalf("Could not start agentServer: %s\n", err.Error())
Expand Down Expand Up @@ -150,15 +150,23 @@ func (c *cliClient) status(args *Status) error {
Expiration: "n/a",
}
status = "down"
defer fmt.Fprintf(os.Stderr, "communication error: %v\n", err)
defer fmt.Fprintf(os.Stderr, "\ncommunication error: %v\n", err)
}

if r.Error != "" {
status = "error"
defer fmt.Fprintf(os.Stderr, "error retrieving status: %v\n", r.Error)
defer fmt.Fprintf(os.Stderr, "\nerror retrieving status: %v\n", r.Error)
}

env := "ok"
errConf := checkActiveAWSConfig()
if errConf != nil {
env = "nok"
defer fmt.Fprintf(os.Stderr, "\nwarning: %v\n", errConf)
}

fmt.Printf("Server: %v\n", status)
fmt.Printf("AWS Config: %v\n", env)
fmt.Printf("Role: %v\n", r.Role)

if args.Verbose == false {
Expand Down
86 changes: 86 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
package main

import (
"fmt"
"os"
"os/user"
"path/filepath"
)

// Config hold configuration read from the configuration file
type Config struct {
profiles Profiles
Expand Down Expand Up @@ -28,3 +35,82 @@ type Profile struct {
SourceProfile string `yaml:"source_profile"`
RoleSessionName string `yaml:"role_session_name"`
}

const (
awsConfDir = ".aws"
awsConfigFile = "config"
awsCredentialsFile = "credentials"
awsAccessKeyEnv = "AWS_ACCESS_KEY_ID"
awsSecretKeyEnv = "AWS_SECRET_ACCESS_KEY"
)

var (
errActiveAWSEnvironment = fmt.Errorf("active AWS environment variables")
errActiveAWSCredentialsFile = fmt.Errorf("active AWS credentials file")
errActiveAWSConfigFile = fmt.Errorf("active AWS config file")
)

func checkActiveAWSConfig() (err error) {
var active bool

if active, err = doCheck(activeAWSEnvironment, err); active {
return errActiveAWSEnvironment
}

if active, err = doCheck(activeAWSCredentialsFile, err); active {
return errActiveAWSCredentialsFile
}

if active, err = doCheck(activeAWSConfigFile, err); active {
return errActiveAWSConfigFile
}

return fmt.Errorf("checkActiveAWSConfig: %v", err)
}

func doCheck(fn func() (bool, error), err error) (bool, error) {
if err != nil {
return false, err
}

return fn()
}

func activeAWSConfigFile() (active bool, err error) {
usr, err := user.Current()
if err != nil {
return false, fmt.Errorf("unable to fetch user information: %v", err)
}

if _, err := os.Stat(filepath.Join(usr.HomeDir, awsConfDir, awsConfigFile)); os.IsNotExist(err) {
return false, nil
}

return true, nil
}

func activeAWSCredentialsFile() (active bool, err error) {
usr, err := user.Current()
if err != nil {
return false, err
}

if _, err := os.Stat(filepath.Join(usr.HomeDir, awsConfDir, awsCredentialsFile)); os.IsNotExist(err) {
return false, nil
}

return true, nil
}

func activeAWSEnvironment() (active bool, err error) {
if env := os.Getenv(awsAccessKeyEnv); env != "" {
return true, nil
}

if env := os.Getenv(awsSecretKeyEnv); env != "" {
return true, nil
}

return false, nil

}
6 changes: 5 additions & 1 deletion credentials-manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,10 @@ func NewCredentialsExpirationManager(conf Config, mfa string) *CredentialsExpira
log.Fatalf("MFA needed")
}

params := &sts.GetSessionTokenInput{}
params := &sts.GetSessionTokenInput{
DurationSeconds: aws.Int64(10 * 3600),
}

if defaultProfile.MFASerial != "" {
params.SerialNumber = aws.String(defaultProfile.MFASerial)
}
Expand Down Expand Up @@ -142,6 +145,7 @@ func (m *CredentialsExpirationManager) RetrieveRoleARN(RoleARN, MFASerial, MFA s
}

ari := &sts.AssumeRoleInput{
DurationSeconds: aws.Int64(1800),
RoleArn: &RoleARN,
RoleSessionName: &m.roleSessionName,
}
Expand Down
59 changes: 48 additions & 11 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@ package main

import (
"errors"
"log"
"os"
"os/user"
"path/filepath"

"github.com/bobziuchkovski/writ"
)

const (
configFilePath = "~/.ims/ims.conf"
domainSocketPath = "~/.ims/ims.sock"
configFilePath = ".limes/config"
domainSocketPath = ".limes/socket"
)

//go:generate protoc -I proto/ proto/ims.proto --go_out=plugins=grpc:proto
Expand All @@ -27,30 +30,30 @@ type IMS struct {
type Start struct {
HelpFlag bool `flag:"h, help" description:"START Display this message and exit"`
MFA string `option:"m, mfa" description:"MFA token to start up server"`
ConfigFile string `option:"c, config" default:"./ims.conf" description:"configuration file"`
Adress string `option:"adress" default:"./ims.sock" description:"configuration file"`
ConfigFile string `option:"c, config" default:"" description:"configuration file"`
Adress string `option:"adress" default:"" description:"addess to local socket communication"`
}

// Stop defines the "stop" command cli flags and options
type Stop struct {
HelpFlag bool `flag:"h, help" description:"STOP Display this message and exit"`
ConfigFile string `option:"c, config" default:"./ims.conf" description:"configuration file"`
Adress string `option:"adress" default:"./ims.sock" description:"configuration file"`
ConfigFile string `option:"c, config" default:"" description:"configuration file"`
Adress string `option:"adress" default:"" description:"configuration file"`
}

// Status defines the "status" command cli flags and options
type Status struct {
HelpFlag bool `flag:"h, help" description:"STATUS Display this message and exit"`
ConfigFile string `option:"c, config" default:"./ims.conf" description:"configuration file"`
Adress string `option:"adress" default:"./ims.sock" description:"configuration file"`
ConfigFile string `option:"c, config" default:"" description:"configuration file"`
Adress string `option:"adress" default:"" description:"configuration file"`
Verbose bool `flag:"v, verbose" description:"enables verbose output"`
}

// SwitchProfile defines the "profile" command cli flags and options
type SwitchProfile struct {
HelpFlag bool `flag:"h, help" description:"SwitchProfile Display this message and exit"`
ConfigFile string `option:"c, config" default:"./ims.conf" description:"configuration file"`
Adress string `option:"adress" default:"./ims.sock" description:"configuration file"`
ConfigFile string `option:"c, config" default:"" description:"configuration file"`
Adress string `option:"adress" default:"" description:"configuration file"`
}

// RunCmd defines the "run" command cli flags ands options
Expand All @@ -72,6 +75,8 @@ func (l *Start) Run(p writ.Path, positional []string) {
p.Last().ExitHelp(nil)
}

l.ConfigFile = setDefaultConfigPath(l.ConfigFile)
l.Adress = setDefaultSocketAdress(l.Adress)
StartService(l)
}

Expand All @@ -81,6 +86,8 @@ func (l *Stop) Run(p writ.Path, positional []string) {
p.Last().ExitHelp(nil)
}

l.ConfigFile = setDefaultConfigPath(l.ConfigFile)
l.Adress = setDefaultSocketAdress(l.Adress)
rpc := newCliClient(l.Adress)
defer rpc.close()
rpc.stop(l)
Expand All @@ -92,6 +99,8 @@ func (l *Status) Run(p writ.Path, positional []string) {
p.Last().ExitHelp(nil)
}

l.ConfigFile = setDefaultConfigPath(l.ConfigFile)
l.Adress = setDefaultSocketAdress(l.Adress)
rpc := newCliClient(l.Adress)
defer rpc.close()
rpc.status(l)
Expand All @@ -107,6 +116,8 @@ func (l *SwitchProfile) Run(p writ.Path, positional []string) {
p.Last().ExitHelp(errors.New("profile name is required"))
}

l.ConfigFile = setDefaultConfigPath(l.ConfigFile)
l.Adress = setDefaultSocketAdress(l.Adress)
rpc := newCliClient(l.Adress)
defer rpc.close()
rpc.assumeRole(positional[0], l)
Expand All @@ -121,6 +132,32 @@ func (l *SwitchProfile) Run(p writ.Path, positional []string) {
// fmt.Printf("Run is not implemented")
// }

func setDefaultSocketAdress(adress string) string {
if adress != "" {
return adress
}

usr, err := user.Current()
if err != nil {
log.Fatalf("unable to extract user information: %v", err)
}

return filepath.Join(usr.HomeDir, domainSocketPath)
}

func setDefaultConfigPath(path string) string {
if path != "" {
return path
}

usr, err := user.Current()
if err != nil {
log.Fatalf("unable to extract user information: %v", err)
}

return filepath.Join(usr.HomeDir, configFilePath)
}

func main() {
ims := &IMS{}
cmd := writ.New("ims", ims)
Expand Down Expand Up @@ -149,7 +186,7 @@ func main() {
// case "ims run":
// ims.RunCmd.Run(path, positional)
default:
panic("BUG: Someone added a new command and forgot to add it's path here")
log.Fatalf("bug: sub command has not been setup: %v", path.String())
}

}

0 comments on commit 183e883

Please sign in to comment.