Skip to content

Commit

Permalink
Feature/extensions bwc setting (opensearch-project#3180)
Browse files Browse the repository at this point in the history
### Description
This Draft PR includes the new setting bwcPluginMode (backward
compatible plugin mode for extensions )

### Issues Resolved
opensearch-project#2616 

Is this a backport? If so, please add backport PR # and/or commits #

### Testing
[Please provide details of testing done: unit testing, integration
testing and manual testing]

### Check List
- [ ] New functionality includes testing
- [ ] New functionality has been documented
- [x] 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](https://github.com/opensearch-project/OpenSearch/blob/main/CONTRIBUTING.md#developer-certificate-of-origin).

---------

Signed-off-by: Sam <[email protected]>
  • Loading branch information
samuelcostae authored Aug 18, 2023
1 parent 91f4478 commit 8a96cab
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@
import org.opensearch.indices.IndicesService;
import org.opensearch.indices.SystemIndexDescriptor;
import org.opensearch.plugins.ClusterPlugin;
import org.opensearch.plugins.ExtensionAwarePlugin;
import org.opensearch.plugins.MapperPlugin;
import org.opensearch.repositories.RepositoriesService;
import org.opensearch.rest.RestController;
Expand Down Expand Up @@ -194,7 +195,15 @@
import org.opensearch.watcher.ResourceWatcherService;
// CS-ENFORCE-SINGLE

public final class OpenSearchSecurityPlugin extends OpenSearchSecuritySSLPlugin implements ClusterPlugin, MapperPlugin {
public final class OpenSearchSecurityPlugin extends OpenSearchSecuritySSLPlugin
implements
ClusterPlugin,
MapperPlugin,
// CS-SUPPRESS-SINGLE: RegexpSingleline get Extensions Settings
ExtensionAwarePlugin
// CS-ENFORCE-SINGLE

{

private static final String KEYWORD = ".keyword";
private static final Logger actionTrace = LogManager.getLogger("opendistro_security_action_trace");
Expand Down Expand Up @@ -1110,6 +1119,23 @@ public Settings additionalSettings() {
}
return builder.build();
}
// CS-SUPPRESS-SINGLE: RegexpSingleline get Extensions Settings

@Override
public List<Setting<?>> getExtensionSettings() {
List<Setting<?>> extensionSettings = new ArrayList<Setting<?>>();

extensionSettings.add(
Setting.boolSetting(
ConfigConstants.EXTENSIONS_BWC_PLUGIN_MODE,
ConfigConstants.EXTENSIONS_BWC_PLUGIN_MODE_DEFAULT,
Property.ExtensionScope,
Property.Final
)
);
return extensionSettings;
}
// CS-ENFORCE-SINGLE:

@Override
public List<Setting<?>> getSettings() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.apache.logging.log4j.Logger;

import org.opensearch.common.settings.Settings;
import org.opensearch.security.support.ConfigConstants;

public class JwtVendor {
private static final Logger logger = LogManager.getLogger(JwtVendor.class);
Expand All @@ -40,6 +41,7 @@ public class JwtVendor {
private final JsonWebKey signingKey;
private final JoseJwtProducer jwtProducer;
private final LongSupplier timeProvider;
private final Boolean bwcModeEnabled;

public JwtVendor(final Settings settings, final Optional<LongSupplier> timeProvider) {
JoseJwtProducer jwtProducer = new JoseJwtProducer();
Expand All @@ -59,6 +61,12 @@ public JwtVendor(final Settings settings, final Optional<LongSupplier> timeProvi
} else {
this.timeProvider = () -> System.currentTimeMillis() / 1000;
}
// CS-SUPPRESS-SINGLE: RegexpSingleline get Extensions Settings
this.bwcModeEnabled = settings.getAsBoolean(
ConfigConstants.EXTENSIONS_BWC_PLUGIN_MODE,
ConfigConstants.EXTENSIONS_BWC_PLUGIN_MODE_DEFAULT
);
// CS-ENFORCE-SINGLE
}

/*
Expand Down Expand Up @@ -142,7 +150,10 @@ public String createJwt(
throw new Exception("Roles cannot be null");
}

/* TODO: If the backendRoles is not null and the BWC Mode is on, put them into the "dbr" claim */
if (bwcModeEnabled && backendRoles != null) {
String listOfBackendRoles = String.join(",", backendRoles);
jwtClaims.setProperty("dbr", listOfBackendRoles);
}

String encodedJwt = jwtProducer.processJwt(jwt);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,11 @@ public enum RolesMappingResolution {
public static final String TENANCY_GLOBAL_TENANT_NAME = "global";
public static final String TENANCY_GLOBAL_TENANT_DEFAULT_NAME = "";

// CS-SUPPRESS-SINGLE: RegexpSingleline get Extensions Settings
public static final String EXTENSIONS_BWC_PLUGIN_MODE = "bwcPluginMode";
public static final boolean EXTENSIONS_BWC_PLUGIN_MODE_DEFAULT = false;
// CS-ENFORCE-SINGLE

public static Set<String> getSettingAsSet(
final Settings settings,
final String key,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.junit.Test;

import org.opensearch.common.settings.Settings;
import org.opensearch.security.support.ConfigConstants;

public class JwtVendorTest {

Expand All @@ -48,7 +49,7 @@ public void testCreateJwtWithRoles() throws Exception {
String subject = "admin";
String audience = "audience_0";
List<String> roles = List.of("IT", "HR");
List<String> backendRoles = List.of("Sales");
List<String> backendRoles = List.of("Sales", "Support");
String expectedRoles = "IT,HR";
Integer expirySeconds = 300;
LongSupplier currentTime = () -> (int) 100;
Expand All @@ -71,6 +72,48 @@ public void testCreateJwtWithRoles() throws Exception {
Assert.assertEquals(expectedExp, jwt.getClaim("exp"));
Assert.assertNotEquals(expectedRoles, jwt.getClaim("er"));
Assert.assertEquals(expectedRoles, EncryptionDecryptionUtil.decrypt(claimsEncryptionKey, jwt.getClaim("er").toString()));
Assert.assertNull(jwt.getClaim("dbr"));
}

@Test
public void testCreateJwtWithBackwardsCompatibilityMode() throws Exception {
String issuer = "cluster_0";
String subject = "admin";
String audience = "audience_0";
List<String> roles = List.of("IT", "HR");
List<String> backendRoles = List.of("Sales", "Support");
String expectedRoles = "IT,HR";
String expectedBackendRoles = "Sales,Support";

Integer expirySeconds = 300;
LongSupplier currentTime = () -> (int) 100;
String claimsEncryptionKey = RandomStringUtils.randomAlphanumeric(16);
Settings settings = Settings.builder()
.put("signing_key", "abc123")
.put("encryption_key", claimsEncryptionKey)
// CS-SUPPRESS-SINGLE: RegexpSingleline get Extensions Settings
.put(ConfigConstants.EXTENSIONS_BWC_PLUGIN_MODE, true)
// CS-ENFORCE-SINGLE
.build();
Long expectedExp = currentTime.getAsLong() + expirySeconds;

JwtVendor jwtVendor = new JwtVendor(settings, Optional.of(currentTime));
String encodedJwt = jwtVendor.createJwt(issuer, subject, audience, expirySeconds, roles, backendRoles);

JwsJwtCompactConsumer jwtConsumer = new JwsJwtCompactConsumer(encodedJwt);
JwtToken jwt = jwtConsumer.getJwtToken();

Assert.assertEquals("obo", jwt.getClaim("typ"));
Assert.assertEquals("cluster_0", jwt.getClaim("iss"));
Assert.assertEquals("admin", jwt.getClaim("sub"));
Assert.assertEquals("audience_0", jwt.getClaim("aud"));
Assert.assertNotNull(jwt.getClaim("iat"));
Assert.assertNotNull(jwt.getClaim("exp"));
Assert.assertEquals(expectedExp, jwt.getClaim("exp"));
Assert.assertNotEquals(expectedRoles, jwt.getClaim("er"));
Assert.assertEquals(expectedRoles, EncryptionDecryptionUtil.decrypt(claimsEncryptionKey, jwt.getClaim("er").toString()));
Assert.assertNotNull(jwt.getClaim("dbr"));
Assert.assertEquals(expectedBackendRoles, jwt.getClaim("dbr"));
}

@Test(expected = Exception.class)
Expand Down

0 comments on commit 8a96cab

Please sign in to comment.