From 4f2f9a8a57ee347b1d86630f5a986cb44f6d9e5c Mon Sep 17 00:00:00 2001 From: Eugene Dementiev Date: Wed, 8 Apr 2020 09:24:31 +1200 Subject: [PATCH] Add meta tags. Set up deployment pipeline --- .dockerignore | 1 + .github/workflows/release.yml | 29 +++++++++++++++++++++++++++++ .gitignore | 1 + Dockerfile | 2 +- README.md | 10 +++++++--- go.mod | 2 ++ go.sum | 4 ---- lib/reconf.go | 12 +++++++++++- lib/util.go | 22 +++++++++++++++------- modd.conf | 3 +++ 10 files changed, 70 insertions(+), 16 deletions(-) create mode 100644 .github/workflows/release.yml create mode 100644 modd.conf diff --git a/.dockerignore b/.dockerignore index 5f1c97c..a6856ee 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,3 +1,4 @@ vendor/ Dockerfile build.sh +*.git diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..a78dbe0 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,29 @@ +name: Build and publish aws-ssh +on: + push: + tags: + - '*' +jobs: + build_and_deploy: + name: build and deploy aws-ssh + runs-on: ubuntu-latest + steps: + - + name: Checkout + uses: actions/checkout@v2 + - + name: Unshallow to restore tags + run: git fetch --prune --unshallow + - + name: Set up Go + uses: actions/setup-go@v1 + with: + go-version: 1.13.x + - + name: Run GoReleaser + uses: goreleaser/goreleaser-action@v1 + with: + version: latest + args: release --rm-dist + env: + GITHUB_TOKEN: ${{ secrets.RELEASE_GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index 9aa6fcd..d43c920 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ aws-ssh *.log dist/ vendor/ +*.swp diff --git a/Dockerfile b/Dockerfile index eb79746..c170e80 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.11-alpine as build +FROM golang:1.13-alpine as build RUN apk update && apk add git diff --git a/README.md b/README.md index a1cec09..cbd982f 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,14 @@ ### What it is + This program goes through all available AWS accounts in parallel and determines IP addresses of ec2 instances. It also detects so-called "bastion" instances. -If a bastion instance has tag "Global" with value "yes", "true" or "1", then aws-ssh decides it can be -used across multiple VPCs. If there are multiple bastion instances, it chooses the instance that has the most common match in name. +There are the following EC2 instance tags that change behaviour: + +1. (Deprecated) If a bastion instance has tag "Global" with value "yes", "true" or "1", then aws-ssh will use it for all VPCs. If there are multiple bastion instances, it chooses the instance that has the most common match in name. +2. "x-aws-ssh-global" - same as the above +3. "x-aws-ssh-user" - sets the ssh username in the config. Any comments and especially pull requests are highly appreciated. @@ -28,5 +32,5 @@ Use "aws-ssh [command] --help" for more information about a command. ### Build -You'll need go>=1.11. Note that this project uses `go.mod`, so the project has to be cloned somewhere outside of the `GOPATH` directory. +You'll need go>=1.13. Note that this project uses `go.mod`, so the project has to be cloned somewhere outside of the `GOPATH` directory. Or just use provided `Dockerfile`. diff --git a/go.mod b/go.mod index a1b82d3..b5ec074 100644 --- a/go.mod +++ b/go.mod @@ -23,3 +23,5 @@ require ( gopkg.in/ahmetb/go-linq.v3 v3.0.0 gopkg.in/ini.v1 v1.41.0 // indirect ) + +go 1.13 diff --git a/go.sum b/go.sum index 4b51ad9..731ba21 100644 --- a/go.sum +++ b/go.sum @@ -3,8 +3,6 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/apex/log v1.1.0 h1:J5rld6WVFi6NxA6m8GJ1LJqu3+GiTFIt3mYv27gdQWI= github.com/apex/log v1.1.0/go.mod h1:yA770aXIDQrhVOIGurT/pVdfCpSq1GQV/auzMN5fzvY= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/aws/aws-sdk-go v1.16.26 h1:GWkl3rkRO/JGRTWoLLIqwf7AWC4/W/1hMOUZqmX0js4= -github.com/aws/aws-sdk-go v1.16.26/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.25.23 h1:EJx1uSb8E/HRkDa02pOb0r/73bkDbds7qg74s57qYgs= github.com/aws/aws-sdk-go v1.25.23/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= @@ -16,8 +14,6 @@ github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/go-ini/ini v1.41.0 h1:526aoxDtxRHFQKMZfcX2OG9oOI8TJ5yPLM0Mkno/uTY= -github.com/go-ini/ini v1.41.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-ini/ini v1.48.0 h1:TvO60hO/2xgaaTWp2P0wUe4CFxwdMzfbkv3+343Xzqw= github.com/go-ini/ini v1.48.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg= diff --git a/lib/reconf.go b/lib/reconf.go index 9fcd301..05ab6f6 100644 --- a/lib/reconf.go +++ b/lib/reconf.go @@ -20,6 +20,7 @@ type SSHEntry struct { InstanceID, Name, ProxyJump, + User, Profile string } @@ -28,6 +29,9 @@ func (e SSHEntry) ConfigFormat() string { var output = []string{ fmt.Sprintf("Host %s %s %s.%s", e.Name, e.InstanceID, e.Address, e.Profile), } + if e.User != "" { + output = append(output, fmt.Sprintf(" User %s", e.User)) + } if e.ProxyJump != "" { output = append(output, fmt.Sprintf(" ProxyJump %s", e.ProxyJump)) } @@ -121,12 +125,18 @@ func Reconf(profiles []string, filename string) { } entry.Address = aws.StringValue(instance.PrivateIpAddress) // get the private address first as we always have one if bastion != nil { // get private address and add proxyhost, which is the bastion ip - entry.ProxyJump = aws.StringValue(bastion.PublicIpAddress) + bastionUser := getTagValue("x-aws-ssh-user", bastion.Tags) + if bastionUser != "" { + entry.ProxyJump = fmt.Sprintf("%s@%s", bastionUser, aws.StringValue(bastion.PublicIpAddress)) + } else { + entry.ProxyJump = aws.StringValue(bastion.PublicIpAddress) + } } else { // get public IP if we have one if publicIP := aws.StringValue(instance.PublicIpAddress); publicIP != "" { entry.Address = aws.StringValue(instance.PublicIpAddress) } } + entry.User = getTagValue("x-aws-ssh-user", instance.Tags) sshEntries = append(sshEntries, entry) } } diff --git a/lib/util.go b/lib/util.go index 186bd91..51feb19 100644 --- a/lib/util.go +++ b/lib/util.go @@ -13,16 +13,24 @@ const bastionCanonicalName = "bastion" var sanitiser = regexp.MustCompile("[\\s-]+") -func getNameFromTags(tags []*ec2.Tag) string { - if len(tags) > 0 { - for _, tag := range tags { - if aws.StringValue(tag.Key) == "Name" { - return strings.ToLower(aws.StringValue(tag.Value)) - } +func getTagValue(tag string, tags []*ec2.Tag, caseInsensitive ...bool) string { + if len(caseInsensitive) > 0 { + if caseInsensitive[0] { + tag = strings.ToLower(tag) + } + } + + for _, subTag := range tags { + if aws.StringValue(subTag.Key) == tag { + return aws.StringValue(subTag.Value) } } return "" + +} +func getNameFromTags(tags []*ec2.Tag) string { + return strings.ToLower(getTagValue("Name", tags)) } func isBastionFromTags(tags []*ec2.Tag, checkGlobal bool) bool { @@ -34,7 +42,7 @@ func isBastionFromTags(tags []*ec2.Tag, checkGlobal bool) bool { switch aws.StringValue(tag.Key) { case "Name": name = strings.ToLower(aws.StringValue(tag.Value)) - case "Global": + case "Global", "x-aws-ssh-global": { value := strings.ToLower(aws.StringValue(tag.Value)) if value == "yes" || value == "true" || value == "1" { diff --git a/modd.conf b/modd.conf new file mode 100644 index 0000000..2c76e1e --- /dev/null +++ b/modd.conf @@ -0,0 +1,3 @@ +**/*.go { + prep: go build +}