Skip to content

Commit

Permalink
inital commit
Browse files Browse the repository at this point in the history
  • Loading branch information
princespaghetti committed Jul 3, 2020
1 parent 622c77b commit 2d9d0ae
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 1 deletion.
22 changes: 22 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Release with goreleaser
on:
push:
tags:
- v*.*.*
jobs:
build:
runs-on: ubuntu-latest
name: goreleaser
steps:
- uses: actions/checkout@v2
- name: Unshallow Fetch
run: git fetch --prune --unshallow
- uses: actions/setup-go@v2
with:
go-version: '^1.14.0'
- name: Release via goreleaser
uses: goreleaser/goreleaser-action@master
with:
args: release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
26 changes: 26 additions & 0 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# This is an example goreleaser.yaml file with some sane defaults.
# Make sure to check the documentation at http://goreleaser.com
before:
hooks:
# You may remove this if you don't use go modules.
- go mod download
builds:
- env:
- CGO_ENABLED=0
archives:
- replacements:
darwin: Darwin
linux: Linux
windows: Windows
386: i386
amd64: x86_64
checksum:
name_template: 'checksums.txt'
snapshot:
name_template: "{{ .Tag }}-next"
changelog:
sort: asc
filters:
exclude:
- '^docs:'
- '^test:'
30 changes: 29 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,29 @@
# actionhero
# Action Hero

## What is Action Hero?

Action Hero is a sidecar style utility to assist with creating least privilege IAM Policies for AWS.

## Why is it needed?

Commonly developers begin creating infrastructure as code with more permissive roles that have administrative access to rapidly iterate. However, trying to create a more finely scoped set of permissions can be painful and time consuming.

Action Hero provides a means to capture all required permissions during the more permissive iterations to make it easier to create an IAM role with just the required permissions.

## How does it work?

Action Hero uses a feature of the AWS SDK known as Client Side Monitoring. This feature sends AWS API calls to a local udp port (31000 by default)

Summit Route discusses the feature in this [post](https://summitroute.com/blog/2020/05/25/client_side_monitoring/) (which was the inspiration for this tool)

## Prerequisites

As discussed in the above post ``export AWS_CSM_ENABLED=true`` must be run in the shell or set in a profile where the tool using the SDK will be run. For example if you're using terraform it would need to be exported in the shell that the plan/apply would be run from

## Running Action Hero

In a seperate terminal from where you are using the SDK run the binary

``./actionhero``

Ctrl+C can be used to terminate the process safely
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/princespaghetti/actionhero

go 1.13
81 changes: 81 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package main

import (
"encoding/json"
"fmt"
"log"
"net"
"os"
"os/signal"
"runtime"
"strings"
"syscall"
)

// ActionMessage is a struct representing a message from CSM
type ActionMessage struct {
Version int `json:"Version"`
ClientID string `json:"ClientId"`
Type string `json:"Type"`
Service string `json:"Service"`
Action string `json:"Api"`
Timestamp int `json:"Timestamp"`
AttemptLatency int `json:"AttemptLatency"`
Fqdn string `json:"Fqdn"`
UserAgent string `json:"UserAgent"`
AccessKey string `json:"AccessKey"`
Region string `json:"Region"`
HTTPStatusCode int `json:"HttpStatusCode"`
FinalHTTPStatusCode int `json:"FinalHttpStatusCode"`
XAmzRequestID string `json:"XAmzRequestId"`
XAmzID2 string `json:"XAmzId2"`
}

func listen(connection *net.UDPConn, quit chan struct{}) {
buffer := make([]byte, 1024)
n, _, err := 0, new(net.UDPAddr), error(nil)
var message ActionMessage
for err == nil {
n, _, err = connection.ReadFromUDP(buffer)
err := json.Unmarshal(buffer[:n], &message)
if err != nil {
log.Println(err)
}
//Each action taken sends two json messages. The first has a type of "ApiCallAttempt" this filters for the API call itself
if message.Type == "ApiCall" {
fmt.Println(strings.ToLower(message.Service) + ":" + message.Action)
}
}
fmt.Println("listener failed - ", err)
quit <- struct{}{}
}

//SetupCloseHandler Displays a message when the user closes the program
func SetupCloseHandler() {
c := make(chan os.Signal)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
go func() {
<-c
fmt.Println("\rCtrl+C pressed, Stopping...")
os.Exit(0)
}()
}

func main() {

addr := net.UDPAddr{
Port: 31000,
IP: net.IP{127, 0, 0, 1},
}
connection, err := net.ListenUDP("udp", &addr)
if err != nil {
panic(err)
}
fmt.Println("Action Hero Starting...")
SetupCloseHandler()
quit := make(chan struct{})
for i := 0; i < runtime.NumCPU(); i++ {
go listen(connection, quit)
}
<-quit // hang until an error
}

0 comments on commit 2d9d0ae

Please sign in to comment.