Skip to content

Commit

Permalink
Initial version
Browse files Browse the repository at this point in the history
  • Loading branch information
luizm committed Apr 24, 2020
1 parent 933cb8c commit 72f19ad
Show file tree
Hide file tree
Showing 6 changed files with 152 additions and 41 deletions.
27 changes: 27 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: goreleaser
on:
push:
branches:
- "!*"
tags:
- "v*.*.*"
jobs:
build:
name: goreleser
runs-on: ubuntu-latest
steps:
- name: Set up Go 1.14
uses: actions/setup-go@v1
with:
go-version: 1.14
id: go
- name: Check out code into the Go module directory
uses: actions/checkout@v1
with:
fetch-depth: 1
- name: Run goreleaser
uses: goreleaser/goreleaser-action@master
with:
args: release
env:
GITHUB_TOKEN: ${{ secrets.CUSTOM_GITHUB_TOKEN }}
10 changes: 10 additions & 0 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
brews:
- name: aws-whois
github:
owner: luizm
name: homebrew-tap
homepage: https://github.com/luizm/aws-whois
description: CLI to find which aws resource are using a specific IP
folder: Formula
test: |
system "#{bin}/aws-whois -h"
60 changes: 43 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,31 +1,57 @@
# aws-whois
## Description

WIP - Just for fun
If you have a lot of accounts, this is a simple way to check which resource on AWS are using a specific public or private IP.

`aws-whois --profile example --ip 172.20.202.101`
## Install

```sh
$ brew install luizm/tap/aws-whois
```

Or download the binary from [github releases](https://github.com/luizm/aws-whois/releases)

## Usage

`$ aws-whois --profile example --ip 172.20.X.X`

```log
{
"OwnerId": "xxxxxxxx",
"Description": "Interface for NAT Gateway nat-xxxxxxxxxxxx",
"InterfaceType": "nat_gateway",
"AvailabilityZone": "us-east-1c"
"Profile": "example",
"ENI": {
"OwnerId": "xxxxxx",
"Description": "Interface for NAT Gateway nat-xxxxxx",
"InterfaceType": "nat_gateway",
"AvailabilityZone": "us-east-1c",
}
"EC2Associated": null
}
```

`aws-whois --profile example --ip 172.20.202.10`
`$ aws-whois --profile example --profile example2 --ip 54.X.X.X`

```log
{
"OwnerId": "xxxxxxxx",
"VpcId": "vpc-xxxxxxxx",
"InstanceId": "i-xxxxxxxxxx",
"InstanceType": "t3.micro",
"Tags": [
{
"Key": "Name",
"Value": "instance-example.local"
"Profile": "example",
"Message": "ip 54.X.X.X not found"
}
{
"Profile": "example2",
"ENI": {
"OwnerId": "xxxxxx",
"Description": "Primary network interface",
"InterfaceType": "interface",
"AvailabilityZone": "us-east-1a",
"EC2Associated": {
"VpcId": "vpc-xxxxxx",
"InstanceId": "i-xxxxxx",
"InstanceType": "t3.micro",
"Tags": [
{
"Key": "Name",
"Value": "example.local"
}
]
}
}
]
}
```
12 changes: 7 additions & 5 deletions cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func Execute() {
DefaultText: "us-east-1",
Required: false,
},
&cli.StringFlag{
&cli.StringSliceFlag{
Name: "profile",
Aliases: []string{"p"},
Usage: "Use a specific profile from your credential file",
Expand All @@ -33,11 +33,13 @@ func Execute() {
},
},
Action: func(c *cli.Context) error {
result, err := whois.Find(c.String("profile"), c.String("region"), c.String("ip"))
if err != nil {
return err
for _, p := range c.StringSlice("profile") {
result, err := whois.FindIP(p, c.String("region"), c.String("ip"))
if err != nil {
return err
}
fmt.Println(string(result))
}
fmt.Println(string(result))
return nil
},
}
Expand Down
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/aws/aws-sdk-go v1.30.7 h1:IaXfqtioP6p9SFAnNfsqdNczbR5UNbYqvcZUSsCAdTY=
github.com/aws/aws-sdk-go v1.30.7/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
Expand Down
83 changes: 64 additions & 19 deletions pkg/whois.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,55 @@ package whois

import (
"encoding/json"
"errors"
"fmt"
"net"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/ec2"
)

type Result struct {
Profile string `json:"Profile"`
ENI *DefaultOutput
}

type ResultNotFond struct {
Profile string `json:"Profile"`
Message string
}

type DefaultOutput struct {
OwnerId *string `json:"OwnerId"`
Description *string `json:"Description"`
InterfaceType *string `json:"InterfaceType"`
AvailabilityZone *string `json:"AvailabilityZone"`
EC2Associated *EC2Output
}

type EC2Output struct {
OwnerId *string `json:"OwnerId"`
VpcId *string `json:"VpcId"`
InstanceId *string `json:"InstanceId"`
InstanceType *string `json:"InstanceType"`
Tags []*ec2.Tag `json:"Tags"`
}

func describeInstace(sess *session.Session, i *string) (*EC2Output, error) {
func isPrivateIP(ip string) (bool, error) {
private := false
IP := net.ParseIP(ip)
if IP == nil {
return false, errors.New("invalid IP address")
}
_, prefix08, _ := net.ParseCIDR("10.0.0.0/8")
_, prefix12, _ := net.ParseCIDR("172.16.0.0/12")
_, prefix16, _ := net.ParseCIDR("192.168.0.0/16")
private = prefix08.Contains(IP) || prefix12.Contains(IP) || prefix16.Contains(IP)

return private, nil
}

func getInstanceInfo(sess *session.Session, i *string) (*EC2Output, error) {

svc := ec2.New(sess)

Expand All @@ -36,7 +62,6 @@ func describeInstace(sess *session.Session, i *string) (*EC2Output, error) {
}

return &EC2Output{
OwnerId: result.Reservations[0].OwnerId,
VpcId: result.Reservations[0].Instances[0].VpcId,
InstanceId: result.Reservations[0].Instances[0].InstanceId,
InstanceType: result.Reservations[0].Instances[0].InstanceType,
Expand All @@ -58,13 +83,23 @@ func newSession(profile, region string) (*session.Session, error) {
return sess, err
}

func describeNetworkInterface(sess *session.Session, ip string) (*ec2.DescribeNetworkInterfacesOutput, error) {
func getInterfaceInfo(sess *session.Session, ip string) (*ec2.DescribeNetworkInterfacesOutput, error) {
svc := ec2.New(sess)
filter := "association.public-ip"

isPrivate, err := isPrivateIP(ip)
if err != nil {
return nil, err
}

if isPrivate {
filter = "private-ip-address"
}

input := &ec2.DescribeNetworkInterfacesInput{
Filters: []*ec2.Filter{
{
Name: aws.String("private-ip-address"),
Name: aws.String(filter),
Values: []*string{
aws.String(ip),
},
Expand All @@ -79,36 +114,46 @@ func describeNetworkInterface(sess *session.Session, ip string) (*ec2.DescribeNe
return result, nil
}

func Find(profile, region, ip string) ([]byte, error) {
func FindIP(profile, region, ip string) ([]byte, error) {
var e *EC2Output

sess, err := newSession(profile, region)
if err != nil {
return nil, err
}

result, err := describeNetworkInterface(sess, ip)
result, err := getInterfaceInfo(sess, ip)
if err != nil {
return nil, err
}
if result.NetworkInterfaces == nil {
return []byte(fmt.Sprintf("Check in the %v profile, ip %v not found", profile, ip)), nil
}

instanceID := result.NetworkInterfaces[0].Attachment.InstanceId
if instanceID != nil {
r, _ := describeInstace(sess, instanceID)
b, err := json.MarshalIndent(r, " ", " ")
r := &ResultNotFond{
Profile: profile,
Message: fmt.Sprintf("ip %v not found", ip),
}
b, err := json.MarshalIndent(r, "", " ")
if err != nil {
return nil, err
}
return b, nil
}

b, err := json.MarshalIndent(&DefaultOutput{
OwnerId: result.NetworkInterfaces[0].OwnerId,
Description: result.NetworkInterfaces[0].Description,
InterfaceType: result.NetworkInterfaces[0].InterfaceType,
AvailabilityZone: result.NetworkInterfaces[0].AvailabilityZone}, " ", " ")
instanceID := result.NetworkInterfaces[0].Attachment.InstanceId
if instanceID != nil {
e, _ = getInstanceInfo(sess, instanceID)
}

r := Result{
Profile: profile,
ENI: &DefaultOutput{
OwnerId: result.NetworkInterfaces[0].OwnerId,
Description: result.NetworkInterfaces[0].Description,
InterfaceType: result.NetworkInterfaces[0].InterfaceType,
AvailabilityZone: result.NetworkInterfaces[0].AvailabilityZone,
EC2Associated: e,
},
}
b, err := json.MarshalIndent(r, "", " ")
if err != nil {
return nil, err
}
Expand Down

0 comments on commit 72f19ad

Please sign in to comment.