Skip to content

View API and Rollback API for Versioned Security Configurations#5366

Closed
divyanshi-0402 wants to merge 4 commits intoopensearch-project:mainfrom
divyanshi-0402:securityConfigVersionViewAPI
Closed

View API and Rollback API for Versioned Security Configurations#5366
divyanshi-0402 wants to merge 4 commits intoopensearch-project:mainfrom
divyanshi-0402:securityConfigVersionViewAPI

Conversation

@divyanshi-0402
Copy link
Copy Markdown
Contributor

Description

Implementing View API and Rollback API for Versioned Security Configurations, build upon the changes from the PR : Versioned Security Configuration Management #5357.
Hence, kindly just review the final commit for this PR : 989c1e6

API Design

View Security Configuration Versions

Purpose: View the complete history of security configuration changes, or any specific version of the security configurations.

Endpoint:

  • To view all the versions : GET /_plugins/_security/api/version
  • To view a specific version : GET /_plugins/_security/api/version/{versionId}

Access Control: Admin/Security Manager permissions required

Response Format for specific version:

curl -XGET "https://localhost:9200/_plugins/_security/api/version/v2?pretty" -u 'admin:Divvv@admin123' --insecure

{
  "versions": [
    {
      "version_id": "v2",
      "timestamp": "2025-05-23T06:56:20.081933886Z",
      "modified_by": "admin",
      "security_configs": {
        "rolesmapping": {
          "lastUpdated": "2025-05-23T06:56:20.081933886Z",
          "configData": {
            "all_access": {
              "backend_roles": ["admin"],
              "users": [],
              "hosts": [],
              "reserved": false,
              "hidden": false,
              "description": "Maps admin to all_access",
              "and_backend_roles": []
            },
            ...
          }
        },
        "roles": {
          "lastUpdated": "2025-05-23T06:56:20.081933886Z",
          "configData": {
            "alerting_full_access": {
              "cluster_permissions": [
                "cluster:admin/opendistro/alerting/*",
                "cluster:admin/opensearch/alerting/*",
                ...
              ],
              "index_permissions": [
                {
                  "index_patterns": ["*"],
                  "allowed_actions": ["indices:admin/mappings/get", ...]
                }
              ],
              "reserved": true,
              "hidden": false,
              "static": false
            },
            ...
          }
        },
        "internalusers": {
          "lastUpdated": "2025-05-23T06:56:20.081933886Z",
          "configData": {
            "admin": {
              "backend_roles": ["admin"],
              "reserved": true,
              "description": "Demo admin user",
              ...
            },
            "testuser": {
              "backend_roles": [],
              "reserved": false,
              ...
            },
            ...
          }
        },
        ...
      }
    }
  ]
}

Response Format for all versions :

curl -XGET "https://localhost:9200/_plugins/_security/api/version?pretty" -u 'admin:Divvv@admin123' --insecure

{
  "versions": [
    {
      "version_id": "v1",
      "timestamp": "2025-05-22T08:46:11.887620466Z",
      "modified_by": "system",
      "security_configs": {
        "rolesmapping": {
          "lastUpdated": "2025-05-22T08:46:11.887620466Z",
          "configData": {
            "all_access": {
              "backend_roles": ["admin"],
              "users": [],
              "hosts": [],
              "reserved": false,
              "hidden": false,
              "description": "Maps admin to all_access",
              "and_backend_roles": []
            },
            ...
          }
        },
        "internalusers": {
          "lastUpdated": "2025-05-22T08:46:11.887620466Z",
          "configData": {
            "admin": {
              "backend_roles": ["admin"],
              "reserved": true,
              "hidden": false,
              "description": "Demo admin user",
              ...
            },
            ...
          }
        },
        ...
      }
    },
    {
      "version_id": "v2",
      "timestamp": "2025-05-23T06:56:20.081933886Z",
      "modified_by": "admin",
      "security_configs": {
        "rolesmapping": {
          "lastUpdated": "2025-05-23T06:56:20.081933886Z",
          "configData": {
            "all_access": {
              "backend_roles": ["admin"],
              "users": [],
              "hosts": [],
              "reserved": false,
              "hidden": false,
              "description": "Maps admin to all_access",
              "and_backend_roles": []
            },
            ...
          }
        },
        "internalusers": {
          "lastUpdated": "2025-05-23T06:56:20.081933886Z",
          "configData": {
            "admin": {
              "backend_roles": ["admin"],
              "reserved": true,
              "hidden": false,
              "description": "Demo admin user",
              ...
            },
            "testuser": {
              "backend_roles": [],
              "reserved": false,
              "hidden": false,
              ...
            },
            ...
          }
        },
        ...
      }
    },
    ...
  ]
}

Response format if the version doesn't exist :

curl -XGET "https://localhost:9200/_plugins/_security/api/version/v3?pretty" -u 'admin:Divvv@admin123' --insecure
{
  "status" : "NOT_FOUND",
  "message" : "Version v3 not found"
}

Rollback to desired Security Configuration Versions

Purpose : Allows rollback to immediate or any desired version of security

Endpoint:

  • To rollback to immediate previous version : POST /_plugins/_security/api/rollback
  • To rollback to a specific version : POST /_plugins/_security/api/rollback/version/{versionID}

Access Control: Admin/Security Manager permissions required

Response format to rollback to immediate previous version :

[.opendistro_security_config_versions] index has 8 versions 

curl -XPOST "https://localhost:9200/_plugins/_security/api/rollback" -u 'admin:Divvv@admin123' --insecure           
{
  "status" : "OK",
  "message" : "config rolled back to version v7"
}


 Detected changes in security configuration: [{"op":"add","path":"/internalusers/testuser","value":{"attributes":{},"backend_roles":[],"hash":"$2y$12$3q6lxV8DBxvifcRJ4tMuUeclwyJzawJTzhY.JcKEpL1TdWy.JeUPu","hidden":false,"opendistro_security_roles":[],"reserved":false,"static":false}}]
 Successfully saved version v9 to .opendistro_security_config_versions

Response format to rollback to a specific version :

curl -XPOST "https://localhost:9200/_plugins/_security/api/rollback/version/v3" -u 'admin:Divvv@admin123' --insecure
{
  "status" : "OK",
  "message" : "config rolled back to version v3"
}% 


Detected changes in security configuration: [{"op":"remove","path":"/internalusers/testuser"}]
Successfully saved version v10 to .opendistro_security_config_versions

Response format if the version doesn't exist :

curl -XPOST "https://localhost:9200/_plugins/_security/api/rollback/version/v13" -u 'admin:Divvv@admin123' --insecure
{
  "status" : "NOT_FOUND",
  "message" : "Version v13 not found"
}

Issues Resolved

Related to #5093

Testing

Unit Tests and Integration Tests included

Check List

  • New functionality includes testing
  • New functionality has been documented
  • New Roles/Permissions have a corresponding security dashboards plugin PR
  • API changes companion pull request created
  • Commits are signed per the DCO using --signoff

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.

Divyanshi Chouksey added 3 commits May 22, 2025 02:01
Signed-off-by: Divyanshi Chouksey <divvv@amazon.com>
Signed-off-by: Divyanshi Chouksey <divvv@amazon.com>
Signed-off-by: Divyanshi Chouksey <divvv@amazon.com>
Signed-off-by: Divyanshi Chouksey <77962346+divyanshi-0402@users.noreply.github.com>
@codecov
Copy link
Copy Markdown

codecov bot commented May 31, 2025

Codecov Report

Attention: Patch coverage is 74.23971% with 144 lines in your changes missing coverage. Please review.

Project coverage is 72.24%. Comparing base (45e541d) to head (8d642ef).
Report is 30 commits behind head on main.

Files with missing lines Patch % Lines
...curity/dlic/rest/api/RollbackVersionApiAction.java 62.32% 47 Missing and 8 partials ⚠️
...ty/configuration/SecurityConfigVersionsLoader.java 59.25% 27 Missing and 6 partials ⚠️
...ty/configuration/SecurityConfigVersionHandler.java 77.46% 27 Missing and 5 partials ⚠️
...ty/configuration/SecurityConfigDiffCalculator.java 68.08% 10 Missing and 5 partials ⚠️
...h/security/dlic/rest/api/ViewVersionApiAction.java 90.76% 6 Missing ⚠️
...y/configuration/SecurityConfigVersionDocument.java 94.64% 0 Missing and 3 partials ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #5366      +/-   ##
==========================================
+ Coverage   72.18%   72.24%   +0.06%     
==========================================
  Files         382      388       +6     
  Lines       23628    24185     +557     
  Branches     3629     3681      +52     
==========================================
+ Hits        17055    17473     +418     
- Misses       4789     4901     +112     
- Partials     1784     1811      +27     
Files with missing lines Coverage Δ
.../opensearch/security/OpenSearchSecurityPlugin.java 84.72% <100.00%> (+0.03%) ⬆️
...arch/security/dlic/rest/api/AbstractApiAction.java 88.46% <100.00%> (+0.04%) ⬆️
...rg/opensearch/security/dlic/rest/api/Endpoint.java 100.00% <100.00%> (ø)
...security/dlic/rest/api/SecurityRestApiActions.java 90.00% <100.00%> (+10.00%) ⬆️
...ch/security/securityconf/DynamicConfigFactory.java 63.81% <100.00%> (+1.48%) ⬆️
...ecurityconf/impl/SecurityDynamicConfiguration.java 83.56% <100.00%> (+0.46%) ⬆️
...g/opensearch/security/support/ConfigConstants.java 95.23% <ø> (ø)
...y/configuration/SecurityConfigVersionDocument.java 94.64% <94.64%> (ø)
...h/security/dlic/rest/api/ViewVersionApiAction.java 90.76% <90.76%> (ø)
...ty/configuration/SecurityConfigDiffCalculator.java 68.08% <68.08%> (ø)
... and 3 more

... and 5 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

SSL;
SSL,
VIEW_VERSION,
ROLLBACK_VERSION;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two should be grouped under VERSION.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/**
* REST endpoint:
* POST /_plugins/_security/api/rollback
* POST /_plugins/_security/api/rollback/version/{versionID}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the endpoints should be prefixed as /_plugins/_security/api/version/rollback to follow correct verbiage.

*/
protected void consumeParameters(final RestRequest request) {
request.param("name");
request.param("versionID");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move this to the view and rollback API actions and over-ride consumeParams there to consume versionID


private ValidationResult<SecurityConfiguration> rollbackToPreviousVersion() throws IOException {
SecurityConfigVersionDocument doc = versionsLoader.loadFullDocument();
SecurityConfigVersionsLoader.sortVersionsById(doc.getVersions());
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorting should be done post validation of the size

Comment on lines +131 to +202
private ValidationResult<SecurityConfiguration> handlePostRequest(RestRequest request) throws IOException {
String versionParam = request.param("versionID");
try {
if (versionParam == null) {
return rollbackToPreviousVersion();
} else {
return rollbackToSpecificVersion(versionParam);
}
} catch (Exception e) {
log.error("Rollback request failed", e);
return ValidationResult.error(INTERNAL_SERVER_ERROR, payload(INTERNAL_SERVER_ERROR, e.getMessage()));
}
}

private ValidationResult<SecurityConfiguration> rollbackToPreviousVersion() throws IOException {
SecurityConfigVersionDocument doc = versionsLoader.loadFullDocument();
SecurityConfigVersionsLoader.sortVersionsById(doc.getVersions());
var versions = doc.getVersions();

if (versions.size() < 2) {
return ValidationResult.error(NOT_FOUND, payload(NOT_FOUND, "No previous version available to rollback"));
}

String previousVersionId = versions.get(versions.size() - 2).getVersion_id();
return rollbackCommon(previousVersionId, doc);
}

private ValidationResult<SecurityConfiguration> rollbackToSpecificVersion(String versionId) throws IOException {
SecurityConfigVersionDocument doc = versionsLoader.loadFullDocument();
SecurityConfigVersionsLoader.sortVersionsById(doc.getVersions());

var maybeVer = doc.getVersions().stream().filter(v -> versionId.equals(v.getVersion_id())).findFirst();

if (maybeVer.isEmpty()) {
return ValidationResult.error(NOT_FOUND, payload(NOT_FOUND, "Version " + versionId + " not found"));
}

return rollbackCommon(versionId, doc);
}

private ValidationResult<SecurityConfiguration> rollbackCommon(String versionId, SecurityConfigVersionDocument doc) throws IOException {
SecurityConfigVersionsLoader.sortVersionsById(doc.getVersions());
var maybeVer = doc.getVersions().stream().filter(v -> versionId.equals(v.getVersion_id())).findFirst().orElse(null);

if (maybeVer == null) {
return ValidationResult.error(NOT_FOUND, payload(NOT_FOUND, "Version " + versionId + " not found"));
}

try {

rollbackConfigsToSecurityIndex(maybeVer);

ThreadContext threadContext = threadPool.getThreadContext();

EventBus.getDefault()
.register(
new SecurityConfigVersionHandler(configRepository, clusterService.getSettings(), threadContext, threadPool, client)
);

EventBus.getDefault().post(new SecurityConfigChangeEvent());

return ValidationResult.error(OK, (builder, params) -> {
XContentBuilder inner = buildRollbackResponseJson(versionId);
builder.copyCurrentStructure(JsonXContent.jsonXContent.createParser(null, null, BytesReference.bytes(inner).streamInput()));
return builder;
});

} catch (Exception e) {
log.error("Rollback to version {} failed", versionId, e);
return ValidationResult.error(INTERNAL_SERVER_ERROR, payload(INTERNAL_SERVER_ERROR, "Rollback failed: " + e.getMessage()));
}
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
private ValidationResult<SecurityConfiguration> handlePostRequest(RestRequest request) throws IOException {
String versionParam = request.param("versionID");
try {
if (versionParam == null) {
return rollbackToPreviousVersion();
} else {
return rollbackToSpecificVersion(versionParam);
}
} catch (Exception e) {
log.error("Rollback request failed", e);
return ValidationResult.error(INTERNAL_SERVER_ERROR, payload(INTERNAL_SERVER_ERROR, e.getMessage()));
}
}
private ValidationResult<SecurityConfiguration> rollbackToPreviousVersion() throws IOException {
SecurityConfigVersionDocument doc = versionsLoader.loadFullDocument();
SecurityConfigVersionsLoader.sortVersionsById(doc.getVersions());
var versions = doc.getVersions();
if (versions.size() < 2) {
return ValidationResult.error(NOT_FOUND, payload(NOT_FOUND, "No previous version available to rollback"));
}
String previousVersionId = versions.get(versions.size() - 2).getVersion_id();
return rollbackCommon(previousVersionId, doc);
}
private ValidationResult<SecurityConfiguration> rollbackToSpecificVersion(String versionId) throws IOException {
SecurityConfigVersionDocument doc = versionsLoader.loadFullDocument();
SecurityConfigVersionsLoader.sortVersionsById(doc.getVersions());
var maybeVer = doc.getVersions().stream().filter(v -> versionId.equals(v.getVersion_id())).findFirst();
if (maybeVer.isEmpty()) {
return ValidationResult.error(NOT_FOUND, payload(NOT_FOUND, "Version " + versionId + " not found"));
}
return rollbackCommon(versionId, doc);
}
private ValidationResult<SecurityConfiguration> rollbackCommon(String versionId, SecurityConfigVersionDocument doc) throws IOException {
SecurityConfigVersionsLoader.sortVersionsById(doc.getVersions());
var maybeVer = doc.getVersions().stream().filter(v -> versionId.equals(v.getVersion_id())).findFirst().orElse(null);
if (maybeVer == null) {
return ValidationResult.error(NOT_FOUND, payload(NOT_FOUND, "Version " + versionId + " not found"));
}
try {
rollbackConfigsToSecurityIndex(maybeVer);
ThreadContext threadContext = threadPool.getThreadContext();
EventBus.getDefault()
.register(
new SecurityConfigVersionHandler(configRepository, clusterService.getSettings(), threadContext, threadPool, client)
);
EventBus.getDefault().post(new SecurityConfigChangeEvent());
return ValidationResult.error(OK, (builder, params) -> {
XContentBuilder inner = buildRollbackResponseJson(versionId);
builder.copyCurrentStructure(JsonXContent.jsonXContent.createParser(null, null, BytesReference.bytes(inner).streamInput()));
return builder;
});
} catch (Exception e) {
log.error("Rollback to version {} failed", versionId, e);
return ValidationResult.error(INTERNAL_SERVER_ERROR, payload(INTERNAL_SERVER_ERROR, "Rollback failed: " + e.getMessage()));
}
}
private ValidationResult<SecurityConfiguration> handlePostRequest(RestRequest request) throws IOException {
String versionParam = request.param("versionID");
try {
rollBack(versionParam);
} catch (Exception e) {
log.error("Rollback request failed", e);
return ValidationResult.error(INTERNAL_SERVER_ERROR, payload(INTERNAL_SERVER_ERROR, e.getMessage()));
}
}
private ValidationResult<SecurityConfiguration> rollBack(String rollBackVersionId) throws IOException {
SecurityConfigVersionDocument doc = versionsLoader.loadFullDocument();
if (doc.getVersions().size() < 2) {
return ValidationResult.error(NOT_FOUND, payload(NOT_FOUND, "No previous version available to rollback"));
}
SecurityConfigVersionsLoader.sortVersionsById(doc.getVersions());
var docVersions = doc.getVersions();
if (rollBackVersionId != null) {
rollBackVersionId = doc.getVersions().stream().filter(v -> rollBackVersionId.equals(v.getVersion_id())).findFirst();
if (rollBackVersionId.isEmpty()) {
return ValidationResult.error(NOT_FOUND, payload(NOT_FOUND, "Version " + rollBackVersionId + " not found"));
}
} else {
rollBackVersionId = docVersions.get(docVersions.size() - 2).getVersion_id();
}
try {
rollbackConfigsToSecurityIndex(rollBackVersionI);
ThreadContext threadContext = threadPool.getThreadContext();
EventBus.getDefault()
.register(
new SecurityConfigVersionHandler(configRepository, clusterService.getSettings(), threadContext, threadPool, client)
);
EventBus.getDefault().post(new SecurityConfigChangeEvent());
return ValidationResult.error(OK, (builder, params) -> {
XContentBuilder inner = buildRollbackResponseJson(versionId);
builder.copyCurrentStructure(JsonXContent.jsonXContent.createParser(null, null, BytesReference.bytes(inner).streamInput()));
return builder;
});
} catch (Exception e) {
log.error("Rollback to version {} failed", versionId, e);
return ValidationResult.error(INTERNAL_SERVER_ERROR, payload(INTERNAL_SERVER_ERROR, "Rollback failed: " + e.getMessage()));
}
}

}

@Override
protected EndpointValidator createEndpointValidator() {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need to over-ride this method?

Comment on lines +89 to +128
private ValidationResult<SecurityConfiguration> handleGetRequest(String versionParam) throws IOException {
LOGGER.info("Called handleGetRequest with versionParam={}", versionParam);
try {
if (versionParam == null) {
return viewAllVersions();
} else {
return viewSpecificVersion(versionParam);
}
} catch (Exception e) {
return ValidationResult.error(RestStatus.INTERNAL_SERVER_ERROR, payload(RestStatus.INTERNAL_SERVER_ERROR, e.getMessage()));
}
}

private ValidationResult<SecurityConfiguration> viewAllVersions() throws IOException {
SecurityConfigVersionDocument doc = versionsLoader.loadFullDocument();
SecurityConfigVersionsLoader.sortVersionsById(doc.getVersions());

return ValidationResult.error(OK, (builder, params) -> {
XContentBuilder inner = buildVersionsJsonBuilder(doc.getVersions());
builder.copyCurrentStructure(JsonXContent.jsonXContent.createParser(null, null, BytesReference.bytes(inner).streamInput()));
return builder;
});
}

private ValidationResult<SecurityConfiguration> viewSpecificVersion(String versionId) throws IOException {
SecurityConfigVersionDocument doc = versionsLoader.loadFullDocument();
SecurityConfigVersionsLoader.sortVersionsById(doc.getVersions());

var maybeVer = doc.getVersions().stream().filter(v -> versionId.equals(v.getVersion_id())).findFirst();

if (maybeVer.isEmpty()) {
return ValidationResult.error(NOT_FOUND, payload(NOT_FOUND, "Version " + versionId + " not found"));
}

return ValidationResult.error(OK, (builder, params) -> {
XContentBuilder inner = buildVersionsJsonBuilder(List.of(maybeVer.get()));
builder.copyCurrentStructure(JsonXContent.jsonXContent.createParser(null, null, BytesReference.bytes(inner).streamInput()));
return builder;
});
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
private ValidationResult<SecurityConfiguration> handleGetRequest(String versionParam) throws IOException {
LOGGER.info("Called handleGetRequest with versionParam={}", versionParam);
try {
if (versionParam == null) {
return viewAllVersions();
} else {
return viewSpecificVersion(versionParam);
}
} catch (Exception e) {
return ValidationResult.error(RestStatus.INTERNAL_SERVER_ERROR, payload(RestStatus.INTERNAL_SERVER_ERROR, e.getMessage()));
}
}
private ValidationResult<SecurityConfiguration> viewAllVersions() throws IOException {
SecurityConfigVersionDocument doc = versionsLoader.loadFullDocument();
SecurityConfigVersionsLoader.sortVersionsById(doc.getVersions());
return ValidationResult.error(OK, (builder, params) -> {
XContentBuilder inner = buildVersionsJsonBuilder(doc.getVersions());
builder.copyCurrentStructure(JsonXContent.jsonXContent.createParser(null, null, BytesReference.bytes(inner).streamInput()));
return builder;
});
}
private ValidationResult<SecurityConfiguration> viewSpecificVersion(String versionId) throws IOException {
SecurityConfigVersionDocument doc = versionsLoader.loadFullDocument();
SecurityConfigVersionsLoader.sortVersionsById(doc.getVersions());
var maybeVer = doc.getVersions().stream().filter(v -> versionId.equals(v.getVersion_id())).findFirst();
if (maybeVer.isEmpty()) {
return ValidationResult.error(NOT_FOUND, payload(NOT_FOUND, "Version " + versionId + " not found"));
}
return ValidationResult.error(OK, (builder, params) -> {
XContentBuilder inner = buildVersionsJsonBuilder(List.of(maybeVer.get()));
builder.copyCurrentStructure(JsonXContent.jsonXContent.createParser(null, null, BytesReference.bytes(inner).streamInput()));
return builder;
});
}
private ValidationResult<SecurityConfiguration> handleGetRequest(String versionId) throws IOException {
try {
viewVersions(versionId);
} catch (Exception e) {
return ValidationResult.error(RestStatus.INTERNAL_SERVER_ERROR, payload(RestStatus.INTERNAL_SERVER_ERROR, e.getMessage()));
}
}
private ValidationResult<SecurityConfiguration> viewVersion(String versionId) throws IOException {
SecurityConfigVersionDocument doc = versionsLoader.loadFullDocument();
if (versionId.isEmpty()) {
LOGGER.info("Fetching doc with all versions");
} else if (.isEmpty()) {
return ValidationResult.error(NOT_FOUND, payload(NOT_FOUND, "Version " + versionId + " not found"));
} else {
LOGGER.info("Fetching doc version {}", versionId);
}
return ValidationResult.error(OK, (builder, params) -> {
XContentBuilder inner = buildVersionsJsonBuilder(versionId.isEmpty() ? doc.getVersions() : List.of(versionId));
builder.copyCurrentStructure(JsonXContent.jsonXContent.createParser(null, null, BytesReference.bytes(inner).streamInput()));
return builder;
});
}

* Build the JSON structure:
*/

private XContentBuilder buildVersionsJsonBuilder(List<SecurityConfigVersionDocument.Version<?>> versions) throws IOException {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we usually name these methods as toXContent()

}

@Override
protected EndpointValidator createEndpointValidator() {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need this override?

@DarshitChanpura
Copy link
Copy Markdown
Member

In addition to the comments above we should make these APIs protected with rest-admin API permission.

@nagarajg17
Copy link
Copy Markdown
Contributor

@divyanshi-0402 Lets mark this PR as draft until me make all the required changes based on changes in previous PR

@divyanshi-0402 divyanshi-0402 marked this pull request as draft June 16, 2025 06:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants