-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
140 changed files
with
4,169 additions
and
3,279 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
120 changes: 120 additions & 0 deletions
120
docs/user/security/securing-communications/elasticsearch-mutual-tls.asciidoc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
[role="xpack"] | ||
[[elasticsearch-mutual-tls]] | ||
=== Mutual TLS authentication between {kib} and {es} | ||
++++ | ||
<titleabbrev>Mutual TLS with {es}</titleabbrev> | ||
++++ | ||
|
||
In a standard Transport Layer Security (TLS/SSL) configuration, the server presents a signed certificate to authenticate itself to the | ||
client. In a mutual TLS configuration, the client also presents a signed certificate to authenticate itself to the server. | ||
|
||
When {security} is enabled on your cluster, each request that {kib} makes to {es} must be authenticated. Most requests made through {kib} to | ||
{es} are authenticated by using the credentials of the logged-in user. There are, however, a few internal requests that the {kib} server | ||
needs to make to the {es} cluster. For this reason, you must configure credentials for the {kib} server to use for those requests. | ||
|
||
If {kib} has `elasticsearch.username` and `elasticsearch.password` configured, it will attempt to use these to authenticate to {es} via the | ||
{ref}/native-realm.html[Native realm]. However, {kib} also supports mutual TLS authentication with {es} via a {ref}/pki-realm.html[Public | ||
Key Infrastructure (PKI) realm]. To do so, {es} needs to verify the signature on the {kib} client certificate, and it also needs to map the | ||
certificate's distinguished name (DN) to the appropriate `kibana_system` role. | ||
|
||
NOTE: Using a PKI realm is a gold feature. For a comparison of the Elastic license levels, see https://www.elastic.co/subscriptions[the | ||
subscription page]. | ||
|
||
To configure {kib} and {es} to use mutual TLS authentication: | ||
|
||
. <<using-kibana-with-security,Set up {kib} to work with {security}>> with a username and password. | ||
|
||
. <<configuring-tls-kib-es,Set up TLS encryption between {kib} and {es}>>. At a minimum, this requires a server certificate for {es}. | ||
|
||
. Create a client certificate and private key for {kib} to use when connecting to {es}. | ||
+ | ||
-- | ||
NOTE: This is not the same as the <<configuring-tls-browser-kib,server certificate>> that {kib} will present to web browsers. | ||
|
||
You may choose to generate a certificate and private key using {ref}/certutil.html[the {es} certutil tool]. At this point, you will have | ||
already set up a certificate authority (CA) to sign the {es} server certificate. You may choose to use the same CA to sign the {kib} client | ||
certificate. You would do this like so: | ||
|
||
[source,sh] | ||
-------------------------------------------------------------------------------- | ||
bin/elasticsearch-certutil cert -ca elastic-stack-ca.p12 -name kibana-client | ||
-------------------------------------------------------------------------------- | ||
|
||
This will generate a certificate and private key in a PKCS #12 keystore named `kibana-client.p12`. The certificate has a Common Name (CN) of | ||
"kibana-client". | ||
|
||
You will also need to use the CA certificate when setting up the PKI realm in {es}. While you could use the CA keystore in the above example | ||
for this purpose, it is bad practice to expose the CA's private key in such a manner. Instead, you can extract the CA certificate (without | ||
its private key) like so: | ||
|
||
[source,sh] | ||
-------------------------------------------------------------------------------- | ||
openssl pkcs12 -in kibana-client.p12 -cacerts -nokeys -out ca.crt | ||
-------------------------------------------------------------------------------- | ||
-- | ||
|
||
. Configure a PKI realm and a Native realm in your {es} cluster: | ||
+ | ||
-- | ||
By default, {es} provides a Native realm. However, to support both a PKI realm (for {kib}) and a Native realm (for end users), you must | ||
configure each realm in `elasticsearch.yml`: | ||
|
||
[source,yaml] | ||
-------------------------------------------------------------------------------- | ||
xpack.security.authc.realms.pki.realm1.order: 1 | ||
xpack.security.authc.realms.pki.realm1.certificate_authorities: "/path/to/ca.crt" | ||
xpack.security.authc.realms.native.realm2.order: 2 | ||
-------------------------------------------------------------------------------- | ||
|
||
-- | ||
|
||
. Configure your {es} cluster to request client certificates: | ||
+ | ||
-- | ||
By default, {es} will not request a client certificate when establishing a TLS connection. To change this, you must set up optional client | ||
certificate authentication in `elasticsearch.yml`: | ||
|
||
[source,yaml] | ||
-------------------------------------------------------------------------------- | ||
xpack.security.http.ssl.client_authentication: "optional" | ||
-------------------------------------------------------------------------------- | ||
-- | ||
|
||
. Restart your {es} cluster. | ||
|
||
. Use {kib} to create a <<role-mappings,role mapping>> for your new client certificate: | ||
+ | ||
-- | ||
This role mapping will assign the `kibana_system` role to any user that matches the included mapping rule, which is set to equal the client | ||
certificate's DN attribute: | ||
|
||
[role="screenshot"] | ||
image:user/security/images/mutual-tls-role-mapping.png["Role mapping for the {kib} client certificate"] | ||
-- | ||
|
||
. Configure {kib} to use the client certificate: | ||
+ | ||
-- | ||
Assuming you used the {es} certutil tool to generate a certificate and private key in a PKCS #12 keystore, add the following values to | ||
`kibana.yml`: | ||
|
||
[source,yaml] | ||
-------------------------------------------------------------------------------- | ||
elasticsearch.ssl.keystore.path: "/path/to/kibana-client.p12" | ||
elasticsearch.ssl.keystore.password: "decryption password" | ||
-------------------------------------------------------------------------------- | ||
|
||
The decryption password should match what you entered when prompted by the {es} certutil tool. | ||
|
||
You must also remove the `elasticsearch.username` and `elasticsearch.password` values from the configuration file. Otherwise, {kib} will | ||
attempt to use those to authenticate via the Native realm. | ||
|
||
TIP: Alternatively, {kib} also supports using a client certificate and private key in PEM format with the `elasticsearch.ssl.certificate` | ||
and `elasticsearch.ssl.key` settings. For more information, see <<settings,{kib} configuration settings>>. | ||
-- | ||
|
||
. Restart {kib}. | ||
|
||
NOTE: The steps above enable {kib} to authenticate to {es} using a certificate. However, end users will only be able to authenticate to | ||
{kib} with a username and password. To allow end users to authenticate to {kib} using certificates, see <<pki-authentication,{kib} PKI | ||
authentication>>. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,4 +5,3 @@ This folder contains example plugins. To run the plugins in this folder, use th | |
``` | ||
yarn start --run-examples | ||
``` | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
{ | ||
"id": "bfetchExplorer", | ||
"version": "0.0.1", | ||
"kibanaVersion": "kibana", | ||
"configPath": ["bfetch_explorer"], | ||
"server": true, | ||
"ui": true, | ||
"requiredPlugins": ["bfetch"], | ||
"optionalPlugins": [] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{ | ||
"name": "bfetch_explorer", | ||
"version": "1.0.0", | ||
"main": "target/examples/bfetch_explorer", | ||
"kibana": { | ||
"version": "kibana", | ||
"templateVersion": "1.0.0" | ||
}, | ||
"license": "Apache-2.0", | ||
"scripts": { | ||
"kbn": "node ../../scripts/kbn.js", | ||
"build": "rm -rf './target' && tsc" | ||
}, | ||
"devDependencies": { | ||
"typescript": "3.7.2" | ||
} | ||
} |
93 changes: 93 additions & 0 deletions
93
examples/bfetch_explorer/public/components/count_until/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
/* | ||
* Licensed to Elasticsearch B.V. under one or more contributor | ||
* license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright | ||
* ownership. Elasticsearch B.V. licenses this file to you under | ||
* the Apache License, Version 2.0 (the "License"); you may | ||
* not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
import React, { useState } from 'react'; | ||
import useMountedState from 'react-use/lib/useMountedState'; | ||
import useList from 'react-use/lib/useList'; | ||
import { EuiForm, EuiSpacer, EuiFieldNumber, EuiFormRow, EuiButton } from '@elastic/eui'; | ||
import { BfetchPublicSetup } from '../../../../../src/plugins/bfetch/public'; | ||
|
||
export interface Props { | ||
fetchStreaming: BfetchPublicSetup['fetchStreaming']; | ||
} | ||
|
||
export const CountUntil: React.FC<Props> = ({ fetchStreaming }) => { | ||
const isMounted = useMountedState(); | ||
const [data, setData] = useState(5); | ||
const [showingResults, setShowingResults] = useState(false); | ||
const [results, { push: pushResult, clear: clearList }] = useList<string>([]); | ||
const [completed, setCompleted] = useState(false); | ||
const [error, setError] = useState<any>(null); | ||
|
||
const handleSubmit = () => { | ||
setShowingResults(true); | ||
const { stream } = fetchStreaming({ | ||
url: '/bfetch_explorer/count', | ||
body: JSON.stringify({ data }), | ||
}); | ||
stream.subscribe({ | ||
next: (next: string) => { | ||
if (!isMounted()) return; | ||
pushResult(next); | ||
}, | ||
error: (nextError: any) => { | ||
if (!isMounted()) return; | ||
setError(nextError); | ||
}, | ||
complete: () => { | ||
if (!isMounted()) return; | ||
setCompleted(true); | ||
}, | ||
}); | ||
}; | ||
|
||
const handleReset = () => { | ||
setShowingResults(false); | ||
clearList(); | ||
setError(null); | ||
setCompleted(false); | ||
}; | ||
|
||
if (showingResults) { | ||
return ( | ||
<EuiForm data-test-subj="CountUntil"> | ||
<pre>{JSON.stringify(error || results, null, 4)}</pre> | ||
<EuiSpacer size="l" /> | ||
<EuiButton disabled={!completed} onClick={handleReset}> | ||
Reset | ||
</EuiButton> | ||
</EuiForm> | ||
); | ||
} | ||
|
||
return ( | ||
<EuiForm data-test-subj="CountUntil"> | ||
<EuiFormRow label="Some integer" fullWidth> | ||
<EuiFieldNumber | ||
placeholder="Some integer" | ||
value={data} | ||
onChange={e => setData(Number(e.target.value))} | ||
/> | ||
</EuiFormRow> | ||
<EuiButton type="submit" fill onClick={handleSubmit}> | ||
Start | ||
</EuiButton> | ||
</EuiForm> | ||
); | ||
}; |
105 changes: 105 additions & 0 deletions
105
examples/bfetch_explorer/public/components/double_integers/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
/* | ||
* Licensed to Elasticsearch B.V. under one or more contributor | ||
* license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright | ||
* ownership. Elasticsearch B.V. licenses this file to you under | ||
* the Apache License, Version 2.0 (the "License"); you may | ||
* not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
import React, { useState } from 'react'; | ||
import useMountedState from 'react-use/lib/useMountedState'; | ||
import useList from 'react-use/lib/useList'; | ||
import useCounter from 'react-use/lib/useCounter'; | ||
import { EuiForm, EuiSpacer, EuiTextArea, EuiFormRow, EuiButton } from '@elastic/eui'; | ||
import { ExplorerService } from '../../plugin'; | ||
|
||
interface ResultItem { | ||
num: number; | ||
result?: { | ||
num: number; | ||
}; | ||
error?: any; | ||
} | ||
|
||
const defaultNumbers = [2000, 300, -1, 1000].join('\n'); | ||
|
||
export interface Props { | ||
double: ExplorerService['double']; | ||
} | ||
|
||
export const DoubleIntegers: React.FC<Props> = ({ double }) => { | ||
const isMounted = useMountedState(); | ||
const [numbers, setNumbers] = useState(defaultNumbers); | ||
const [showingResults, setShowingResults] = useState(false); | ||
const [numberOfResultsAwaiting, counter] = useCounter(0); | ||
const [results, { push: pushResult, clear: clearList }] = useList<ResultItem>([]); | ||
|
||
const handleSubmit = () => { | ||
setShowingResults(true); | ||
const nums = numbers | ||
.split('\n') | ||
.map(num => num.trim()) | ||
.filter(Boolean) | ||
.map(Number); | ||
counter.set(nums.length); | ||
nums.forEach(num => { | ||
double({ num }).then( | ||
result => { | ||
if (!isMounted()) return; | ||
counter.dec(); | ||
pushResult({ num, result }); | ||
}, | ||
error => { | ||
if (!isMounted()) return; | ||
counter.dec(); | ||
pushResult({ num, error }); | ||
} | ||
); | ||
}); | ||
}; | ||
|
||
const handleReset = () => { | ||
setShowingResults(false); | ||
counter.reset(); | ||
clearList(); | ||
}; | ||
|
||
if (showingResults) { | ||
return ( | ||
<EuiForm data-test-subj="DoubleIntegers"> | ||
<pre>{JSON.stringify(results, null, 4)}</pre> | ||
<EuiSpacer size="l" /> | ||
<EuiButton disabled={!!numberOfResultsAwaiting} onClick={handleReset}> | ||
Reset | ||
</EuiButton> | ||
</EuiForm> | ||
); | ||
} | ||
|
||
return ( | ||
<EuiForm data-test-subj="DoubleIntegers"> | ||
<EuiFormRow label="Numbers in ms separated by new line" fullWidth> | ||
<EuiTextArea | ||
fullWidth | ||
placeholder="Enter numbers in milliseconds separated by new line" | ||
value={numbers} | ||
onChange={e => setNumbers(e.target.value)} | ||
/> | ||
</EuiFormRow> | ||
<EuiButton type="submit" fill onClick={handleSubmit}> | ||
Send | ||
</EuiButton> | ||
</EuiForm> | ||
); | ||
}; |
Oops, something went wrong.