-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsearch_in_sg.go
148 lines (135 loc) · 3.56 KB
/
search_in_sg.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
package main
import (
"encoding/json"
"flag"
"fmt"
"log"
"os"
"regexp"
"strings"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/olekukonko/tablewriter"
)
type secGroup struct {
ID string
Name string
Description string
Permissions []*ec2.IpPermission
}
type connParams struct {
Region string
Config string
Section string
Egress bool
}
var (
configPtr = flag.String("config", "", "Allow changing path to the file with AWS credentials")
sectionPtr = flag.String("section", "default", "Which part of AWS credentials to use")
regionPtr = flag.String("region", "us-east-1", "Defines region")
ingressPtr = flag.String("ingress", "", "Specify ingress to find")
egressPtr = flag.Bool("egress", false, "Search Egress rules. Search in Ingress by default")
outputPtr = flag.String("output", "table", "Set output format")
)
func getSecurityGroups(connParams connParams) []secGroup {
var sgList []secGroup
creds := credentials.NewSharedCredentials(connParams.Config, connParams.Section)
_, err := creds.Get()
if err != nil {
log.Fatal(err)
}
svc := ec2.New(session.New(), &aws.Config{
Region: aws.String(*regionPtr),
Credentials: creds,
})
sgIn := &ec2.DescribeSecurityGroupsInput{}
securityGroupsResult, err := svc.DescribeSecurityGroups(sgIn)
if err != nil {
log.Fatal("Error: ", err)
}
for _, sgs := range securityGroupsResult.SecurityGroups {
var perm []*ec2.IpPermission
id := *sgs.GroupId
name := *sgs.GroupName
desc := *sgs.Description
if connParams.Egress {
perm = sgs.IpPermissionsEgress
} else {
perm = sgs.IpPermissions
}
sg := secGroup{
ID: id,
Name: name,
Description: desc,
Permissions: perm,
}
sgList = append(sgList, sg)
}
return sgList
}
func searchSg(sgList []secGroup) [][]string {
var match = regexp.MustCompile(*ingressPtr)
var re = regexp.MustCompile(`\r?\n|\t+|\s+`)
var out [][]string
for _, sgs := range sgList {
for _, perms := range sgs.Permissions {
if match.MatchString(perms.GoString()) {
rules := re.ReplaceAllString(perms.GoString(), " ")
info := []string{sgs.ID, sgs.Name, rules, sgs.Description}
out = append(out, info)
break
}
}
}
return out
}
func compileOutput(fn func([]secGroup) [][]string, sgList []secGroup) {
var data = fn(sgList)
switch *outputPtr {
case "table":
table := tablewriter.NewWriter(os.Stdout)
table.SetHeader([]string{"ID", "Name", "Rule", "Description"})
table.SetAutoMergeCells(true)
table.SetRowLine(true)
table.AppendBulk(data)
table.Render()
case "json":
var jRaw []map[string]string
for _, val := range data {
element := make(map[string]string)
element["ID"] = val[0]
element["Name"] = val[1]
element["Rule"] = val[2]
element["Description"] = val[3]
jRaw = append(jRaw, element)
}
jsonOut, err := json.Marshal(jRaw)
if err != nil {
log.Fatal("Unable to create JSON output.")
}
fmt.Println(string(jsonOut))
case "text":
for _, v := range data {
fmt.Println("\t ID, \t", "\t Name, \t,", "\t Rule, \t", "\t Description \t")
fmt.Println(strings.Join(v, ", "))
}
default:
log.Fatal("Only table, json, and text outputs are supported for now.")
}
}
func main() {
flag.Parse()
if *ingressPtr == "" {
log.Fatal("No search ingress specified")
}
connParams := connParams{
Region: *regionPtr,
Config: *configPtr,
Section: *sectionPtr,
Egress: *egressPtr,
}
sgList := getSecurityGroups(connParams)
compileOutput(searchSg, sgList)
}