Commit e2bb108c authored by Jochen Kressin's avatar Jochen Kressin
Browse files

first OEM integrator features added

parent db0a7469
---
title: System integrators
html_title: Cross Cluster and Tribe
slug: system-integrators-oem-search-guard
category: integrators
order: 100
layout: docs
edition: community
description: How to integrate Search Guard with other products and plugins. For System Integrators and OEM partners.
---
<!---
Copyright 2018 floragunn GmbH
-->
# System integrators
## Injecting a Search Guard user
If you are running an Elasticsearch plugin that has access to the `ThreadContext`, you can inject a Search Guard user directly, bypassing the authentication and authorization steps completely. Use this feature if the product you are integrating Search Guard with performs it's own authentication and authorization.
Search Guard will implicitly trust any injected user. You do not need to add these users to any backend system like LDAP or the internal user database. You can use all features of the role mapping to map injected users to Search Guard roles.
You can use the Search Guard authentication and authorization features and injected users in parallel: When Search Guard detects an injected user, no authentication and authorization steps are performed. If there is no injected user found, the regular authentication and authorization steps apply.
You can enable this feature in elasticsearch.yml by setting:
```
searchguard.unsupported.inject_user.enabled: true
```
Inject a user by adding it as transient header in the ThreadContext:
```
threadContext.putTransient("injected_user", "user_string");
```
If you are compiling against Search Guard, instead of using *injected_user* you can also the the following constant:
```
com.floragunn.searchguard.support.SG_INJECTED_USER
```
### Security risks and caveats
By enabling this feature, you make it possible to inject users in the ThreadContext. Usually, this is done by an Elasticsearch plugin running in front of Search Guard. However, it is also possible to use a `TransportClient` for it. Thus you have to make sure that end users are not able to connect to the Elasticsearch cluster on the transport layer. **Otherwise a malicious attacker can inject any user and impersonate as any user, without having to authenticate!**
If your plugin registers a HTTP transport to intercept REST calls and to inject users, be aware that you cannot use TLS on the REST layer anymore. This is because Elasticsearch only allows one HTTP transport. So the Search Guard TLS HTTP transport has to be disabled.
### Format
The user string has the following format:
```
username|backend roles|remoteIP:port|custom attributes|tenant
```
| Name | Description |
|---|---|
| username | Name of the user. Mandatory. |
| roles | Comma-separated list of backend roles. Optional |
| remoteIP:port | Remote IP and port of the original request. Optional. If missing, Search Guard will perform the standard remote IP lookup.|
| custom attributes | Custom attributes of the user. Comma-separated list of key/value pairs. The number of values has to be an even number. Optional. |
| tenant | The selected tenant for this request. Optional. |
The only mandatory field is the username. You can leave all or parts of the other fields empty.
### Example
Full example:
```
admin|role1,role2|127.0.0:80|key1,value1,key2,value2|mytenant
```
```
Username: admin,
backendroles: ["role1", "role2"],
remoteip: "127.0.0:80",
custom_attributes: {
key1: "value1",
key2: "value2"
},
tenant: "mytenant"
```
Partial example:
```
admin|role1,role2|||mytenant
```
```
Username: admin,
backendroles: ["role1", "role2"],
remoteip: "(set by Search Guard)",
custom_attributes: {},
tenant: "mytenant"
```
Minimal example:
```
admin||||
```
```
Username: admin,
backendroles: [],
remoteip: "(set by Search Guard)",
custom_attributes: {},
tenant: null
```
## Admin access for injected users
You can assign Search Guard admin privileges to any injected user. By doing so, these users will have complete control over the cluster, bypassing any security restriction imposed by Search Guard. Each request these users make will be executed as if a TLS admin certificate was provided.
To activate that feature, configure it in elasticsearch.yml like:
```
searchguard.unsupported.inject_user.enabled: true
```
To assign elevated admin privileges to a user, list the username in the `searchguard.authcz.admin_dn` section in `elasticsearch.yml`:
```
searchguard.authcz.admin_dn:
- injectedadmin
```
Any injected user with username `injectedadmin` will be assigned admin privileges.
**Note: Due to security concerns, this is only possible for injected users. You cannot assign admin privileges for regular users. Use an admin TLS certificate instead.**
You can also mix admin access granted by a TLS certificate and admin access for injected users:
```
searchguard.authcz.admin_dn:
- injectedadmin
- CN=kirk,OU=client,O=client,L=Test,C=DE"
```
Any entry that is not a DN will be treated as usernames, whereas DNs are applied to admin certificates.
## Custom inter-node traffic evaluator
If the provided methods of listing the DNs of node certificates or adding an OID to the certificates does not work for you, you can implement your own class to identify inter-cluster traffic. It must implement the following interface:
```java
com.floragunn.searchguard.transport.InterClusterRequestEvaluator
```
And provide a singe argument constructor that takes a
```java
org.elasticsearch.common.settings.Settings
```
as argument. For example:
```java
public final class MyInterClusterRequestEvaluator
implements InterClusterRequestEvaluator {
public MyInterClusterRequestEvaluator(final Settings settings) {
...
}
@Override
public boolean isInterClusterRequest(
TransportRequest request,
X509Certificate[] localCerts,
X509Certificate[] peerCerts,
final String principal) {
...
}
}
```
Make sure the class is on the classpath, and configure your custom implementation in `elasticsearch.yml`:
```
searchguard.cert.intercluster_request_evaluator_class: ...
```
## Custom Principal Extractor
When using (client) TLS certificates for authentication and authorisation, Search Guard uses the X.500 principal as username by default. If you want to use any other part of the certificate as principal, Search Guard provides a hook for your own implementation.
Create a class that implements the `com.floragunn.searchguard.ssl.transport.PrincipalExtractor` interface:
```java
public interface PrincipalExtractor {
public enum Type {
HTTP,
TRANSPORT
}
/**
* Extract the principal name
*
* Please note that this method gets called for principal
* extraction of other nodes as well as transport clients.
* It's up to the implementer to distinguish between them
* and handle them appropriately.
*
* Implementations must be public classes with a default
* public default constructor.
*
* @param x509Certificate The first X509 certificate in the
* peer certificate chain. This can be null, in this case the
* method must also return <code>null</code>.
*
* @return The principal as string. This may be <code>null</code>
* in case where x509Certificate is null or the principal cannot
* be extracted because of any other circumstances.
*/
String extractPrincipal(X509Certificate x509Certificate, Type type);
}
```
You can then define the Principal Extractor to use in `elasticsearch.yml` like:
```yaml
searchguard.ssl.transport.principal_extractor_class: com.example.MyPrincipalExtractor
```
## Injecting an SSLContext
If you are integrating Search Guard with your own software, you might already have an `javax.net.ssl.SSLContext` object available that you want to use. In this case, instead of building an `SSLContext` from the configured keystore and truststore, you can instruct Search Guard to use your `SSLContext` directly.
Search Guard is able to manage multiple `SSLContext` objects. You need to register the objects you want to use with the `com.floragunn.searchguard.ssl.ExternalSearchGuardKeyStore` and an id first. When constructing the `Settings` object used for instantiating the `TransportClient`, you can configure which `SSLContext` should be used for this `TransportClient`.
Example:
```java
SSLContext sslContext =
ExternalSearchGuardKeyStore.registerExternalSslContext(
"mycontext",
sslContext
);
final Settings tcSettings = Settings.builder()
.put("searchguard.ssl.client.external_context_id", "mycontext")
.put("path.home",".")
...
.build();
Client client = TransportClient.builder()
.settings(tcSettings)
.addPlugin(SearchGuardSSLPlugin.class)
.build()
```
......@@ -106,4 +106,27 @@ To mark a resource `readonly`, add the following flag:
sg_kibana_user:
readonly: true
...
```
\ No newline at end of file
```
## Hidden resources
Any resource can be marked *hidden*. As the name implies, a hidden resource
* is removed from any API GET request result
* when querying for a single hidden resource, a `404` is returned
* when querying for all resources, hidden resources are filtered from the result set
* cannot be deleted
* a `404` is returned instead
* cannot be changed
* a `403` is returned instead
Hidden resources are most useful if you want to give end users access to the REST API, but you want to hide some of the service users your platform is using. For example, the Kibana server user or the logstash user.
Example:
```yaml
sg_kibana_server:
hidden: true
...
```
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment