Skip to content

Commit

Permalink
add licensing for authorization engine
Browse files Browse the repository at this point in the history
  • Loading branch information
jaymode committed Feb 4, 2019
1 parent 1c9a8e1 commit 3e60a91
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@ private static String[] securityAcknowledgementMessages(OperationMode currentMod
"The following X-Pack security functionality will be disabled: authentication, authorization, " +
"ip filtering, and auditing. Please restart your node after applying the license.",
"Field and document level access control will be disabled.",
"Custom realms will be ignored."
"Custom realms will be ignored.",
"A custom authorization engine will be ignored."
};
}
break;
Expand All @@ -116,7 +117,8 @@ private static String[] securityAcknowledgementMessages(OperationMode currentMod
case PLATINUM:
return new String[] {
"Field and document level access control will be disabled.",
"Custom realms will be ignored."
"Custom realms will be ignored.",
"A custom authorization engine will be ignored."
};
}
break;
Expand All @@ -131,7 +133,8 @@ private static String[] securityAcknowledgementMessages(OperationMode currentMod
"Authentication will be limited to the native realms.",
"IP filtering and auditing will be disabled.",
"Field and document level access control will be disabled.",
"Custom realms will be ignored."
"Custom realms will be ignored.",
"A custom authorization engine will be ignored."
};
}
}
Expand Down Expand Up @@ -433,6 +436,17 @@ public synchronized boolean isAuthorizationRealmAllowed() {
&& status.active;
}

/**
* @return whether a custom authorization engine is allowed based on the license {@link OperationMode}
* @see org.elasticsearch.xpack.core.security.authc.support.DelegatedAuthorizationSettings
*/
public synchronized boolean isAuthorizationEngineAllowed() {
final boolean isSecurityCurrentlyEnabled =
isSecurityEnabled(status.mode, isSecurityExplicitlyEnabled, isSecurityEnabled);
return isSecurityCurrentlyEnabled && (status.mode == OperationMode.PLATINUM || status.mode == OperationMode.TRIAL)
&& status.active;
}

/**
* Determine if Watcher is available based on the current license.
* <p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,17 +226,17 @@ public void testSecurityAckAnyToTrialOrPlatinum() {
}

public void testSecurityAckTrialStandardGoldOrPlatinumToBasic() {
assertAckMesssages(XPackField.SECURITY, randomTrialStandardGoldOrPlatinumMode(), BASIC, 3);
assertAckMesssages(XPackField.SECURITY, randomTrialStandardGoldOrPlatinumMode(), BASIC, 4);
}

public void testSecurityAckAnyToStandard() {
OperationMode from = randomFrom(BASIC, GOLD, PLATINUM, TRIAL);
assertAckMesssages(XPackField.SECURITY, from, STANDARD, 4);
assertAckMesssages(XPackField.SECURITY, from, STANDARD, 5);
}

public void testSecurityAckBasicStandardTrialOrPlatinumToGold() {
OperationMode from = randomFrom(BASIC, PLATINUM, TRIAL, STANDARD);
assertAckMesssages(XPackField.SECURITY, from, GOLD, 2);
assertAckMesssages(XPackField.SECURITY, from, GOLD, 3);
}

public void testMonitoringAckBasicToAny() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,8 @@ Collection<Object> createComponents(Client client, ThreadPool threadPool, Cluste
requestInterceptors = Collections.unmodifiableSet(requestInterceptors);

final AuthorizationService authzService = new AuthorizationService(settings, allRolesStore, clusterService,
auditTrailService, failureHandler, threadPool, anonymousUser, getAuthorizationEngine(), requestInterceptors);
auditTrailService, failureHandler, threadPool, anonymousUser, getAuthorizationEngine(), requestInterceptors,
getLicenseState());

components.add(nativeRolesStore); // used by roles actions
components.add(reservedRolesStore); // used by roles actions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.concurrent.ThreadContext;
import org.elasticsearch.index.IndexNotFoundException;
import org.elasticsearch.license.XPackLicenseState;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportActionProxy;
import org.elasticsearch.transport.TransportRequest;
Expand Down Expand Up @@ -103,13 +104,14 @@ public class AuthorizationService {
private final AuthorizationEngine rbacEngine;
private final AuthorizationEngine authorizationEngine;
private final Set<RequestInterceptor> requestInterceptors;
private final XPackLicenseState licenseState;
private final boolean isAnonymousEnabled;
private final boolean anonymousAuthzExceptionEnabled;

public AuthorizationService(Settings settings, CompositeRolesStore rolesStore, ClusterService clusterService,
AuditTrailService auditTrail, AuthenticationFailureHandler authcFailureHandler,
ThreadPool threadPool, AnonymousUser anonymousUser, @Nullable AuthorizationEngine authorizationEngine,
Set<RequestInterceptor> requestInterceptors) {
Set<RequestInterceptor> requestInterceptors, XPackLicenseState licenseState) {
this.clusterService = clusterService;
this.auditTrail = auditTrail;
this.indicesAndAliasesResolver = new IndicesAndAliasesResolver(settings, clusterService);
Expand All @@ -122,6 +124,7 @@ public AuthorizationService(Settings settings, CompositeRolesStore rolesStore, C
this.authorizationEngine = authorizationEngine == null ? this.rbacEngine : authorizationEngine;
this.requestInterceptors = requestInterceptors;
this.settings = settings;
this.licenseState = licenseState;
}

public void checkPrivileges(Authentication authentication, HasPrivilegesRequest request,
Expand Down Expand Up @@ -349,10 +352,14 @@ AuthorizationEngine getAuthorizationEngine(final Authentication authentication)
}

private AuthorizationEngine getAuthorizationEngineForUser(final User user) {
if (ClientReservedRealm.isReserved(user.principal(), settings) || isInternalUser(user)) {
return rbacEngine;
if (rbacEngine != authorizationEngine && licenseState.isAuthorizationEngineAllowed()) {
if (ClientReservedRealm.isReserved(user.principal(), settings) || isInternalUser(user)) {
return rbacEngine;
} else {
return authorizationEngine;
}
} else {
return authorizationEngine;
return rbacEngine;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
import org.elasticsearch.common.util.concurrent.ThreadContext;
import org.elasticsearch.index.IndexNotFoundException;
import org.elasticsearch.index.shard.ShardId;
import org.elasticsearch.license.XPackLicenseState;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportActionProxy;
Expand Down Expand Up @@ -144,7 +145,6 @@
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.function.Function;
import java.util.function.Predicate;

import static java.util.Arrays.asList;
Expand Down Expand Up @@ -233,7 +233,7 @@ public void setup() {
roleMap.put(ReservedRolesStore.SUPERUSER_ROLE_DESCRIPTOR.getName(), ReservedRolesStore.SUPERUSER_ROLE_DESCRIPTOR);
authorizationService = new AuthorizationService(settings, rolesStore, clusterService,
auditTrail, new DefaultAuthenticationFailureHandler(Collections.emptyMap()), threadPool, new AnonymousUser(settings), null,
Collections.emptySet());
Collections.emptySet(), new XPackLicenseState(settings));
}

private void authorize(Authentication authentication, String action, TransportRequest request) {
Expand Down Expand Up @@ -659,7 +659,8 @@ public void testDenialForAnonymousUser() {
Settings settings = Settings.builder().put(AnonymousUser.ROLES_SETTING.getKey(), "a_all").build();
final AnonymousUser anonymousUser = new AnonymousUser(settings);
authorizationService = new AuthorizationService(settings, rolesStore, clusterService, auditTrail,
new DefaultAuthenticationFailureHandler(Collections.emptyMap()), threadPool, anonymousUser, null, Collections.emptySet());
new DefaultAuthenticationFailureHandler(Collections.emptyMap()), threadPool, anonymousUser, null, Collections.emptySet(),
new XPackLicenseState(settings));

RoleDescriptor role = new RoleDescriptor("a_all", null,
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("a").privileges("all").build() }, null);
Expand Down Expand Up @@ -687,7 +688,7 @@ public void testDenialForAnonymousUserAuthorizationExceptionDisabled() {
final Authentication authentication = createAuthentication(new AnonymousUser(settings));
authorizationService = new AuthorizationService(settings, rolesStore, clusterService, auditTrail,
new DefaultAuthenticationFailureHandler(Collections.emptyMap()), threadPool, new AnonymousUser(settings), null,
Collections.emptySet());
Collections.emptySet(), new XPackLicenseState(settings));

RoleDescriptor role = new RoleDescriptor("a_all", null,
new IndicesPrivileges[]{IndicesPrivileges.builder().indices("a").privileges("all").build()}, null);
Expand Down Expand Up @@ -1391,36 +1392,60 @@ public void getUserPrivileges(Authentication authentication, AuthorizationInfo a
}
};

XPackLicenseState licenseState = mock(XPackLicenseState.class);
when(licenseState.isAuthorizationEngineAllowed()).thenReturn(true);
authorizationService = new AuthorizationService(Settings.EMPTY, rolesStore, clusterService,
auditTrail, new DefaultAuthenticationFailureHandler(Collections.emptyMap()), threadPool, new AnonymousUser(Settings.EMPTY),
engine, Collections.emptySet());
engine, Collections.emptySet(), licenseState);
Authentication authentication = createAuthentication(new User("test user", "a_all"));
assertEquals(engine, authorizationService.getAuthorizationEngine(authentication));
when(licenseState.isAuthorizationEngineAllowed()).thenReturn(false);
assertThat(authorizationService.getAuthorizationEngine(authentication), instanceOf(RBACEngine.class));

when(licenseState.isAuthorizationEngineAllowed()).thenReturn(true);
authentication = createAuthentication(new User("runas", new String[] { "runas_role" }, new User("runner", "runner_role")));
assertEquals(engine, authorizationService.getAuthorizationEngine(authentication));
assertEquals(engine, authorizationService.getRunAsAuthorizationEngine(authentication));
when(licenseState.isAuthorizationEngineAllowed()).thenReturn(false);
assertThat(authorizationService.getAuthorizationEngine(authentication), instanceOf(RBACEngine.class));
assertThat(authorizationService.getRunAsAuthorizationEngine(authentication), instanceOf(RBACEngine.class));

when(licenseState.isAuthorizationEngineAllowed()).thenReturn(true);
authentication = createAuthentication(new User("runas", new String[] { "runas_role" }, new ElasticUser(true)));
assertEquals(engine, authorizationService.getAuthorizationEngine(authentication));
assertNotEquals(engine, authorizationService.getRunAsAuthorizationEngine(authentication));
assertThat(authorizationService.getRunAsAuthorizationEngine(authentication), instanceOf(RBACEngine.class));
when(licenseState.isAuthorizationEngineAllowed()).thenReturn(false);
assertThat(authorizationService.getAuthorizationEngine(authentication), instanceOf(RBACEngine.class));
assertThat(authorizationService.getRunAsAuthorizationEngine(authentication), instanceOf(RBACEngine.class));

when(licenseState.isAuthorizationEngineAllowed()).thenReturn(true);
authentication = createAuthentication(new User("elastic", new String[] { "superuser" }, new User("runner", "runner_role")));
assertNotEquals(engine, authorizationService.getAuthorizationEngine(authentication));
assertThat(authorizationService.getAuthorizationEngine(authentication), instanceOf(RBACEngine.class));
assertEquals(engine, authorizationService.getRunAsAuthorizationEngine(authentication));
when(licenseState.isAuthorizationEngineAllowed()).thenReturn(false);
assertThat(authorizationService.getAuthorizationEngine(authentication), instanceOf(RBACEngine.class));
assertThat(authorizationService.getRunAsAuthorizationEngine(authentication), instanceOf(RBACEngine.class));

when(licenseState.isAuthorizationEngineAllowed()).thenReturn(true);
authentication = createAuthentication(new User("kibana", new String[] { "kibana_system" }, new ElasticUser(true)));
assertNotEquals(engine, authorizationService.getAuthorizationEngine(authentication));
assertThat(authorizationService.getAuthorizationEngine(authentication), instanceOf(RBACEngine.class));
assertNotEquals(engine, authorizationService.getRunAsAuthorizationEngine(authentication));
assertThat(authorizationService.getRunAsAuthorizationEngine(authentication), instanceOf(RBACEngine.class));
when(licenseState.isAuthorizationEngineAllowed()).thenReturn(false);
assertThat(authorizationService.getAuthorizationEngine(authentication), instanceOf(RBACEngine.class));
assertThat(authorizationService.getRunAsAuthorizationEngine(authentication), instanceOf(RBACEngine.class));

when(licenseState.isAuthorizationEngineAllowed()).thenReturn(true);
authentication = createAuthentication(randomFrom(XPackUser.INSTANCE, XPackSecurityUser.INSTANCE,
new ElasticUser(true), new KibanaUser(true)));
assertNotEquals(engine, authorizationService.getRunAsAuthorizationEngine(authentication));
assertThat(authorizationService.getRunAsAuthorizationEngine(authentication), instanceOf(RBACEngine.class));
when(licenseState.isAuthorizationEngineAllowed()).thenReturn(false);
assertThat(authorizationService.getAuthorizationEngine(authentication), instanceOf(RBACEngine.class));
assertThat(authorizationService.getRunAsAuthorizationEngine(authentication), instanceOf(RBACEngine.class));
}

static AuthorizationInfo authzInfoRoles(String[] expectedRoles) {
Expand Down

0 comments on commit 3e60a91

Please sign in to comment.