Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
Signed-off-by: Alexander Tanton <[email protected]>
  • Loading branch information
Tanton committed Oct 22, 2018
1 parent 9539b38 commit 2730dc8
Show file tree
Hide file tree
Showing 494 changed files with 223,798 additions and 2 deletions.
17 changes: 17 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
FROM golang:1.11-alpine3.8 as build

RUN apk add -U --no-cache ca-certificates git bash

COPY ./ /go/src/github.com/tantona/aws-sigv4-proxy
WORKDIR /go/src/github.com/tantona/aws-sigv4-proxy

RUN go build -o app github.com/tantona/aws-sigv4-proxy && \
mv ./app /go/bin

FROM alpine:3.8

WORKDIR /opt/
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=build /go/bin/app /opt/

ENTRYPOINT [ "/opt/app" ]
147 changes: 147 additions & 0 deletions Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

38 changes: 38 additions & 0 deletions Gopkg.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Gopkg.toml example
#
# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html
# for detailed Gopkg.toml documentation.
#
# required = ["github.com/user/thing/cmd/thing"]
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
#
# [[constraint]]
# name = "github.com/user/project"
# version = "1.0.0"
#
# [[constraint]]
# name = "github.com/user/project2"
# branch = "dev"
# source = "github.com/myfork/project2"
#
# [[override]]
# name = "github.com/x/y"
# version = "2.4.0"
#
# [prune]
# non-go = false
# go-tests = true
# unused-packages = true


[[constraint]]
name = "github.com/aws/aws-sdk-go"
version = "1.15.27"

[[constraint]]
name = "github.com/coreos/pkg"
version = "4.0.0"

[prune]
go-tests = true
unused-packages = true
4 changes: 4 additions & 0 deletions OWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
approvers:
- tantona
reviewers:
- tantona
56 changes: 54 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,58 @@
## AWS Sigv4 Proxy
# AWS SigV4 Proxy

The AWS SigV4 Proxy will sign incoming HTTP requests and forward them to the host specified in the `Host` header.

## Getting Started

Build and run the Proxy

```go
* The proxy will try to find credentials in the environment, shared credentials file, then the ec2 instance

docker build -t aws-sigv4-proxy .

# Env vars
docker run --rm -ti \
-e 'AWS_ACCESS_KEY_ID=<YOUR ACCESS KEY ID>' \
-e 'AWS_SECRET_ACCESS_KEY=<YOUR SECRET ACCESS KEY>' \
-p 8080:8080 \
aws-sigv4-proxy -v

***** or ******

# Shared Credentials
docker run --rm -ti \
-v ~/.aws:/root/.aws \
-p 8080:8080 \
-e 'AWS_PROFILE=<SOME PROFILE>' \
aws-sigv4-proxy -v
```

## Examples

S3
```
# us-east-1
curl -s -H 'host: s3.us-west-2.amazonaws.com' http://localhost:8080/<BUCKET_NAME>
# other region
curl -s -H 'host: s3.<BUCKET_REGION>.amazonaws.com' http://localhost:8080/<BUCKET_NAME>
```

SQS
```sh
curl -s -H 'host: sqs.<AWS_REGION>.amazonaws.com' 'http://localhost:8080/<AWS_ACCOUNT_ID>/<QUEUE_NAME>?Action=SendMessage&MessageBody=example'
```

API Gateway
```sh
curl -H 'host: <REST_API_ID>.execute-api.<AWS_REGION>.amazonaws.com' http://localhost:8080/<STAGE>/<PATH>
```

## Reference

- [AWS SigV4 signing Docs ](https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html)

This project signs and proxies HTTP requests with Sigv4

## License

Expand Down
40 changes: 40 additions & 0 deletions handler/aws.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package handler

import (
"fmt"
"strings"

"github.com/aws/aws-sdk-go/aws/endpoints"
)

var services = map[string]endpoints.ResolvedEndpoint{}

func init() {
// Triple nested loop - 😭
for _, partition := range endpoints.DefaultPartitions() {

for _, service := range partition.Services() {
for _, endpoint := range service.Endpoints() {
resolvedEndpoint, _ := endpoint.ResolveEndpoint()
host := strings.Replace(resolvedEndpoint.URL, "https://", "", 1)
services[host] = resolvedEndpoint
}
}
}

// Add api gateway endpoints
for region := range endpoints.AwsPartition().Regions() {
host := fmt.Sprintf("execute-api.%s.amazonaws.com", region)
services[host] = endpoints.ResolvedEndpoint{URL: fmt.Sprintf("https://%s", host), SigningMethod: "v4", SigningRegion: region, SigningName: "execute-api"}
}
}

func determineAWSServiceFromHost(host string) *endpoints.ResolvedEndpoint {
for endpoint, service := range services {
if strings.Contains(host, endpoint) {
return &service
}
}

return nil
}
45 changes: 45 additions & 0 deletions handler/handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package handler

import (
"bytes"
"io"
"net/http"

log "github.com/sirupsen/logrus"
)

type Handler struct {
ProxyClient Client
}

func (h *Handler) write(w http.ResponseWriter, status int, body []byte) {
w.WriteHeader(status)
w.Write(body)
}

func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
resp, err := h.ProxyClient.Do(r)
if err != nil {
log.WithError(err).Error("unable to proxy request")
h.write(w, http.StatusBadRequest, []byte(err.Error()))
return
}
defer resp.Body.Close()

// read response body
buf := bytes.Buffer{}
if _, err := io.Copy(&buf, resp.Body); err != nil {
log.WithError(err).Error("unable to proxy request")
h.write(w, http.StatusInternalServerError, []byte(err.Error()))
return
}

// copy headers
for k, vals := range resp.Header {
for _, v := range vals {
w.Header().Add(k, v)
}
}

h.write(w, resp.StatusCode, buf.Bytes())
}
Loading

0 comments on commit 2730dc8

Please sign in to comment.