Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ protected void innerXContent(XContentBuilder builder, Params params) throws IOEx
builder.field(AUDIT_XFIELD, auditUsage);
builder.field(IP_FILTER_XFIELD, ipFilterUsage);
builder.field(ANONYMOUS_XFIELD, anonymousUsage);
} else if (sslUsage.isEmpty() == false) {
// A trial (or basic) license can have SSL without security.
// This is because security defaults to disabled on that license, but that dynamic-default does not disable SSL.
builder.field(SSL_XFIELD, sslUsage);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,10 +150,18 @@ public void usage(ActionListener<XPackFeatureSet.Usage> listener) {
}

static Map<String, Object> sslUsage(Settings settings) {
Map<String, Object> map = new HashMap<>(2);
map.put("http", singletonMap("enabled", HTTP_SSL_ENABLED.get(settings)));
map.put("transport", singletonMap("enabled", TRANSPORT_SSL_ENABLED.get(settings)));
return map;
// If security has been explicitly disabled in the settings, then SSL is also explicitly disabled, and we don't want to report
// these http/transport settings as they would be misleading (they could report `true` even though they were ignored)
// But, if security has not been explicitly configured, but has defaulted to off due to the current license type,
// then these SSL settings are still respected (that is SSL might be enabled, while the rest of security is disabled).
if (XPackSettings.SECURITY_ENABLED.get(settings)) {
Map<String, Object> map = new HashMap<>(2);
map.put("http", singletonMap("enabled", HTTP_SSL_ENABLED.get(settings)));
map.put("transport", singletonMap("enabled", TRANSPORT_SSL_ENABLED.get(settings)));
return map;
} else {
return Collections.emptyMap();
}
}

static Map<String, Object> tokenServiceUsage(Settings settings) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.elasticsearch.xpack.security.transport.filter.IPFilter;
import org.junit.Before;

import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
Expand Down Expand Up @@ -126,29 +127,10 @@ public void testUsage() throws Exception {


final boolean rolesStoreEnabled = randomBoolean();
doAnswer(invocationOnMock -> {
ActionListener<Map<String, Object>> listener = (ActionListener<Map<String, Object>>) invocationOnMock.getArguments()[0];
if (rolesStoreEnabled) {
listener.onResponse(Collections.singletonMap("count", 1));
} else {
listener.onResponse(Collections.emptyMap());
}
return Void.TYPE;
}).when(rolesStore).usageStats(any(ActionListener.class));
configureRoleStoreUsage(rolesStoreEnabled);

final boolean roleMappingStoreEnabled = randomBoolean();
doAnswer(invocationOnMock -> {
ActionListener<Map<String, Object>> listener = (ActionListener) invocationOnMock.getArguments()[0];
if (roleMappingStoreEnabled) {
final Map<String, Object> map = new HashMap<>();
map.put("size", 12L);
map.put("enabled", 10L);
listener.onResponse(map);
} else {
listener.onResponse(Collections.emptyMap());
}
return Void.TYPE;
}).when(roleMappingStore).usageStats(any(ActionListener.class));
configureRoleMappingStoreUsage(roleMappingStoreEnabled);

Map<String, Object> realmsUsageStats = new HashMap<>();
for (int i = 0; i < 5; i++) {
Expand All @@ -158,11 +140,7 @@ public void testUsage() throws Exception {
realmUsage.put("key2", Arrays.asList(i));
realmUsage.put("key3", Arrays.asList(i % 2 == 0));
}
doAnswer(invocationOnMock -> {
ActionListener<Map<String, Object>> listener = (ActionListener) invocationOnMock.getArguments()[0];
listener.onResponse(realmsUsageStats);
return Void.TYPE;
}).when(realms).usageStats(any(ActionListener.class));
configureRealmsUsage(realmsUsageStats);

final boolean anonymousEnabled = randomBoolean();
if (anonymousEnabled) {
Expand All @@ -182,11 +160,7 @@ public void testUsage() throws Exception {
assertThat(usage.name(), is(XPackField.SECURITY));
assertThat(usage.enabled(), is(enabled));
assertThat(usage.available(), is(authcAuthzAvailable));
XContentSource source;
try (XContentBuilder builder = XContentFactory.jsonBuilder()) {
usage.toXContent(builder, ToXContent.EMPTY_PARAMS);
source = new XContentSource(builder);
}
XContentSource source = getXContentSource(usage);

if (enabled) {
if (authcAuthzAvailable) {
Expand Down Expand Up @@ -251,4 +225,101 @@ public void testUsage() throws Exception {
}
}
}

public void testUsageOnTrialLicenseWithSecurityDisabledByDefault() throws Exception {
when(licenseState.isSecurityAvailable()).thenReturn(true);
when(licenseState.isSecurityDisabledByTrialLicense()).thenReturn(true);

Settings.Builder settings = Settings.builder().put(this.settings);

final boolean httpSSLEnabled = randomBoolean();
settings.put("xpack.security.http.ssl.enabled", httpSSLEnabled);
final boolean transportSSLEnabled = randomBoolean();
settings.put("xpack.security.transport.ssl.enabled", transportSSLEnabled);

final boolean auditingEnabled = randomBoolean();
settings.put(XPackSettings.AUDIT_ENABLED.getKey(), auditingEnabled);

final boolean rolesStoreEnabled = randomBoolean();
configureRoleStoreUsage(rolesStoreEnabled);

final boolean roleMappingStoreEnabled = randomBoolean();
configureRoleMappingStoreUsage(roleMappingStoreEnabled);

configureRealmsUsage(Collections.emptyMap());

SecurityFeatureSet featureSet = new SecurityFeatureSet(settings.build(), licenseState,
realms, rolesStore, roleMappingStore, ipFilter);
PlainActionFuture<XPackFeatureSet.Usage> future = new PlainActionFuture<>();
featureSet.usage(future);
XPackFeatureSet.Usage securityUsage = future.get();
BytesStreamOutput out = new BytesStreamOutput();
securityUsage.writeTo(out);
XPackFeatureSet.Usage serializedUsage = new SecurityFeatureSetUsage(out.bytes().streamInput());
for (XPackFeatureSet.Usage usage : Arrays.asList(securityUsage, serializedUsage)) {
assertThat(usage, is(notNullValue()));
assertThat(usage.name(), is(XPackField.SECURITY));
assertThat(usage.enabled(), is(false));
assertThat(usage.available(), is(true));
XContentSource source = getXContentSource(usage);

// check SSL : This is permitted even though security has been dynamically disabled by the trial license.
assertThat(source.getValue("ssl"), is(notNullValue()));
assertThat(source.getValue("ssl.http.enabled"), is(httpSSLEnabled));
assertThat(source.getValue("ssl.transport.enabled"), is(transportSSLEnabled));

// everything else is missing because security is disabled
assertThat(source.getValue("realms"), is(nullValue()));
assertThat(source.getValue("token_service"), is(nullValue()));
assertThat(source.getValue("api_key_service"), is(nullValue()));
assertThat(source.getValue("audit"), is(nullValue()));
assertThat(source.getValue("anonymous"), is(nullValue()));
assertThat(source.getValue("ipfilter"), is(nullValue()));
assertThat(source.getValue("roles"), is(nullValue()));
}
}

private XContentSource getXContentSource(XPackFeatureSet.Usage usage) throws IOException {
XContentSource source;
try (XContentBuilder builder = XContentFactory.jsonBuilder()) {
usage.toXContent(builder, ToXContent.EMPTY_PARAMS);
source = new XContentSource(builder);
}
return source;
}

private void configureRealmsUsage(Map<String, Object> realmsUsageStats) {
doAnswer(invocationOnMock -> {
ActionListener<Map<String, Object>> listener = (ActionListener) invocationOnMock.getArguments()[0];
listener.onResponse(realmsUsageStats);
return Void.TYPE;
}).when(realms).usageStats(any(ActionListener.class));
}

private void configureRoleStoreUsage(boolean rolesStoreEnabled) {
doAnswer(invocationOnMock -> {
ActionListener<Map<String, Object>> listener = (ActionListener<Map<String, Object>>) invocationOnMock.getArguments()[0];
if (rolesStoreEnabled) {
listener.onResponse(Collections.singletonMap("count", 1));
} else {
listener.onResponse(Collections.emptyMap());
}
return Void.TYPE;
}).when(rolesStore).usageStats(any(ActionListener.class));
}

private void configureRoleMappingStoreUsage(boolean roleMappingStoreEnabled) {
doAnswer(invocationOnMock -> {
ActionListener<Map<String, Object>> listener = (ActionListener) invocationOnMock.getArguments()[0];
if (roleMappingStoreEnabled) {
final Map<String, Object> map = new HashMap<>();
map.put("size", 12L);
map.put("enabled", 10L);
listener.onResponse(map);
} else {
listener.onResponse(Collections.emptyMap());
}
return Void.TYPE;
}).when(roleMappingStore).usageStats(any(ActionListener.class));
}
}