elasticsearch

package module
v0.5.4 Latest Latest
Warning

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

Go to latest
Published: Mar 18, 2020 License: MPL-2.0 Imports: 18 Imported by: 3

README

Elasticsearch Database Secrets Engine

This plugin provides unique, short-lived credentials for Elasticsearch using native X-Pack Security.

Getting Started

To take advantage of this plugin, you must first enable Elasticsearch's native realm of security by activating X-Pack. These instructions will walk you through doing this using ElasticSearch 7.1.1.

Enable X-Pack Security in Elasticsearch

Read Securing the Elastic Stack and follow its instructions for enabling X-Pack Security.

Enable Encrypted Communications

This plugin communicates with Elasticsearch's security API. In ES 7.1.1, you must enable TLS to consume that API.

To set up TLS in Elasticsearch, first read encrypted communications and go through its instructions on encrypting HTTP client communications.

After enabling TLS on the Elasticsearch side, you'll need to convert the .p12 certificates you generated to other formats so they can be used by Vault. Here is an example using OpenSSL to convert our .p12 certs to the pem format.

Also, on the instance running Elasticsearch, we needed to install our newly generated CA certificate that was originally in the .p12 format. We did this by converting the .p12 CA cert to a pem, and then further converting that pem to a crt, adding that crt to /usr/share/ca-certificates/extra, and using sudo dpkg-reconfigure ca-certificates.

The above instructions may vary if you are not using an Ubuntu machine. Please ensure you're using the methods specific to your operating environment. Describing every operating environment is outside the scope of these instructions.

Set Up Passwords

When done, verify that you've enabled X-Pack by running $ $ES_HOME/bin/elasticsearch-setup-passwords interactive. You'll know it's been set up successfully if it takes you through a number of password-inputting steps.

Create a Role for Vault

Next, in Elasticsearch, we recommend that you create a user just for Vault to use in managing secrets.

To do this, first create a role that will allow Vault the minimum privileges needed to administer users and passwords by performing a POST to Elasticsearch. To do this, we used the elastic superuser whose password we created in the $ $ES_HOME/bin/elasticsearch-setup-passwords interactive step.

$ curl \
    -X POST \
    -H "Content-Type: application/json" \
    -d '{"cluster": ["manage_security"]}' \
    http://elastic:$PASSWORD@localhost:9200/_xpack/security/role/vault

Next, create a user for Vault associated with that role.

$ curl \
    -X POST \
    -H "Content-Type: application/json" \
    -d @data.json \
    http://elastic:$PASSWORD@localhost:9200/_xpack/security/user/vault

The contents of data.json in this example are:

{
 "password" : "myPa55word",
 "roles" : [ "vault" ],
 "full_name" : "Hashicorp Vault",
 "metadata" : {
   "plugin_name": "Vault Plugin Secrets ElasticSearch",
   "plugin_url": "https://github.com/hashicorp/vault-plugin-secrets-elasticsearch"
 }
}

Now, Elasticsearch is configured and ready to be used with Vault.

Example Walkthrough

Here is an example of how to successfully configure and use this secrets engine using the Vault CLI. Note that the plugin_name may need to be vault-plugin-database-elasticsearch if you manually mounted it rather than using the version of the plugin built in to Vault.

export ES_HOME=/home/somewhere/Applications/elasticsearch-7.1.1

vault secrets enable database

vault write database/config/my-elasticsearch-database \
    plugin_name="elasticsearch-database-plugin" \
    allowed_roles="internally-defined-role,externally-defined-role" \
    username=vault \
    password=myPa55word \
    url=http://localhost:9200 \
    ca_cert=/usr/share/ca-certificates/extra/elastic-stack-ca.crt.pem \
    client_cert=$ES_HOME/config/certs/elastic-certificates.crt.pem \
    client_key=$ES_HOME/config/certs/elastic-certificates.key.pem
    
# create and get creds with one type of role
vault write database/roles/internally-defined-role \
    db_name=my-elasticsearch-database \
    creation_statements='{"elasticsearch_role_definition": {"indices": [{"names":["*"], "privileges":["read"]}]}}' \
    default_ttl="1h" \
    max_ttl="24h"
    
vault read database/creds/internally-defined-role
    
# create and get creds with another type of role
vault write database/roles/externally-defined-role \
    db_name=my-elasticsearch-database \
    creation_statements='{"elasticsearch_roles": ["vault"]}' \
    default_ttl="1h" \
    max_ttl="24h"

vault read database/creds/externally-defined-role

# renew credentials
vault lease renew database/creds/internally-defined-role/nvJ6SveX9PN1E4BlxVWdKuX1

# revoke credentials
vault lease revoke database/creds/internally-defined-role/nvJ6SveX9PN1E4BlxVWdKuX1

# rotate root credentials
vault write -force database/rotate-root/my-elasticsearch-database

Developing

The Vault plugin system is documented on the Vault documentation site.

You will need to define a plugin directory using the plugin_directory configuration directive, then place the vault-plugin-database-elasticsearch executable generated above in the directory.

Register the plugin using

vault write sys/plugins/catalog/vault-plugin-database-elasticsearch \
    sha256=$(sha256sum bin/vault-plugin-database-elasticsearch) \
    command="vault-plugin-database-elasticsearch"

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func New

func New() (interface{}, error)

func Run

func Run(apiTLSConfig *api.TLSConfig) error

Types

type Client

type Client struct {
	// contains filtered or unexported fields
}

func NewClient

func NewClient(config *ClientConfig) (*Client, error)

func (*Client) ChangePassword

func (c *Client) ChangePassword(ctx context.Context, name, newPassword string) error

func (*Client) CreateRole

func (c *Client) CreateRole(ctx context.Context, name string, role map[string]interface{}) error

func (*Client) CreateUser

func (c *Client) CreateUser(ctx context.Context, name string, user *User) error

func (*Client) DeleteRole

func (c *Client) DeleteRole(ctx context.Context, name string) error

func (*Client) DeleteUser

func (c *Client) DeleteUser(ctx context.Context, name string) error

func (*Client) GetRole

func (c *Client) GetRole(ctx context.Context, name string) (map[string]interface{}, error)

GetRole returns nil, nil if role is unfound.

type ClientConfig

type ClientConfig struct {
	Username, Password, BaseURL string

	// Leave this nil to flag that TLS is not desired
	TLSConfig *TLSConfig
}

type Elasticsearch

type Elasticsearch struct {
	// contains filtered or unexported fields
}

Elasticsearch implements dbplugin's Database interface.

func NewElasticsearch

func NewElasticsearch() *Elasticsearch

func (*Elasticsearch) Close

func (es *Elasticsearch) Close() error

func (*Elasticsearch) CreateUser

func (es *Elasticsearch) CreateUser(ctx context.Context, statements dbplugin.Statements, usernameConfig dbplugin.UsernameConfig, _ time.Time) (string, string, error)

CreateUser is called on `$ vault read database/creds/:role-name` and it's the first time anything is touched from `$ vault write database/roles/:role-name`. This is likely to be the highest-throughput method for this plugin.

func (*Elasticsearch) GenerateCredentials

func (es *Elasticsearch) GenerateCredentials(ctx context.Context) (string, error)

GenerateCredentials returns a generated password

func (*Elasticsearch) Init

func (es *Elasticsearch) Init(ctx context.Context, config map[string]interface{}, verifyConnection bool) (map[string]interface{}, error)

Init is called on `$ vault write database/config/:db-name`, or when you do a creds call after Vault's been restarted.

func (*Elasticsearch) Initialize

func (es *Elasticsearch) Initialize(ctx context.Context, config map[string]interface{}, verifyConnection bool) error

DEPRECATED, included for backward-compatibility until removal

func (*Elasticsearch) RenewUser

func (es *Elasticsearch) RenewUser(_ context.Context, _ dbplugin.Statements, _ string, _ time.Time) error

RenewUser gets called on `$ vault lease renew {{lease-id}}`. It automatically pushes out the amount of time until the database secrets engine calls RevokeUser, if appropriate.

func (*Elasticsearch) RevokeUser

func (es *Elasticsearch) RevokeUser(ctx context.Context, statements dbplugin.Statements, username string) error

RevokeUser is called when a lease expires.

func (*Elasticsearch) RotateRootCredentials

func (es *Elasticsearch) RotateRootCredentials(ctx context.Context, _ []string) (map[string]interface{}, error)

RotateRootCredentials doesn't require any statements from the user because it's not configurable in any way. We simply generate a new password and hit a pre-defined Elasticsearch REST API to rotate them.

func (*Elasticsearch) SecretValues

func (es *Elasticsearch) SecretValues() map[string]interface{}

SecretValues is used by some error-sanitizing middleware in Vault that basically replaces the keys in the map with the values given so they're not leaked via error messages.

func (*Elasticsearch) SetCredentials

func (es *Elasticsearch) SetCredentials(ctx context.Context, statements dbplugin.Statements, staticConfig dbplugin.StaticUserConfig) (username string, password string, err error)

SetCredentials is used to set the credentials for a database user to a specific username and password. This is not currently supported by the elastic search plugin, but is needed to conform to the dbplugin.Database interface

func (*Elasticsearch) Type

func (es *Elasticsearch) Type() (string, error)

type TLSConfig

type TLSConfig struct {
	// CACert is the path to a PEM-encoded CA cert file to use to verify theHTTPClient
	// Elasticsearch server SSL certificate.
	CACert string

	// CAPath is the path to a directory of PEM-encoded CA cert files to verify
	// the Elasticsearch server SSL certificate.
	CAPath string

	// ClientCert is the path to the certificate for Elasticsearch communication
	ClientCert string

	// ClientKey is the path to the private key for Elasticsearch communication
	ClientKey string

	// TLSServerName, if set, is used to set the SNI host when connecting via
	// TLS.
	TLSServerName string

	// Insecure enables or disables SSL verification
	Insecure bool
}

TLSConfig contains the parameters needed to configure TLS on the HTTP client used to communicate with Elasticsearch.

type User

type User struct {
	Password string   `json:"password"` // Passwords must be at least 6 characters long.
	Roles    []string `json:"roles"`
}

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

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