mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
Previously if Elasticsearch was unavailable in the Kibana default distribution, you would be prompted with a disabled login screen stating "Login is currently disabled. Administrators should consult the Kibana logs for more details". This was rather confusing for users who have a Basic license. This now provides the user with a screen providing only the required messaging. Additionally, if you were using Kibana with a Basic license with an OSS distribution of Elasticsearch, you would see the same disabled login screen as mentioned previously. This also separates the messaging there to provide clear details for the user to resolve the issue.
This commit is contained in:
parent
928e6f0898
commit
390d9bcd63
8 changed files with 70 additions and 11 deletions
|
@ -156,13 +156,14 @@ export const security = (kibana) => new kibana.Plugin({
|
|||
initLogoutView(server);
|
||||
|
||||
server.injectUiAppVars('login', () => {
|
||||
const { showLogin, loginMessage, allowLogin } = xpackInfo.feature(plugin.id).getLicenseCheckResults() || {};
|
||||
const { showLogin, loginMessage, allowLogin, layout = 'form' } = xpackInfo.feature(plugin.id).getLicenseCheckResults() || {};
|
||||
|
||||
return {
|
||||
loginState: {
|
||||
showLogin,
|
||||
allowLogin,
|
||||
loginMessage
|
||||
loginMessage,
|
||||
layout,
|
||||
}
|
||||
};
|
||||
});
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<div class="kibanaWelcomeLogo"></div>
|
||||
</div>
|
||||
|
||||
<div class="form-container">
|
||||
<div class="form-container" ng-if="login.layout === 'form'">
|
||||
<form class="login-form" ng-submit="login.submit(username, password)">
|
||||
<div ng-show="login.error" class="form-group error-message">
|
||||
<label class="control-label" data-test-subj="loginErrorMessage" >Oops! Error. Try again.</label>
|
||||
|
@ -44,4 +44,15 @@
|
|||
</form>
|
||||
</div>
|
||||
|
||||
<div class="euiText loginErrorEsUnavailable" ng-if="login.layout === 'error-es-unavailable'">
|
||||
<p class="euiTitle euiTitle--medium euiTextColor euiTextColor--danger">Cannot connect to the Elasticsearch cluster currently configured for Kibana.</p>
|
||||
<p>Refer to the Kibana logs for more details and refresh to try again.</p>
|
||||
</div>
|
||||
|
||||
<div class="euiText loginErrorXpackUnavailable" ng-if="login.layout === 'error-xpack-unavailable'">
|
||||
<p class="euiTitle euiTitle--medium euiTextColor euiTextColor--danger">Cannot connect to an Elasticsearch cluster running the OSS distribution from an instance of Kibana that has a Basic license or above.</p>
|
||||
<p>Upgrade Elasticsearch to the default distribution, or use the OSS version of Kibana.</p>
|
||||
<p>Refresh to try again.</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
|
@ -26,11 +26,9 @@ chrome
|
|||
const self = this;
|
||||
|
||||
function setupScope() {
|
||||
const defaultLoginMessage = 'Login is currently disabled because the license could not be determined. '
|
||||
+ 'Please check that Elasticsearch is running, then refresh this page.';
|
||||
|
||||
self.layout = loginState.layout;
|
||||
self.allowLogin = loginState.allowLogin;
|
||||
self.loginMessage = loginState.loginMessage || defaultLoginMessage;
|
||||
self.loginMessage = loginState.loginMessage;
|
||||
self.infoMessage = get(messageMap, parse($window.location.href, true).query.msg);
|
||||
self.isDisabled = !isSecure && secureCookies;
|
||||
self.isLoading = false;
|
||||
|
|
|
@ -117,3 +117,9 @@ input.form-control {
|
|||
font-size: 1.125em;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.loginErrorEsUnavailable,
|
||||
.loginErrorXpackUnavailable {
|
||||
width: 550px;
|
||||
z-index: 10;
|
||||
}
|
|
@ -15,6 +15,7 @@ describe('check_license', function () {
|
|||
beforeEach(function () {
|
||||
mockXPackInfo = {
|
||||
isAvailable: sinon.stub(),
|
||||
isXpackUnavailable: sinon.stub(),
|
||||
feature: sinon.stub(),
|
||||
license: sinon.stub({
|
||||
isOneOf() {},
|
||||
|
@ -24,8 +25,9 @@ describe('check_license', function () {
|
|||
mockXPackInfo.isAvailable.returns(true);
|
||||
});
|
||||
|
||||
it('should show login page but not allow login if license information is not available.', () => {
|
||||
it('should display error when ES is unavailable', () => {
|
||||
mockXPackInfo.isAvailable.returns(false);
|
||||
mockXPackInfo.isXpackUnavailable.returns(false);
|
||||
|
||||
const licenseCheckResults = checkLicense(mockXPackInfo);
|
||||
expect(licenseCheckResults).to.be.eql({
|
||||
|
@ -34,11 +36,28 @@ describe('check_license', function () {
|
|||
showLinks: false,
|
||||
allowRoleDocumentLevelSecurity: false,
|
||||
allowRoleFieldLevelSecurity: false,
|
||||
layout: 'error-es-unavailable',
|
||||
allowRbac: false,
|
||||
loginMessage: 'Login is currently disabled. Administrators should consult the Kibana logs for more details.'
|
||||
});
|
||||
});
|
||||
|
||||
it('should display error when X-Pack is unavailable', () => {
|
||||
mockXPackInfo.isAvailable.returns(false);
|
||||
mockXPackInfo.isXpackUnavailable.returns(true);
|
||||
|
||||
const licenseCheckResults = checkLicense(mockXPackInfo);
|
||||
expect(licenseCheckResults).to.be.eql({
|
||||
showLogin: true,
|
||||
allowLogin: false,
|
||||
showLinks: false,
|
||||
allowRoleDocumentLevelSecurity: false,
|
||||
allowRoleFieldLevelSecurity: false,
|
||||
layout: 'error-xpack-unavailable',
|
||||
allowRbac: false,
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should not show login page or other security elements if license is basic.', () => {
|
||||
mockXPackInfo.license.isOneOf.withArgs(['basic']).returns(true);
|
||||
mockXPackInfo.feature.withArgs('security').returns({
|
||||
|
|
|
@ -34,7 +34,7 @@ export function checkLicense(xPackInfo) {
|
|||
allowRoleDocumentLevelSecurity: false,
|
||||
allowRoleFieldLevelSecurity: false,
|
||||
allowRbac: false,
|
||||
loginMessage: 'Login is currently disabled. Administrators should consult the Kibana logs for more details.'
|
||||
layout: xPackInfo.isXpackUnavailable() ? 'error-xpack-unavailable' : 'error-es-unavailable'
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -126,6 +126,22 @@ describe('XPackInfo', () => {
|
|||
expect(xPackInfo.license.isActive()).to.be(true);
|
||||
});
|
||||
|
||||
|
||||
it('communicates X-Pack being unavailable', async () => {
|
||||
const badRequestError = new Error('Bad request');
|
||||
badRequestError.status = 400;
|
||||
|
||||
mockElasticsearchCluster.callWithInternalUser.returns(Promise.reject(badRequestError));
|
||||
await xPackInfo.refreshNow();
|
||||
|
||||
expect(xPackInfo.isAvailable()).to.be(false);
|
||||
expect(xPackInfo.isXpackUnavailable()).to.be(true);
|
||||
expect(xPackInfo.license.isActive()).to.be(false);
|
||||
expect(xPackInfo.unavailableReason()).to.be(
|
||||
'X-Pack plugin is not installed on the [data] Elasticsearch cluster.'
|
||||
);
|
||||
});
|
||||
|
||||
it('correctly updates xpack info if Elasticsearch API fails.', async () => {
|
||||
expect(xPackInfo.isAvailable()).to.be(true);
|
||||
expect(xPackInfo.license.isActive()).to.be(true);
|
||||
|
|
|
@ -95,6 +95,14 @@ export class XPackInfo {
|
|||
return !!this._cache.response && !!this._cache.response.license;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether ES was available
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isXpackUnavailable() {
|
||||
return this._cache.error instanceof Error && this._cache.error.status === 400;
|
||||
}
|
||||
|
||||
/**
|
||||
* If present, describes the reason why XPack info is not available.
|
||||
* @returns {Error|string}
|
||||
|
@ -104,7 +112,7 @@ export class XPackInfo {
|
|||
return `[${this._clusterSource}] Elasticsearch cluster did not respond with license information.`;
|
||||
}
|
||||
|
||||
if (this._cache.error instanceof Error && this._cache.error.status === 400) {
|
||||
if (this.isXpackUnavailable()) {
|
||||
return `X-Pack plugin is not installed on the [${this._clusterSource}] Elasticsearch cluster.`;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue