Skip to content

Commit

Permalink
Merge pull request #6 from Sjeanpierre/multiple_aws_account_support
Browse files Browse the repository at this point in the history
Multiple aws account support
  • Loading branch information
Stevenson Jean-Pierre authored Aug 4, 2016
2 parents 2dd8b6f + 127df50 commit 8fbef02
Show file tree
Hide file tree
Showing 4 changed files with 173 additions and 37 deletions.
118 changes: 118 additions & 0 deletions aws_profile.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package main

import (
"github.com/go-ini/ini"
"fmt"
"log"
"io/ioutil"
"encoding/json"
"os"
"path"
)

var (
awsProfileNamesPath = path.Join(resourcePath, "aws_profile_names.json")
awsCredentialFilePath = path.Join(os.Getenv("HOME"), ".aws", "credentials")
)

func existingProfiles() bool {
if _, err := os.Stat(awsProfileNamesPath); os.IsNotExist(err) {
return false
}
return true
}

func awsProfiles() []string {
if existingProfiles() {
profiles, err := readAWSProfileFile()
if err != nil {
fmt.Printf("Error: %s", err)
}
return profiles
}
userQuestion := fmt.Sprint("Use AWS profiles? [y/n]:")
if confirmUserSelection(userQuestion) {
setupProfiles()
profiles, err := readAWSProfileFile()
if err != nil {
fmt.Printf("Error: %s", err)
}
return profiles
}
return []string{"default"}
}

func writeAWSProfileFile(profileNames []string) {
profileNamesJSON, err := json.Marshal(profileNames)
if err != nil {
fmt.Println(err)
return
}
writeError := ioutil.WriteFile(awsProfileNamesPath, profileNamesJSON, 0755)
if writeError != nil {
fmt.Print("Could not write AWS profile names to config file\n")
log.Fatal(writeError)
}
}

func readAWSProfileFile() ([]string, error) {
file, e := ioutil.ReadFile(awsProfileNamesPath)
if e != nil {
if noSuchFileErrRegexp.MatchString(e.Error()) {
return []string{}, e
}
fmt.Printf("Could not: %v\n", e.Error())
os.Exit(1)
}
var awsProfiles []string
json.Unmarshal(file, &awsProfiles)
return awsProfiles, nil
}

func detail4Capture(attr string) string {
var response string
fmt.Printf("%s ", attr)
_, err := fmt.Scanln(&response)
if err != nil {
if err.Error() == "unexpected newline" {
return ""
}
log.Fatal(err)
}
return response
}

func confirmUserSelection(userPrompt string) bool {
var returnVar bool
confirmation := detail4Capture(userPrompt)
switch confirmation {
case "y":
returnVar = true
case "n":
returnVar = false
default:
confirmUserSelection(userPrompt)
}
return returnVar
}

func setupProfiles() {
fmt.Println("Discovering AWS profile names from credentials file\n")
cfg, err := ini.Load(awsCredentialFilePath)
if err != nil {
fmt.Printf("error reading AWS credential file: %s", err)
}
sections := cfg.SectionStrings()
fmt.Println("Please select profiles AWS profiles to include\n")
var addedProfiles []string
for _, section := range sections {
if section == ini.DEFAULT_SECTION {
continue
}
userQuestion := fmt.Sprintf("Include profile [%s]? [y/n]:", section)
if confirmUserSelection(userQuestion) {
addedProfiles = append(addedProfiles, section)
}
}
writeAWSProfileFile(addedProfiles)
}
1 change: 0 additions & 1 deletion vpn_connection.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package main

//todo use keychain to store psks instead of plaintext config file
//todo write out IP-up template with all host for routing instead of using route command

import (
"os/exec"
Expand Down
66 changes: 41 additions & 25 deletions vpn_host_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@ import (
"os"
"strconv"
"sort"
"github.com/aws/aws-sdk-go/aws/credentials"
)

var awsRegions = []string{"us-east-1", "us-west-1", "us-west-2", "eu-west-1", "eu-central-1", "sa-east-1"}
var hostFilePath = path.Join(resourcePath, "vpn_hosts.json")
var vpnInstanceFieldNames = []string{"ID#", "VPC ID", "VPN Name", "Environment", "Public IP", "VPC CIDR"}
var vpnInstanceFieldNames = []string{"ID #", "VPC ID", "VPN Name", "Environment", "Public IP", "VPC CIDR"}

type vpnInstance struct {
VpcID string `json:"vpc_id"`
Expand All @@ -30,11 +31,16 @@ type vpnInstance struct {
}
type vpnInstanceGrp []vpnInstance

func listVPCs() map[string]string {

func listVPCs(profile string) map[string]string {
vpcList := make(map[string]string)
for _, region := range awsRegions {
fmt.Printf("fetching vpc details for region: %v\n", region)
svc := ec2.New(session.New(&aws.Config{Region: aws.String(region)}))
svc := ec2.New(session.New(&aws.Config{Region: aws.String(region),
Credentials: credentials.NewCredentials(&credentials.SharedCredentialsProvider{
Profile: profile,
}),
}))
params := &ec2.DescribeVpcsInput{}
resp, err := svc.DescribeVpcs(params)
if err != nil {
Expand All @@ -51,23 +57,14 @@ func listVPCs() map[string]string {
return vpcList
}

func (slice vpnInstanceGrp) Len() int {
return len(slice)
}

func (slice vpnInstanceGrp) Less(i, j int) bool {
return slice[i].Name < slice[j].Name;
}

func (slice vpnInstanceGrp) Swap(i, j int) {
slice[i], slice[j] = slice[j], slice[i]
}


func listFilteredInstances(nameFilter string) []*ec2.Instance {
func listFilteredInstances(nameFilter string,profile string) []*ec2.Instance {
var filteredInstances []*ec2.Instance
for _, region := range awsRegions {
svc := ec2.New(session.New(&aws.Config{Region: aws.String(region)}))
svc := ec2.New(session.New(&aws.Config{Region: aws.String(region),
Credentials: credentials.NewCredentials(&credentials.SharedCredentialsProvider{
Profile: profile,
}),
}))
fmt.Printf("fetching instances with tag %v in: %v\n", nameFilter, region)
params := &ec2.DescribeInstancesInput{
Filters: []*ec2.Filter{
Expand Down Expand Up @@ -104,9 +101,9 @@ func extractTagValue(tagList []*ec2.Tag, lookup string) string {
return tagVale
}

func listVpnInstnaces(vpcCidrs map[string]string) vpnInstanceGrp {
func listVpnInstnaces(vpcCidrs map[string]string,profile string) vpnInstanceGrp {
var vpnInstances vpnInstanceGrp
vpnInstanceList := listFilteredInstances("vpn")
vpnInstanceList := listFilteredInstances("vpn",profile)
for _, instance := range vpnInstanceList {
vpn := vpnInstance{
VpcID: *instance.VpcId,
Expand Down Expand Up @@ -135,11 +132,18 @@ func writevpnDetailFile(vpnList vpnInstanceGrp) {
}

func refreshHosts() {
print("refreshing hosts")
vpcList := listVPCs()
vpn := listVpnInstnaces(vpcList)
writevpnDetailFile(vpn)
print("complete")
awsProfiles := awsProfiles()
var vpnHostList vpnInstanceGrp
for _,awsProfile := range awsProfiles {
fmt.Printf("Refreshing hosts list for profile: %s\n",awsProfile)
vpcList := listVPCs(awsProfile)
vpn := listVpnInstnaces(vpcList,awsProfile)
//todo, add profile to instances. create function to do so
vpnHostList = append(vpnHostList,vpn...)
fmt.Println("======")
}
writevpnDetailFile(vpnHostList)
fmt.Println("complete\n")
}

func readHostsJSONFile() vpnInstanceGrp {
Expand Down Expand Up @@ -171,3 +175,15 @@ func printVPNHostList() {
}
consoleTable.Render()
}

func (slice vpnInstanceGrp) Len() int {
return len(slice)
}

func (slice vpnInstanceGrp) Less(i, j int) bool {
return slice[i].Name < slice[j].Name;
}

func (slice vpnInstanceGrp) Swap(i, j int) {
slice[i], slice[j] = slice[j], slice[i]
}
25 changes: 14 additions & 11 deletions vpn_profile.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package main

//todo allow for setting default profiles

import (
"io/ioutil"
"fmt"
Expand All @@ -15,7 +13,7 @@ import (
)

var (
vpnProfileFields = []string{"ID#", "Name", "Username"}
vpnProfileFields = []string{"ID #", "Name", "Username"}
vpnProfileFilePath = path.Join(resourcePath, "vpn_profiles.json")
noSuchFileErrRegexp = regexp.MustCompile(`no such file or directory`)
)
Expand Down Expand Up @@ -53,7 +51,7 @@ func writeProfileFile(profileList []vpnProfile) {
fmt.Print("Could not write profile file\n")
log.Fatal(writeError)
}
fmt.Println("New profile saved!")
fmt.Println("New profile saved!\n")
}

func printVPNProfileList() {
Expand Down Expand Up @@ -107,18 +105,18 @@ func detailCapture(attr string) string {
return response
}

func confirm(username string, password string, psk string) bool {
var returnvar bool
func confirm() bool {
var returnVar bool
confirmation := detailCapture("Save Profile? [y/n]:")
switch confirmation {
case "y":
returnvar = true
returnVar = true
case "n":
main()
default:
confirm(username, password, psk)
confirm()
}
return returnvar
return returnVar
}

func addProfile(profileName string) {
Expand All @@ -128,9 +126,14 @@ func addProfile(profileName string) {
username := detailCapture("USERNAME:")
password := detailCapture("PASSWORD:")
psk := detailCapture("PSK:")
if confirm(username, password, psk) {
if confirm() {
var updated = []vpnProfile{}
updated = append(vpnProfiles, vpnProfile{Name:profileName, UserName:username, PassWord:password, Psk:psk})
updated = append(vpnProfiles,
vpnProfile{Name:profileName,
UserName:username,
PassWord:password,
Psk:psk,
})
writeProfileFile(updated)
}
}
Expand Down

0 comments on commit 8fbef02

Please sign in to comment.