forked from elastic/elasticsearch
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Log the status of security on license change
Whether security is enabled/disabled is dependent on the combination of the node settings and the cluster license. This commit adds a license state listener that logs when the license change causes security to switch state (or to be initialised). This is primarily useful for diagnosing cluster formation issues. Backport of: elastic#42488
- Loading branch information
Showing
4 changed files
with
163 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
45 changes: 45 additions & 0 deletions
45
.../src/main/java/org/elasticsearch/xpack/security/support/SecurityStatusChangeListener.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
package org.elasticsearch.xpack.security.support; | ||
|
||
import org.apache.logging.log4j.LogManager; | ||
import org.apache.logging.log4j.Logger; | ||
import org.elasticsearch.license.LicenseStateListener; | ||
import org.elasticsearch.license.XPackLicenseState; | ||
|
||
import java.util.Objects; | ||
|
||
/** | ||
* A listener for license state changes that provides log messages when a license change | ||
* causes security to switch between enable and disabled (or vice versa). | ||
*/ | ||
public class SecurityStatusChangeListener implements LicenseStateListener { | ||
|
||
private final Logger logger; | ||
private final XPackLicenseState licenseState; | ||
private Boolean securityEnabled; | ||
|
||
public SecurityStatusChangeListener(XPackLicenseState licenseState) { | ||
this.logger = LogManager.getLogger(getClass()); | ||
this.licenseState = licenseState; | ||
this.securityEnabled = null; | ||
} | ||
|
||
/** | ||
* This listener will not be registered if security has been explicitly disabled, so we only need to account for dynamic changes due | ||
* to changes in the applied license. | ||
*/ | ||
@Override | ||
public synchronized void licenseStateChanged() { | ||
final boolean newState = licenseState.isSecurityAvailable() && licenseState.isSecurityDisabledByLicenseDefaults() == false; | ||
// old state might be null (undefined) so do Object comparison | ||
if (Objects.equals(newState, securityEnabled) == false) { | ||
logger.info("Active license is now [{}]; Security is {}", licenseState.getOperationMode(), newState ? "enabled" : "disabled"); | ||
this.securityEnabled = newState; | ||
} | ||
} | ||
} |
115 changes: 115 additions & 0 deletions
115
...test/java/org/elasticsearch/xpack/security/support/SecurityStatusChangeListenerTests.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
package org.elasticsearch.xpack.security.support; | ||
|
||
import org.apache.logging.log4j.Level; | ||
import org.apache.logging.log4j.LogManager; | ||
import org.apache.logging.log4j.Logger; | ||
import org.elasticsearch.common.logging.Loggers; | ||
import org.elasticsearch.license.License; | ||
import org.elasticsearch.license.XPackLicenseState; | ||
import org.elasticsearch.test.ESTestCase; | ||
import org.elasticsearch.test.MockLogAppender; | ||
import org.junit.After; | ||
import org.junit.Before; | ||
import org.mockito.Mockito; | ||
|
||
import static org.mockito.Mockito.when; | ||
|
||
public class SecurityStatusChangeListenerTests extends ESTestCase { | ||
|
||
private XPackLicenseState licenseState; | ||
private SecurityStatusChangeListener listener; | ||
private MockLogAppender logAppender; | ||
private Logger listenerLogger; | ||
|
||
@Before | ||
public void setup() throws IllegalAccessException { | ||
licenseState = Mockito.mock(XPackLicenseState.class); | ||
when(licenseState.isSecurityAvailable()).thenReturn(true); | ||
|
||
listener = new SecurityStatusChangeListener(licenseState); | ||
|
||
logAppender = new MockLogAppender(); | ||
logAppender.start(); | ||
listenerLogger = LogManager.getLogger(listener.getClass()); | ||
Loggers.addAppender(listenerLogger, logAppender); | ||
} | ||
|
||
@After | ||
public void cleanup() { | ||
Loggers.removeAppender(listenerLogger, logAppender); | ||
logAppender.stop(); | ||
} | ||
|
||
public void testSecurityEnabledToDisabled() { | ||
when(licenseState.isSecurityDisabledByLicenseDefaults()).thenReturn(false); | ||
|
||
when(licenseState.getOperationMode()).thenReturn(License.OperationMode.GOLD); | ||
logAppender.addExpectation(new MockLogAppender.SeenEventExpectation( | ||
"initial change", | ||
listener.getClass().getName(), | ||
Level.INFO, | ||
"Active license is now [GOLD]; Security is enabled" | ||
)); | ||
listener.licenseStateChanged(); | ||
|
||
when(licenseState.getOperationMode()).thenReturn(License.OperationMode.PLATINUM); | ||
logAppender.addExpectation(new MockLogAppender.UnseenEventExpectation( | ||
"no-op change", | ||
listener.getClass().getName(), | ||
Level.INFO, | ||
"Active license is now [PLATINUM]; Security is enabled" | ||
)); | ||
|
||
when(licenseState.isSecurityDisabledByLicenseDefaults()).thenReturn(true); | ||
when(licenseState.getOperationMode()).thenReturn(License.OperationMode.BASIC); | ||
logAppender.addExpectation(new MockLogAppender.SeenEventExpectation( | ||
"change to basic", | ||
listener.getClass().getName(), | ||
Level.INFO, | ||
"Active license is now [BASIC]; Security is disabled" | ||
)); | ||
listener.licenseStateChanged(); | ||
|
||
logAppender.assertAllExpectationsMatched(); | ||
} | ||
|
||
public void testSecurityDisabledToEnabled() { | ||
when(licenseState.isSecurityDisabledByLicenseDefaults()).thenReturn(true); | ||
|
||
when(licenseState.getOperationMode()).thenReturn(License.OperationMode.TRIAL); | ||
logAppender.addExpectation(new MockLogAppender.SeenEventExpectation( | ||
"initial change", | ||
listener.getClass().getName(), | ||
Level.INFO, | ||
"Active license is now [TRIAL]; Security is disabled" | ||
)); | ||
listener.licenseStateChanged(); | ||
|
||
when(licenseState.getOperationMode()).thenReturn(License.OperationMode.BASIC); | ||
logAppender.addExpectation(new MockLogAppender.UnseenEventExpectation( | ||
"no-op change", | ||
listener.getClass().getName(), | ||
Level.INFO, | ||
"Active license is now [BASIC]; Security is disabled" | ||
)); | ||
|
||
when(licenseState.isSecurityDisabledByLicenseDefaults()).thenReturn(false); | ||
when(licenseState.getOperationMode()).thenReturn(License.OperationMode.PLATINUM); | ||
logAppender.addExpectation(new MockLogAppender.SeenEventExpectation( | ||
"change to platinum", | ||
listener.getClass().getName(), | ||
Level.INFO, | ||
"Active license is now [PLATINUM]; Security is enabled" | ||
)); | ||
listener.licenseStateChanged(); | ||
|
||
logAppender.assertAllExpectationsMatched(); | ||
} | ||
|
||
} |