Skip to content

Commit

Permalink
Add documentation about security (Authentication and SSL)
Browse files Browse the repository at this point in the history
  • Loading branch information
polyfractal committed Jan 13, 2015
1 parent 8c22a82 commit 87f3fd9
Show file tree
Hide file tree
Showing 3 changed files with 201 additions and 19 deletions.
18 changes: 0 additions & 18 deletions docs/configuration.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -32,24 +32,6 @@ $client = new Elasticsearch\Client($params);

This associative array holds all custom configurations that you may want to set. Often, you'll only need to configure the hosts, but if you need more advanced behavior, read on.

=== HTTP Basic Auth
HTTP basic authentication is a very common requirement. To enable Basic Auth in the client, simply set a parameter with the required auth parameters:

[source,php]
----
$params = array();
$params['connectionParams']['auth'] = array(
'username',
'password',
'Basic' <1>
);
$client = new Elasticsearch\Client($params);
----
<1> Accepts four different options: `Basic`, `Digests`, `NTLM`, `Any`

After being initialized with authentication credentials, all outgoing requests will automatically include the HTTP auth headers.


=== Ignoring exceptions
The library attempts to throw exceptions for common problems. These exceptions
match the HTTP response code provided by Elasticsearch. For example, attempting to
Expand Down
4 changes: 3 additions & 1 deletion docs/index.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,6 @@ include::connections.asciidoc[]

include::serializers.asciidoc[]

include::php-version-requirement.asciidoc[]
include::php-version-requirement.asciidoc[]

include::security.asciidoc[]
198 changes: 198 additions & 0 deletions docs/security.asciidoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@

== Security

=== HTTP Authentication

If your Elasticsearch server is protected by HTTP Authentication, you need to provide the credentials to ES-PHP so that requests can be authenticated server-side. There are two ways to enable HTTP Authentication: inline with the host, or via `auth` parameters:

[source,php]
.Inline Authentication
----
$params = array();
$params['hosts'] = array (
'http://user:pass@localhost:9200', // HTTP Basic Auth
);
$client = new Elasticsearch\Client($params);
----

Only HTTP Basic Auth is supported via the inline syntax. Inline syntax allows different credentials for each host.
Alternatively, you can use the `auth` connection parameter:

[source,php]
.Auth Connection Parameter
----
$params = array();
$params['connectionParams']['auth'] = array(
'user',
'pass',
'Basic' <1>
);
$client = new Elasticsearch\Client($params);
----
<1> Accepts four different options: `Basic`, `Digests`, `NTLM`, `Any`

The `auth` syntax allows all four types of HTTP authentication, although `Basic` is the most often used variety. Unlike the inline syntax,
the `auth` syntax applies to all connections. This is useful if all servers share the same authentication credentials

After being initialized with authentication credentials, all outgoing requests will automatically include the appropriate HTTP auth headers. Authentication setup is identical regardless of the ConnectionClass you are using (e.g. GuzzleConnection or CurlMultiConnection)

=== SSL Configuration

Configuring SSL is a little more complex. First you need to identify if you are using an SSL certificate from a Certificate Authority (CA), or a self-signed certificate. Then you need to identify which ConnectionClass you are using, since they have slightly different syntax to enable SSL.

==== GuzzleConnection + Public CA Cert

If your certificate has been signed by a public Certificate Authority and your server has up-to-date root certificates, you only need to use `https` in the host path. Guzzle will automatically verify SSL certificates:

[source,php]
----
$params = array();
$params['hosts'] = array (
'https://localhost:9200' <1>
);
$client = new Elasticsearch\Client($params);
----
<1> Note that `https` is used, not `http`


If your server has out-dated root certificates, you may need to use a certificate bundle. For PHP clients, the best way is to use https://github.com/Kdyby/CurlCaBundle[Kdyby/CurlCaBundle]. Once installed, you would use inject it into the client:

[source,php]
----
$params = array();
$params['hosts'] = array (
'https://localhost:9200'
);
$params['guzzleOptions'] = array(
\Guzzle\Http\Client::SSL_CERT_AUTHORITY => 'system', <1>
\Guzzle\Http\Client::CURL_OPTIONS => [
CURLOPT_SSL_VERIFYPEER => true, <2>
CURLOPT_SSL_VERIFYHOST => 2, <3>
CURLOPT_CAINFO => \Kdyby\CurlCaBundle\CertificateHelper::getCaInfoFile() <4>
]
);
$client = new Elasticsearch\Client($params);
----
<1> Tell Guzzle that we are providing our own root certificates
<2> Verify that the certificate has been signed by a CA and can be trusted
<3> Verify that the host you are talking to is the host in the certificate. Note that cURL needs the value of `2`, not `true` or `1` (due to an internal cURL depreciation)
<4> Tell cURL where the certificate bundle is located

Note: Guzzle's `CURL_OPTIONS` parameter will accept any PHP http://php.net/manual/en/function.curl-setopt.php[curl_opt] constant for configuring.

==== GuzzleConnection + Self-Signed Certificate

Self-signed certificates are certs that have not been signed by a public CA. They are signed by your own organization. Self-signed certificates are often used for internal purposes, when you can securely spread the root certificate yourself. It should not be used when being exposed to public consumers, since this leaves the client vulnerable to man-in-the-middle attacks.

If you are using a self-signed certificate, you need to provide the certificate to the client and disable peer verification.

[source,php]
----
$params = array();
$params['hosts'] = array (
'https://localhost:9200'
);
$params['guzzleOptions'] = array(
\Guzzle\Http\Client::SSL_CERT_AUTHORITY => 'system',
\Guzzle\Http\Client::CURL_OPTIONS => [
CURLOPT_SSL_VERIFYPEER => false, <1>
CURLOPT_SSL_VERIFYHOST => 2, <2>
CURLOPT_CAINFO => 'cacert.pem', <3>
CURLOPT_SSLCERTTYPE => 'PEM', <4>
]
);
$client = new Elasticsearch\Client($params);
----
<1> Verify Peer is now false, since the cert cannot be verified against a public CA
<2> Verify Host should still be enabled, since you still want the host to match the certificate
<3> CAInfo is used to specify the path to the self-signed certificate
<4> Finally, the certificate type is specified. PEM is default, so you can omit this if you are using .pem certs

==== CurlMultiConnection + Public CA Cert

Similar to Guzzle, CurlMultiConnection will work seamlessly with publicly signed certs. You just need to specify the ConnectionClass and use `https` in the URI:


[source,php]
----
$params = array();
$params['connectionClass'] = '\Elasticsearch\Connections\CurlMultiConnection';
$params['hosts'] = array (
'https://localhost:9200' <1>
);
$client = new Elasticsearch\Client($params);
----
<1> Note that `https` is used, not `http`

If your server does not have up-to-date root certificates, you can also use https://github.com/Kdyby/CurlCaBundle[Kdyby/CurlCaBundle] with
CurlMultiConnection:

[source,php]
----
$params = array();
$params['connectionClass'] = '\Elasticsearch\Connections\CurlMultiConnection';
$params['hosts'] = array (
'https://localhost:9200'
);
$params['connectionParams']['curlOpts'] = array(
CURLOPT_CAINFO => \Kdyby\CurlCaBundle\CertificateHelper::getCaInfoFile()
);
$client = new Elasticsearch\Client($params);
----

Note that the syntax for specifying curl options is different from Guzzle.

==== CurlMultiConnection + Self-Signed Certificates

To use self-signed certificates, you need to provide the certificate and disable peer verification, just like Guzzle, albeit with slightly different syntax:

[source,php]
----
$params = array();
$params['connectionClass'] = '\Elasticsearch\Connections\CurlMultiConnection';
$params['hosts'] = array (
'https://localhost:9200'
);
$params['connectionParams']['curlOpts'] = array(
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => 2,
CURLOPT_CAINFO => 'cacert.pem',
CURLOPT_SSLCERTTYPE => 'PEM'
);
$client = new Elasticsearch\Client($params);
----

=== Using Authentication with SSL

It is possible to use HTTP authentication with SSL. Simply specify `https` in the URI, configure SSL settings as required and provide authentication credentials. For example, this snippet will authenticate using Basic HTTP auth and a self-signed certificate:

[source,php]
----
$params = array();
$params['hosts'] = array (
'https://localhost:9200'
);
$params['connectionParams']['auth'] = array('user', 'pass', 'Basic');
$params['guzzleOptions'] = array(
\Guzzle\Http\Client::SSL_CERT_AUTHORITY => 'system',
\Guzzle\Http\Client::CURL_OPTIONS => [
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => 2,
CURLOPT_CAINFO => 'cacert.pem',
CURLOPT_SSLCERTTYPE => 'PEM',
]
);
$client = new Elasticsearch\Client($params);
----

0 comments on commit 87f3fd9

Please sign in to comment.