Skip to content

Commit

Permalink
added region flag to avoid having to parse the endpoint to get the re…
Browse files Browse the repository at this point in the history
…gion (#1)

hard-coded proxy.service value to "es"
added insecure flag and logic to avoid SSL verification
  • Loading branch information
DustinKLo authored Oct 16, 2020
1 parent 675be30 commit c656b87
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 78 deletions.
34 changes: 26 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ brew install aws-es-proxy
### Build from Source

#### Dependencies:
* go1.14+

- go1.14+

```sh
#requires go1.14
Expand Down Expand Up @@ -82,8 +83,6 @@ export AWS_SECRET_ACCESS_KEY=MY-SECRET-KEY
}
```



## Usage example:

You can use either argument `-endpoint` OR environment variable `ENDPOINT` to specify AWS ElasticSearch endpoint.
Expand All @@ -100,14 +99,14 @@ export ENDPOINT=https://test-es-somerandomvalue.eu-west-1.es.amazonaws.com
Listening on 10.0.0.1:9200
```

*aws-es-proxy* listens on 127.0.0.1:9200 if no additional argument is provided. You can change the IP and Port passing the argument `-listen`
_aws-es-proxy_ listens on 127.0.0.1:9200 if no additional argument is provided. You can change the IP and Port passing the argument `-listen`

```sh
./aws-es-proxy -listen :8080 -endpoint ...
./aws-es-proxy -listen 10.0.0.1:9200 -endpoint ...
```

By default, *aws-es-proxy* will not display any message in the console. However, it has the ability to print requests being sent to Amazon Elasticsearch, and the duration it takes to receive the request back. This can be enabled using the option `-verbose`
By default, _aws-es-proxy_ will not display any message in the console. However, it has the ability to print requests being sent to Amazon Elasticsearch, and the duration it takes to receive the request back. This can be enabled using the option `-verbose`

```sh
./aws-es-proxy -verbose ...
Expand All @@ -124,6 +123,10 @@ For a full list of available options, use `-h`:
```sh
./aws-es-proxy -h
Usage of ./aws-es-proxy:
-auth
Require HTTP Basic Auth
-debug
Print debug messages
-endpoint string
Amazon ElasticSearch Endpoint (e.g: https://dummy-host.eu-west-1.es.amazonaws.com)
-listen string
Expand All @@ -132,15 +135,30 @@ Usage of ./aws-es-proxy:
Log user requests and ElasticSearch responses to files
-no-sign-reqs
Disable AWS Signature v4
-password string
HTTP Basic Auth Password
-pretty
Prettify verbose and file output
-realm string
Authentication Required
-remote-terminate
Allow HTTP remote termination
-timeout int
Set a request timeout to ES. Specify in seconds, defaults to 15 (default 15)
-username string
HTTP Basic Auth Username
-verbose
Print user requests
-version
Print aws-es-proxy version
-region
AWS region (ex. us-west-2) (Required)
-insecure
Will not verify SSL (default false)
```


## Using HTTP Clients

After you run *aws-es-proxy*, you can now open your Web browser on [http://localhost:9200](http://localhost:9200). Everything should be working as you have your own instance of ElasticSearch running on port 9200.
After you run _aws-es-proxy_, you can now open your Web browser on [http://localhost:9200](http://localhost:9200). Everything should be working as you have your own instance of ElasticSearch running on port 9200.

To access Kibana, use [http://localhost:9200/_plugin/kibana/app/kibana](http://localhost:9200/_plugin/kibana/app/kibana)
To access Kibana, use [http://localhost:9200/\_plugin/kibana/app/kibana](http://localhost:9200/_plugin/kibana/app/kibana)
144 changes: 74 additions & 70 deletions aws-es-proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package main
import (
"bytes"
"crypto/subtle"
"crypto/tls"
"encoding/json"
"flag"
"fmt"
Expand All @@ -22,7 +23,6 @@ import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/credentials/stscreds"
"github.com/aws/aws-sdk-go/aws/endpoints"
"github.com/aws/aws-sdk-go/aws/session"
v4 "github.com/aws/aws-sdk-go/aws/signer/v4"
"github.com/sirupsen/logrus"
Expand Down Expand Up @@ -69,23 +69,25 @@ type responseStruct struct {
}

type proxy struct {
scheme string
host string
region string
service string
endpoint string
verbose bool
prettify bool
logtofile bool
nosignreq bool
fileRequest *os.File
fileResponse *os.File
credentials *credentials.Credentials
httpClient *http.Client
auth bool
username string
password string
realm string
scheme string
host string
region string
service string
endpoint string
verbose bool
prettify bool
logtofile bool
nosignreq bool
fileRequest *os.File
fileResponse *os.File
credentials *credentials.Credentials
httpClient *http.Client
auth bool
username string
password string
realm string
remoteTerminate bool
insecure bool
}

func newProxy(args ...interface{}) *proxy {
Expand All @@ -99,25 +101,33 @@ func newProxy(args ...interface{}) *proxy {
CheckRedirect: noRedirect,
}

if args[12].(bool) == true {
client.Transport = &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
}

return &proxy{
endpoint: args[0].(string),
verbose: args[1].(bool),
prettify: args[2].(bool),
logtofile: args[3].(bool),
nosignreq: args[4].(bool),
httpClient: &client,
auth: args[6].(bool),
username: args[7].(string),
password: args[8].(string),
realm: args[9].(string),
endpoint: args[0].(string),
verbose: args[1].(bool),
prettify: args[2].(bool),
logtofile: args[3].(bool),
nosignreq: args[4].(bool),
httpClient: &client,
auth: args[6].(bool),
username: args[7].(string),
password: args[8].(string),
realm: args[9].(string),
remoteTerminate: args[10].(bool),
region: args[11].(string),
insecure: args[12].(bool),
}
}

func (p *proxy) parseEndpoint() error {
var (
link *url.URL
err error
isAWSEndpoint bool
link *url.URL
err error
)

if link, err = url.Parse(p.endpoint); err != nil {
Expand Down Expand Up @@ -146,6 +156,9 @@ func (p *proxy) parseEndpoint() error {
p.scheme = link.Scheme
p.host = link.Host

p.service = "es"
logrus.Debugln("AWS Region", p.region)

// AWS SignV4 enabled, extract required parts for signing process
if !p.nosignreq {

Expand All @@ -154,29 +167,6 @@ func (p *proxy) parseEndpoint() error {
if len(split) < 2 {
logrus.Debugln("Endpoint split is less than 2")
}

awsEndpoints := []string{}
for _, partition := range endpoints.DefaultPartitions() {
for region := range partition.Regions() {
awsEndpoints = append(awsEndpoints, fmt.Sprintf("%s.es.%s", region, partition.DNSSuffix()))
}
}

isAWSEndpoint = false
for _, v := range awsEndpoints {
if split[1] == v {
logrus.Debugln("Provided endpoint is a valid AWS Elasticsearch endpoint")
isAWSEndpoint = true
break
}
}

if isAWSEndpoint {
// Extract region and service from link. This should be save now
parts := strings.Split(link.Host, ".")
p.region, p.service = parts[1], "es"
logrus.Debugln("AWS Region", p.region)
}
}

return nil
Expand Down Expand Up @@ -210,6 +200,10 @@ func (p *proxy) getSigner() *v4.Signer {
}

func (p *proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if p.remoteTerminate && r.URL.Path == "/terminate-proxy" && r.Method == http.MethodPost {
logrus.Infoln("Terminate Signal")
os.Exit(0)
}

if p.auth {
user, pass, ok := r.BasicAuth()
Expand Down Expand Up @@ -330,6 +324,7 @@ func (p *proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {

fmt.Println()
fmt.Println("========================")
fmt.Println("Region: ", p.region)
fmt.Println(t.Format("2006/01/02 15:04:05"))
fmt.Println("Remote Address: ", r.RemoteAddr)
fmt.Println("Request URI: ", proxied.RequestURI())
Expand Down Expand Up @@ -420,22 +415,25 @@ func copyHeaders(dst, src http.Header) {
func main() {

var (
debug bool
auth bool
username string
password string
realm string
verbose bool
prettify bool
logtofile bool
nosignreq bool
ver bool
endpoint string
listenAddress string
fileRequest *os.File
fileResponse *os.File
err error
timeout int
debug bool
auth bool
username string
password string
realm string
verbose bool
prettify bool
logtofile bool
nosignreq bool
ver bool
endpoint string
listenAddress string
fileRequest *os.File
fileResponse *os.File
err error
timeout int
remoteTerminate bool
region string
insecure bool
)

flag.StringVar(&endpoint, "endpoint", "", "Amazon ElasticSearch Endpoint (e.g: https://dummy-host.eu-west-1.es.amazonaws.com)")
Expand All @@ -451,6 +449,9 @@ func main() {
flag.StringVar(&username, "username", "", "HTTP Basic Auth Username")
flag.StringVar(&password, "password", "", "HTTP Basic Auth Password")
flag.StringVar(&realm, "realm", "", "Authentication Required")
flag.BoolVar(&remoteTerminate, "remote-terminate", false, "Allow HTTP remote termination")
flag.StringVar(&region, "region", "", "AWS Region (ex. us-west-2)")
flag.BoolVar(&insecure, "insecure", false, "Verify SSL")
flag.Parse()

if endpoint == "" {
Expand Down Expand Up @@ -496,6 +497,9 @@ func main() {
username,
password,
realm,
remoteTerminate,
region,
insecure,
)

if err = p.parseEndpoint(); err != nil {
Expand Down

0 comments on commit c656b87

Please sign in to comment.