/
sgctl.go
139 lines (119 loc) · 3.81 KB
/
sgctl.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
package main
import (
"fmt"
"log"
"os"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/ec2metadata"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/spf13/cobra"
)
var region string
func main() {
var instance string
region = os.Getenv("AWS_REGION")
var cmdAdd = &cobra.Command{
Use: "add <security group>",
Short: "Add one or more security groups",
Long: `Add one or more security groups to an EC2 instance. If the scurity
group is alraedy assigned it will be ignored.`,
Run: func(cmd *cobra.Command, args []string) {
if instance == "" {
region = getRegion()
instance = findInstanceID()
}
var new []*string
for i := range args {
new = append(new, aws.String(args[i]))
}
groups := getSg(instance)
fmt.Printf("Adding %d new security groups to %d existing.\n", len(new), len(groups))
modify(instance, generateSgSlice(groups, new))
},
}
var cmdDelete = &cobra.Command{
Use: "del <security group>",
Short: "Delete one or more security groups from an instance",
Long: `Delete one or more security groups from an instance. In case the
security group is not assigned to the instance it will be ignored.`,
Run: func(cmd *cobra.Command, args []string) {
if instance == "" {
region = getRegion()
instance = findInstanceID()
}
var new []*string
existing := getSg(instance)
fmt.Printf("Removing %d security groups from %d existing.\n", len(args), len(existing))
for i := range args {
for j := range existing {
if *existing[j].GroupId == args[i] {
// remove it
existing = append(existing[:j], existing[j+1:]...)
break
}
}
}
modify(instance, generateSgSlice(existing, new))
},
}
cmdAdd.Flags().StringVarP(&instance, "instance", "i", "", "EC2 instance identifier. If not defined this will be evaluated from the EC2 metadata.")
cmdDelete.Flags().StringVarP(&instance, "instance", "i", "", "EC2 instance identifier. If not defined this will be evaluated from the EC2 metadata.")
var rootCmd = &cobra.Command{Use: "app"}
rootCmd.AddCommand(cmdAdd, cmdDelete)
rootCmd.Execute()
}
// get all security groups from an instance
func getSg(instance string) []*ec2.GroupIdentifier {
svc := ec2.New(session.New(), &aws.Config{Region: aws.String(region)})
params := &ec2.DescribeInstanceAttributeInput{
Attribute: aws.String(ec2.InstanceAttributeNameGroupSet), // Required
InstanceId: aws.String(instance), // Required
DryRun: aws.Bool(false),
}
resp, err := svc.DescribeInstanceAttribute(params)
if err != nil {
// Print the error, cast err to awserr.Error to get the Code and
// Message from an error.
fmt.Println(err.Error())
return nil
}
return resp.Groups
}
// flatten the given array og ec2.GroupIdentifier
func generateSgSlice(existing []*ec2.GroupIdentifier, new []*string) []*string {
var result []*string
for i := range existing {
result = append(result, existing[i].GroupId)
}
return append(new, result...)
}
// set the security groups of an EC2 instance
func modify(instance string, sg []*string) {
svc := ec2.New(session.New(), &aws.Config{Region: aws.String(region)})
params := &ec2.ModifyInstanceAttributeInput{
InstanceId: aws.String(instance),
Groups: sg,
}
if _, err := svc.ModifyInstanceAttribute(params); err != nil {
// Print the error, cast err to awserr.Error to get the Code and
// Message from an error.
log.Fatal(err)
}
}
func findInstanceID() string {
metaClient := ec2metadata.New(session.New(&aws.Config{}))
instanceID, err := metaClient.GetMetadata("instance-id")
if err != nil {
log.Fatal(err)
}
return instanceID
}
func getRegion() string {
metaClient := ec2metadata.New(session.New(&aws.Config{}))
region, err := metaClient.Region()
if err != nil {
log.Fatal(err)
}
return region
}