-
Notifications
You must be signed in to change notification settings - Fork 282
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add allowlist configuration and deprecate whitelist (#1808)
Signed-off-by: cliu123 <[email protected]>
- Loading branch information
Showing
22 changed files
with
999 additions
and
111 deletions.
There are no files selected for viewing
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,69 @@ | ||
--- | ||
_meta: | ||
type: "allowlist" | ||
config_version: 2 | ||
|
||
# Description: | ||
# enabled - feature flag. | ||
# if enabled is false, the allowlisting feature is removed. | ||
# This is like removing the check that checks if an API is allowlisted. | ||
# This is equivalent to continuing with the usual access control checks, and removing all the code that implements allowlisting. | ||
# if enabled is true, then all users except SuperAdmin can access only the APIs in requests | ||
# SuperAdmin can access all APIs. | ||
# SuperAdmin is defined by the SuperAdmin certificate, which is configured in the opensearch.yml setting: plugins.security.authcz.admin_dn: | ||
# Refer to the example setting in opensearch.yml.example, and the opendistro documentation to know more about configuring SuperAdmin. | ||
# | ||
# requests - map of allowlisted endpoints, and the allowlisted HTTP requests for those endpoints | ||
|
||
# Examples showing how to configure this yml file (make sure the _meta data from above is also there): | ||
# Example 1: | ||
# To enable allowlisting and allowlist GET /_cluster/settings | ||
# | ||
#config: | ||
# enabled: true | ||
# requests: | ||
# /_cluster/settings: | ||
# - GET | ||
# | ||
# Example 2: | ||
# If you want to allowlist multiple request methods for /_cluster/settings (GET,PUT): | ||
# | ||
#config: | ||
# enabled: true | ||
# requests: | ||
# /_cluster/settings: | ||
# - GET | ||
# - PUT | ||
# | ||
# Example 3: | ||
# If you want to allowlist other APIs as well, for example GET /_cat/nodes, and GET /_cat/shards: | ||
# | ||
#config: | ||
# enabled: true | ||
# requests: | ||
# /_cluster/settings: | ||
# - GET | ||
# - PUT | ||
# /_cat/nodes: | ||
# - GET | ||
# /_cat/shards: | ||
# - GET | ||
# | ||
# Example 4: | ||
# If you want to disable the allowlisting feature, set enabled to false. | ||
# enabled: false | ||
# requests: | ||
# /_cluster/settings: | ||
# - GET | ||
# | ||
#At this point, all APIs become allowlisted because the feature to allowlist is off, so requests is irrelevant. | ||
|
||
|
||
#this name must be config | ||
config: | ||
enabled: false | ||
requests: | ||
/_cluster/settings: | ||
- GET | ||
/_cat/nodes: | ||
- GET |
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
180 changes: 180 additions & 0 deletions
180
src/main/java/org/opensearch/security/dlic/rest/api/AllowlistApiAction.java
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,180 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"). | ||
* You may not use this file except in compliance with the License. | ||
* A copy of the License is located at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* or in the "license" file accompanying this file. This file 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. | ||
*/ | ||
|
||
|
||
package org.opensearch.security.dlic.rest.api; | ||
|
||
import java.io.IOException; | ||
import java.nio.file.Path; | ||
import java.util.List; | ||
|
||
import com.fasterxml.jackson.databind.JsonNode; | ||
import com.google.common.collect.ImmutableList; | ||
|
||
import org.opensearch.action.index.IndexResponse; | ||
import org.opensearch.client.Client; | ||
import org.opensearch.cluster.service.ClusterService; | ||
import org.opensearch.common.bytes.BytesReference; | ||
import org.opensearch.common.inject.Inject; | ||
import org.opensearch.common.settings.Settings; | ||
import org.opensearch.rest.RestChannel; | ||
import org.opensearch.rest.RestController; | ||
import org.opensearch.rest.RestRequest; | ||
import org.opensearch.security.DefaultObjectMapper; | ||
import org.opensearch.security.auditlog.AuditLog; | ||
import org.opensearch.security.configuration.AdminDNs; | ||
import org.opensearch.security.configuration.ConfigurationRepository; | ||
import org.opensearch.security.dlic.rest.validation.AbstractConfigurationValidator; | ||
import org.opensearch.security.dlic.rest.validation.AllowlistValidator; | ||
import org.opensearch.security.privileges.PrivilegesEvaluator; | ||
import org.opensearch.security.securityconf.impl.CType; | ||
import org.opensearch.security.securityconf.impl.SecurityDynamicConfiguration; | ||
import org.opensearch.security.ssl.transport.PrincipalExtractor; | ||
import org.opensearch.security.support.ConfigConstants; | ||
import org.opensearch.security.tools.SecurityAdmin; | ||
import org.opensearch.threadpool.ThreadPool; | ||
|
||
/** | ||
* This class implements GET and PUT operations to manage dynamic AllowlistingSettings. | ||
* <p> | ||
* These APIs are only accessible to SuperAdmin since the configuration controls what APIs are accessible by normal users. | ||
* Eg: If allowlisting is enabled, and a specific API like "/_cat/nodes" is not allowlisted, then only the SuperAdmin can use "/_cat/nodes" | ||
* These APIs allow the SuperAdmin to enable/disable allowlisting, and also change the list of allowlisted APIs. | ||
* <p> | ||
* A SuperAdmin is identified by a certificate which represents a distinguished name(DN). | ||
* SuperAdmin DN's can be set in {@link ConfigConstants#SECURITY_AUTHCZ_ADMIN_DN} | ||
* SuperAdmin certificate for the default superuser is stored as a kirk.pem file in config folder of OpenSearch | ||
* <p> | ||
* Example calling the PUT API as SuperAdmin using curl (if http basic auth is on): | ||
* curl -v --cacert path_to_config/root-ca.pem --cert path_to_config/kirk.pem --key path_to_config/kirk-key.pem -XPUT https://localhost:9200/_plugins/_security/api/allowlist -H "Content-Type: application/json" -d’ | ||
* { | ||
* "enabled" : false, | ||
* "requests" : {"/_cat/nodes": ["GET"], "/_plugins/_security/api/allowlist": ["GET"]} | ||
* } | ||
* | ||
* Example using the PATCH API to change the requests as SuperAdmin: | ||
* curl -v --cacert path_to_config/root-ca.pem --cert path_to_config/kirk.pem --key path_to_config/kirk-key.pem -XPATCH https://localhost:9200/_plugins/_security/api/allowlist -H "Content-Type: application/json" -d’ | ||
* { | ||
* "op":"replace", | ||
* "path":"/config/requests", | ||
* "value": {"/_cat/nodes": ["GET"], "/_plugins/_security/api/allowlist": ["GET"]} | ||
* } | ||
* | ||
* To update enabled, use the "add" operation instead of the "replace" operation, since boolean variables are not recognized as valid paths when they are false. | ||
* eg: | ||
* curl -v --cacert path_to_config/root-ca.pem --cert path_to_config/kirk.pem --key path_to_config/kirk-key.pem -XPATCH https://localhost:9200/_plugins/_security/api/allowlist -H "Content-Type: application/json" -d’ | ||
* { | ||
* "op":"add", | ||
* "path":"/config/enabled", | ||
* "value": true | ||
* } | ||
* | ||
* The backing data is stored in {@link ConfigConstants#SECURITY_CONFIG_INDEX_NAME} which is populated during bootstrap. | ||
* For existing clusters, {@link SecurityAdmin} tool can | ||
* be used to populate the index. | ||
* <p> | ||
*/ | ||
public class AllowlistApiAction extends PatchableResourceApiAction { | ||
private static final List<Route> routes = ImmutableList.of( | ||
new Route(RestRequest.Method.GET, "/_plugins/_security/api/allowlist"), | ||
new Route(RestRequest.Method.PUT, "/_plugins/_security/api/allowlist"), | ||
new Route(RestRequest.Method.PATCH, "/_plugins/_security/api/allowlist") | ||
); | ||
|
||
private static final String name = "config"; | ||
|
||
@Inject | ||
public AllowlistApiAction(final Settings settings, final Path configPath, final RestController controller, final Client client, | ||
final AdminDNs adminDNs, final ConfigurationRepository cl, final ClusterService cs, | ||
final PrincipalExtractor principalExtractor, final PrivilegesEvaluator evaluator, ThreadPool threadPool, AuditLog auditLog) { | ||
super(settings, configPath, controller, client, adminDNs, cl, cs, principalExtractor, evaluator, threadPool, auditLog); | ||
} | ||
|
||
@Override | ||
protected void handleApiRequest(final RestChannel channel, final RestRequest request, final Client client) throws IOException { | ||
if (!isSuperAdmin()) { | ||
forbidden(channel, "API allowed only for super admin."); | ||
return; | ||
} | ||
super.handleApiRequest(channel, request, client); | ||
} | ||
|
||
@Override | ||
protected void handleGet(final RestChannel channel, RestRequest request, Client client, final JsonNode content) | ||
throws IOException { | ||
|
||
|
||
final SecurityDynamicConfiguration<?> configuration = load(getConfigName(), true); | ||
filter(configuration); | ||
successResponse(channel, configuration); | ||
} | ||
|
||
@Override | ||
protected void handleDelete(final RestChannel channel, final RestRequest request, final Client client, final JsonNode content) throws IOException { | ||
notImplemented(channel, RestRequest.Method.DELETE); | ||
} | ||
|
||
@Override | ||
protected void handlePut(final RestChannel channel, final RestRequest request, final Client client, final JsonNode content) throws IOException { | ||
final SecurityDynamicConfiguration<?> existingConfiguration = load(getConfigName(), false); | ||
|
||
if (existingConfiguration.getSeqNo() < 0) { | ||
forbidden(channel, "Security index need to be updated to support '" + getConfigName().toLCString() + "'. Use SecurityAdmin to populate."); | ||
return; | ||
} | ||
|
||
boolean existed = existingConfiguration.exists(name); | ||
existingConfiguration.putCObject(name, DefaultObjectMapper.readTree(content, existingConfiguration.getImplementingClass())); | ||
|
||
saveAnUpdateConfigs(client, request, getConfigName(), existingConfiguration, new OnSucessActionListener<IndexResponse>(channel) { | ||
|
||
@Override | ||
public void onResponse(IndexResponse response) { | ||
if (existed) { | ||
successResponse(channel, "'" + name + "' updated."); | ||
} else { | ||
createdResponse(channel, "'" + name + "' created."); | ||
} | ||
} | ||
}); | ||
} | ||
|
||
|
||
@Override | ||
public List<Route> routes() { | ||
return routes; | ||
} | ||
|
||
@Override | ||
protected Endpoint getEndpoint() { | ||
return Endpoint.ALLOWLIST; | ||
} | ||
|
||
@Override | ||
protected AbstractConfigurationValidator getValidator(RestRequest request, BytesReference ref, Object... param) { | ||
return new AllowlistValidator(request, ref, this.settings, param); | ||
} | ||
|
||
@Override | ||
protected String getResourceName() { | ||
return name; | ||
} | ||
|
||
@Override | ||
protected CType getConfigName() { | ||
return CType.ALLOWLIST; | ||
} | ||
|
||
} |
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 |
---|---|---|
|
@@ -31,5 +31,6 @@ public enum Endpoint { | |
MIGRATE, | ||
VALIDATE, | ||
WHITELIST, | ||
ALLOWLIST, | ||
NODESDN; | ||
} |
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
Oops, something went wrong.