-
Notifications
You must be signed in to change notification settings - Fork 343
Api token authc/z implementation with Cache #4992
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 10 commits
9f695fa
d3fcc4a
6904317
17bca93
92d4e60
22cfbe8
665b9e9
e39df0d
ad63974
73eb2ab
6418226
bc8aacf
b90bae9
552aeda
aa506e7
d9cf78d
d7b7e47
6571d9d
9fcb720
e44072c
0927d99
fb79014
0f60569
6634896
83769b1
685dcfc
6ffc060
763a9ff
a685951
77ad6c3
7a20de3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,112 @@ | ||
| /* | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| * | ||
| * The OpenSearch Contributors require contributions made to | ||
| * this file be licensed under the Apache-2.0 license or a | ||
| * compatible open source license. | ||
| */ | ||
|
|
||
| package org.opensearch.security.action.apitokens; | ||
|
|
||
| import java.io.IOException; | ||
| import java.util.Map; | ||
| import java.util.concurrent.ConcurrentHashMap; | ||
|
|
||
| import org.apache.logging.log4j.LogManager; | ||
| import org.apache.logging.log4j.Logger; | ||
|
|
||
| import org.opensearch.common.xcontent.LoggingDeprecationHandler; | ||
| import org.opensearch.common.xcontent.XContentType; | ||
| import org.opensearch.core.common.bytes.BytesReference; | ||
| import org.opensearch.core.index.shard.ShardId; | ||
| import org.opensearch.core.xcontent.NamedXContentRegistry; | ||
| import org.opensearch.core.xcontent.XContentParser; | ||
| import org.opensearch.index.engine.Engine; | ||
| import org.opensearch.index.shard.IndexingOperationListener; | ||
|
|
||
| /** | ||
| * This class implements an index operation listener for operations performed on api tokens | ||
| * These indices are defined on bootstrap and configured to listen in OpenSearchSecurityPlugin.java | ||
| */ | ||
| public class ApiTokenIndexListenerCache implements IndexingOperationListener { | ||
|
|
||
| private final static Logger log = LogManager.getLogger(ApiTokenIndexListenerCache.class); | ||
|
|
||
| private static final ApiTokenIndexListenerCache INSTANCE = new ApiTokenIndexListenerCache(); | ||
| private final ConcurrentHashMap<String, String> idToJtiMap = new ConcurrentHashMap<>(); | ||
|
|
||
| private Map<String, Permissions> jtis = new ConcurrentHashMap<>(); | ||
|
|
||
| private boolean initialized; | ||
|
|
||
| private ApiTokenIndexListenerCache() {} | ||
|
|
||
| public static ApiTokenIndexListenerCache getInstance() { | ||
| return ApiTokenIndexListenerCache.INSTANCE; | ||
| } | ||
|
|
||
| /** | ||
| * Initializes the ApiTokenIndexListenerCache. | ||
| * This method is called during the plugin's initialization process. | ||
| * | ||
| */ | ||
| public void initialize() { | ||
|
|
||
| if (initialized) { | ||
| return; | ||
|
Check warning on line 56 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenIndexListenerCache.java
|
||
| } | ||
|
|
||
| initialized = true; | ||
|
Check warning on line 59 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenIndexListenerCache.java
|
||
|
|
||
| } | ||
|
Check warning on line 61 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenIndexListenerCache.java
|
||
|
|
||
| public boolean isInitialized() { | ||
| return initialized; | ||
|
Check warning on line 64 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenIndexListenerCache.java
|
||
| } | ||
|
|
||
| /** | ||
| * This method is called after an index operation is performed. | ||
| * It adds the JTI of the indexed document to the cache and maps the document ID to the JTI (for deletion handling). | ||
| * @param shardId The shard ID of the index where the operation was performed. | ||
| * @param index The index where the operation was performed. | ||
| * @param result The result of the index operation. | ||
| */ | ||
| @Override | ||
| public void postIndex(ShardId shardId, Engine.Index index, Engine.IndexResult result) { | ||
| BytesReference sourceRef = index.source(); | ||
|
Check warning on line 76 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenIndexListenerCache.java
|
||
|
|
||
| try { | ||
| XContentParser parser = XContentType.JSON.xContent() | ||
| .createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, sourceRef.streamInput()); | ||
|
Check warning on line 80 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenIndexListenerCache.java
|
||
|
|
||
| ApiToken token = ApiToken.fromXContent(parser); | ||
| jtis.put(token.getJti(), new Permissions(token.getClusterPermissions(), token.getIndexPermissions())); | ||
| idToJtiMap.put(index.id(), token.getJti()); | ||
|
Check warning on line 84 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenIndexListenerCache.java
|
||
|
|
||
| } catch (IOException e) { | ||
| log.error("Failed to parse indexed document", e); | ||
| } | ||
| } | ||
|
Check warning on line 89 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenIndexListenerCache.java
|
||
|
|
||
| /** | ||
| * This method is called after a delete operation is performed. | ||
| * It deletes the corresponding document id in the map and the corresponding jti from the cache. | ||
| * @param shardId The shard ID of the index where the delete operation was performed. | ||
| * @param delete The delete operation that was performed. | ||
| * @param result The result of the delete operation. | ||
| */ | ||
| @Override | ||
| public void postDelete(ShardId shardId, Engine.Delete delete, Engine.DeleteResult result) { | ||
| String docId = delete.id(); | ||
| String jti = idToJtiMap.remove(docId); | ||
|
Check warning on line 101 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenIndexListenerCache.java
|
||
| if (jti != null) { | ||
| jtis.remove(jti); | ||
| log.debug("Removed token with ID {} and JTI {} from cache", docId, jti); | ||
|
Check warning on line 104 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenIndexListenerCache.java
|
||
| } | ||
| } | ||
|
Check warning on line 106 in src/main/java/org/opensearch/security/action/apitokens/ApiTokenIndexListenerCache.java
|
||
|
|
||
| public Map<String, Permissions> getJtis() { | ||
| return jtis; | ||
| } | ||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| /* | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| * | ||
| * The OpenSearch Contributors require contributions made to | ||
| * this file be licensed under the Apache-2.0 license or a | ||
| * compatible open source license. | ||
| */ | ||
|
|
||
| package org.opensearch.security.action.apitokens; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| public class Permissions { | ||
| private List<String> clusterPerm; | ||
| private List<ApiToken.IndexPermission> indexPermission; | ||
|
|
||
| // Constructor | ||
| public Permissions(List<String> clusterPerm, List<ApiToken.IndexPermission> indexPermission) { | ||
| this.clusterPerm = clusterPerm; | ||
| this.indexPermission = indexPermission; | ||
| } | ||
|
|
||
| // Getters and setters | ||
| public List<String> getClusterPerm() { | ||
| return clusterPerm; | ||
| } | ||
|
|
||
| public void setClusterPerm(List<String> clusterPerm) { | ||
| this.clusterPerm = clusterPerm; | ||
| } | ||
|
|
||
| public List<ApiToken.IndexPermission> getIndexPermission() { | ||
| return indexPermission; | ||
| } | ||
|
|
||
| public void setIndexPermission(List<ApiToken.IndexPermission> indexPermission) { | ||
| this.indexPermission = indexPermission; | ||
| } | ||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -584,22 +584,24 @@ | |
| originalSource = "{}"; | ||
| } | ||
| if (securityIndicesMatcher.test(shardId.getIndexName())) { | ||
| try ( | ||
| XContentParser parser = XContentHelper.createParser( | ||
| NamedXContentRegistry.EMPTY, | ||
| THROW_UNSUPPORTED_OPERATION, | ||
| originalResult.internalSourceRef(), | ||
| XContentType.JSON | ||
| ) | ||
| ) { | ||
| Object base64 = parser.map().values().iterator().next(); | ||
| if (base64 instanceof String) { | ||
| originalSource = (new String(BaseEncoding.base64().decode((String) base64), StandardCharsets.UTF_8)); | ||
| } else { | ||
| originalSource = XContentHelper.convertToJson(originalResult.internalSourceRef(), false, XContentType.JSON); | ||
| if (originalSource == null) { | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Changes in this file are to correct a mis-merge that happened in prior PRs to this feature branch. |
||
| try ( | ||
| XContentParser parser = XContentHelper.createParser( | ||
| NamedXContentRegistry.EMPTY, | ||
| THROW_UNSUPPORTED_OPERATION, | ||
| originalResult.internalSourceRef(), | ||
| XContentType.JSON | ||
| ) | ||
| ) { | ||
| Object base64 = parser.map().values().iterator().next(); | ||
| if (base64 instanceof String) { | ||
| originalSource = (new String(BaseEncoding.base64().decode((String) base64), StandardCharsets.UTF_8)); | ||
| } else { | ||
| originalSource = XContentHelper.convertToJson(originalResult.internalSourceRef(), false, XContentType.JSON); | ||
| } | ||
| } catch (Exception e) { | ||
| log.error(e.toString()); | ||
| } | ||
| } catch (Exception e) { | ||
| log.error(e.toString()); | ||
| } | ||
|
|
||
| try ( | ||
|
|
@@ -640,7 +642,7 @@ | |
| } | ||
| } | ||
|
|
||
| if (!complianceConfig.shouldLogWriteMetadataOnly()) { | ||
| if (!complianceConfig.shouldLogWriteMetadataOnly() && !complianceConfig.shouldLogDiffsForWrite()) { | ||
| if (securityIndicesMatcher.test(shardId.getIndexName())) { | ||
| // current source, normally not null or empty | ||
| try ( | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.