awses

package module
v0.0.0-...-656ad4a Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 9, 2019 License: Apache-2.0 Imports: 19 Imported by: 0

README

caddy-awses

Caddy plugin for signing and proxying requests to AWS Elasticsearch (AWS ES).

Configuring access to an AWS ES domain can be tricky. The access policy of an AWS ES domain is based on a principal (which necessitates a signed request) or an IP address whitelist. Whitelisting IP addresses often isn't a viable option and standard tools (such as curl or a browser) can't properly sign requests.

This is exactly the problem this plugin aims to address. Standard tools can make unauthenticated requests to the Caddy server which are then signed and proxied to the AWS ES service.

Getting Started

The simplest way to get started is by invoking caddy with the awses directive, like so:

caddy awses

Or by adding the awses directive to your Caddyfile.

Syntax

awses [/prefix] {
    domain <DOMAIN>
    region <REGION>
    role <ROLE_ARN>
}
/prefix

The prefix the path must match for awses to match and handle the request. Defaults to /, matching all requests.

Note: The prefix is always considered to be a full path segment. i.e. a prefix of /abc will not match a request for /abcdef, but will match /abc/def/.

domain

The name of the AWS ES domain to proxy requests to. Derived from the request path unless set (see URLs below).

Note: awses will lookup the AWS ES domain endpoint automatically and should not be provided.

region

The AWS region containing the AWS ES domains to proxy for. Derived from the request path unless set (see URLs below).

role

The AWS IAM role to assume to sign requests. This can be useful to assume a role that has the permissions necessary to access the domain. This can also be used for cross-account access of a domain. By default, no role is assumed.

Required Permissions

For any AWS ES domain that awses proxies to, the following permission is always required (to lookup the domain's endpoint):

  • es:DescribeElasticsearchDomain

Additionally, the following actions must be allowed for any method you intend awses to proxy:

  • es:ESHttpDelete
  • es:ESHttpGet
  • es:ESHttpHead
  • es:ESHttpPost
  • es:ESHttpPut

Optionally, if no domain is specified the following permission can be granted to get a list of available domains (within a region):

  • es:ListDomainNames

URLs

Requests to awses take the form:

[/region][/domain]/<destination>

If region and/or domain are specified in the configuration, they will not be derived from the request path.

See Examples below for more details.

Examples

All regions and domains
awses

Allows requests in the following form:

  • /<region>/<domain>/<destination>
Specific region (all domains)
awses {
    region us-west-2
}

Allows requests in the following form:

  • /<domain>/<destination>
Specific domain (all regions)
awses {
    domain es-logs
}

Allows requests in the following form:

  • /<region>/<destination>
Specific region and domain
awses {
    region us-west-2
    domain es-logs
}

Allows requests in the following form:

  • /<destination>
Multiple prefixes
awses /docs/ {
    region us-east-1
    domain the-docs
}

awses /logs/ {
    domain es-logs
}

awses /other-account/logs/ {
    domain es-logs
    role arn:aws:iam::123456789012:role/elasticsearch-logs-us-east-2
}

Allows requests in the following forms:

  • /docs/<destination>
  • /logs/<region>/<destination>
  • /other-account/logs/<region>/<destination>

Kibana

Please note that Kibana appears to have issues when hosted at a path other than /, but I haven't had enough time to track down why that is just yet.

If you're looking to use Kibana through awses, the configuration will need to omit the /prefix and will need to include region and domain parameters. This will leave Kibana accessible at /_plugin/kibana/.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrTooManyArgs  = errors.New("[awses] too many arguments provided")
	ErrSingleDomain = errors.New("[awses] a single domain must be provided for the domain directive")
	ErrSingleRegion = errors.New("[awses] a single region must be provided for the region directive")
	ErrSingleRole   = errors.New("[awses] a single role must be provided for the role directive")
)
View Source
var (
	ErrDomainNotFound    = errors.New("AWS ES domain not found")
	ErrInvalidDomainName = errors.New("The provided AWS ES domain is invalid")
)

Functions

This section is empty.

Types

type Config

type Config struct {
	Path string

	Role   string
	Region string

	Domain string
}

func ParseConfigs

func ParseConfigs(c *caddy.Controller) ([]*Config, error)

type Dispatcher

type Dispatcher struct {
	Configs []*Config
	Next    httpserver.Handler
	// contains filtered or unexported fields
}

func NewDispatcher

func NewDispatcher(configs []*Config, next httpserver.Handler) *Dispatcher

func (Dispatcher) ConfigForRequest

func (d Dispatcher) ConfigForRequest(r *http.Request) *Config

func (Dispatcher) ServeHTTP

func (d Dispatcher) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error)

type ElasticsearchClientFactory

type ElasticsearchClientFactory struct {
	RootSession *session.Session
	Role        string
	// contains filtered or unexported fields
}

An Elasticsearch client factory with a cache that allows concurrent cached client sharing

func NewElasticsearchClientFactory

func NewElasticsearchClientFactory(rootSession *session.Session, role string) *ElasticsearchClientFactory

func (*ElasticsearchClientFactory) Get

Returns a cached client or instantiates a new client and caches it

func (*ElasticsearchClientFactory) New

Returns a new client (does not lock or use the cache)

type ElasticsearchManager

type ElasticsearchManager struct {
	ClientFactory ElasticsearchClientFactory
	// contains filtered or unexported fields
}

func NewElasticsearchManager

func NewElasticsearchManager(rootSession *session.Session, role string) *ElasticsearchManager

func (*ElasticsearchManager) GetProxy

func (m *ElasticsearchManager) GetProxy(region, domain string) (*httputil.ReverseProxy, error)

func (*ElasticsearchManager) ListDomains

func (m *ElasticsearchManager) ListDomains(region string) ([]string, error)

func (*ElasticsearchManager) NewProxy

func (m *ElasticsearchManager) NewProxy(region, domain string) (*httputil.ReverseProxy, error)

type Handler

type Handler struct {
	Config *Config
	// contains filtered or unexported fields
}

func NewHandler

func NewHandler(config *Config, rootSession *session.Session) *Handler

func (*Handler) ServeHTTP

func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL