-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add license check for FIPS (#181187)
## Updates ### Latest updates - Expose whether KB is configured to run in FIPS mode from Core -> Security <img width="653" alt="Screenshot 2024-06-20 at 9 55 17 PM" src="https://github.com/elastic/kibana/assets/21210601/56a9f50f-0a05-41ca-9292-ed225b3d8062"> Consolidating all FIPS PRs into this PR *Previous PRs were Approved ### Changes - Config option is now experimental: `xpack.security.experimental.fipsMode.enabled` - Documentation has been revised - Listed as an experimental feature - Added keystore references for adding a password ## Summary Closes #169738 Closes #169739 Closes #169740 Closes #185948 FIPS is a platinum license feature. KIbana instances must have a platinum or better license to start up in FIPS mode, a lesser license will result in Kibana failing to start up If the license is degraded, Kibana will still run, but an error will be logged letting the user know that Kibana will not be able to restart. ## Config changes This PR required the changes that were approved from [a previous PR](#174558), since that PR couldn't be merged into main, I merged it here. ## Testing ### Locally In your `kibana.dev.yml` add: `xpack.security.experimental.fipsMode.enabled: true` To allow Kibana to start without actually providing a compliant OpenSSL provider, in `x-pack/plugins/security/server/config.ts` change L328 from `if (isFipsEnabled !== isNodeRunningWithFipsEnabled)` to `if (false)` You are now configured to run in FIPS-spoof mode! Run: `yarn es snapshot` and `yarn start` > You should see Kibana fail to start with an error about using a basic license. Run: `yarn es snapshot --license trial` and `yarn start` > Kibana should start. Login as `elastic` and navigate to Stack Management > License Management Switch your license to `basic` and accept. In your logs, you will see an error letting users know that you no longer have an appropriate license and Kibana will not restart. ### For FIPS enthusiasts Start an ES instance in a method of your choosing, but not using `yarn es snapshot`. I like to use an 8.15.0-snapshot from the `.es/cache` directory by running `tar -xzvf elasticsearch-8.15.0-SNAPSHOT-darwin-aarch64.tar.gz ` and cd into the new directory's `bin` folder to run `./elasticsearch` Ensure you have Docker running locally. From any command line, run: `docker run --rm -it -e XPACK_SECURITY_FIPSMODE_ENABLED='true' -p 5601:5601/tcp docker.elastic.co/kibana-ci/kibana-ubi-fips:8.15.0-SNAPSHOT-bc3150316ed317c08d57c6bd785ba39586072e1d` This will start Kibana into Interactive Setup mode, copy and paste the token from the ES startup logs. Kibana should fail to start and you should see Kibana fail to start with an error about using a basic license. Repeat the above process except before you paste the token from ES, do the following to enable a trial license on your ES instance: In a new terminal window, navigate to your the top level of your elasticsearch folder and run `curl -X POST --cacert config/certs/http_ca.crt -u elastic:YOUR_PASSWORD_HERE "https://localhost:9200/_license/start_trial?acknowledge=true&pretty"` You should receive a successful response. Now paste the token from the ES startup logs into the Kibana Interactive Setup window and Kibana should start. Login as `elastic` and navigate to Stack Management > License Management Switch your license to `basic` and accept. In your logs, you will see an error letting users know that you no longer have an appropriate license and Kibana will not restart. --------- Co-authored-by: kibanamachine <[email protected]> Co-authored-by: lcawl <[email protected]>
- Loading branch information
1 parent
ae30c30
commit 4554b75
Showing
31 changed files
with
679 additions
and
5 deletions.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
[[xpack-security-fips-140-2]] | ||
=== FIPS 140-2 | ||
|
||
experimental::[] | ||
|
||
The Federal Information Processing Standard (FIPS) Publication 140-2, (FIPS PUB 140-2), | ||
titled "Security Requirements for Cryptographic Modules" is a U.S. government computer security standard | ||
used to approve cryptographic modules. | ||
|
||
{kib} offers a FIPS 140-2 compliant mode and as such can run in a Node.js environment configured with a FIPS | ||
140-2 compliant OpenSSL3 provider. | ||
|
||
To run {kib} in FIPS mode, you must have the appropriate {subscriptions}[subscription]. | ||
|
||
[IMPORTANT] | ||
============================================================================ | ||
The Node bundled with {kib} is not configured for FIPS 140-2. You must configure a FIPS 140-2 compliant OpenSSL3 | ||
provider. Consult the Node.js documentation to learn how to configure your environment. | ||
============================================================================ | ||
|
||
For {kib}, adherence to FIPS 140-2 is ensured by: | ||
|
||
* Using FIPS approved / NIST recommended cryptographic algorithms. | ||
|
||
* Delegating the implementation of these cryptographic algorithms to a NIST validated cryptographic module | ||
(available via Node.js configured with an OpenSSL3 provider). | ||
|
||
* Allowing the configuration of {kib} in a FIPS 140-2 compliant manner, as documented below. | ||
|
||
==== Configuring {kib} for FIPS 140-2 | ||
|
||
Apart from setting `xpack.security.experimental.fipsMode.enabled` to `true` in your {kib} config, a number of security related | ||
settings need to be reviewed and configured in order to run {kib} successfully in a FIPS 140-2 compliant Node.js | ||
environment. | ||
|
||
===== Kibana keystore | ||
|
||
FIPS 140-2 (via NIST Special Publication 800-132) dictates that encryption keys should at least have an effective | ||
strength of 112 bits. As such, the Kibana keystore that stores the application’s secure settings needs to be | ||
password protected with a password that satisfies this requirement. This means that the password needs to be 14 bytes | ||
long which is equivalent to a 14 character ASCII encoded password, or a 7 character UTF-8 encoded password. | ||
|
||
For more information on how to set this password, refer to the <<change-password,keystore documentation>>. | ||
|
||
===== TLS keystore and keys | ||
|
||
Keystores can be used in a number of General TLS settings in order to conveniently store key and trust material. | ||
PKCS#12 keystores cannot be used in a FIPS 140-2 compliant Node.js environment. Avoid using these types of keystores. | ||
Your FIPS 140-2 provider may provide a compliant keystore implementation that can be used, or you can use PEM encoded | ||
files. To use PEM encoded key material, you can use the relevant `\*.key` and `*.certificate` configuration options, | ||
and for trust material you can use `*.certificate_authorities`. | ||
|
||
As an example, avoid PKCS#12 specific settings such as: | ||
|
||
* `server.ssl.keystore.path` | ||
* `server.ssl.truststore.path` | ||
* `elasticsearch.ssl.keystore.path` | ||
* `elasticsearch.ssl.truststore.path` | ||
|
||
===== Limitations | ||
|
||
Configuring {kib} to run in FIPS mode is still considered to be experimental. Not all features are guaranteed to | ||
function as expected. |
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
119 changes: 119 additions & 0 deletions
119
packages/core/security/core-security-server-internal/src/fips/fips.test.ts
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,119 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
|
||
const mockGetFipsFn = jest.fn(); | ||
jest.mock('crypto', () => ({ | ||
randomBytes: jest.fn(), | ||
constants: jest.requireActual('crypto').constants, | ||
get getFips() { | ||
return mockGetFipsFn; | ||
}, | ||
})); | ||
|
||
import { SecurityServiceConfigType } from '../utils'; | ||
import { isFipsEnabled, checkFipsConfig } from './fips'; | ||
import { loggingSystemMock } from '@kbn/core-logging-server-mocks'; | ||
|
||
describe('fips', () => { | ||
let config: SecurityServiceConfigType; | ||
describe('#isFipsEnabled', () => { | ||
it('should return `true` if config.experimental.fipsMode.enabled is `true`', () => { | ||
config = { experimental: { fipsMode: { enabled: true } } }; | ||
|
||
expect(isFipsEnabled(config)).toBe(true); | ||
}); | ||
|
||
it('should return `false` if config.experimental.fipsMode.enabled is `false`', () => { | ||
config = { experimental: { fipsMode: { enabled: false } } }; | ||
|
||
expect(isFipsEnabled(config)).toBe(false); | ||
}); | ||
|
||
it('should return `false` if config.experimental.fipsMode.enabled is `undefined`', () => { | ||
expect(isFipsEnabled(config)).toBe(false); | ||
}); | ||
}); | ||
|
||
describe('checkFipsConfig', () => { | ||
let mockExit: jest.SpyInstance; | ||
|
||
beforeAll(() => { | ||
mockExit = jest.spyOn(process, 'exit').mockImplementation((exitCode) => { | ||
throw new Error(`Fake Exit: ${exitCode}`); | ||
}); | ||
}); | ||
|
||
afterAll(() => { | ||
mockExit.mockRestore(); | ||
}); | ||
|
||
it('should log an error message if FIPS mode is misconfigured - xpack.security.experimental.fipsMode.enabled true, Nodejs FIPS mode false', async () => { | ||
config = { experimental: { fipsMode: { enabled: true } } }; | ||
const logger = loggingSystemMock.create().get(); | ||
try { | ||
checkFipsConfig(config, logger); | ||
} catch (e) { | ||
expect(mockExit).toHaveBeenNthCalledWith(1, 78); | ||
} | ||
|
||
expect(loggingSystemMock.collect(logger).error).toMatchInlineSnapshot(` | ||
Array [ | ||
Array [ | ||
"Configuration mismatch error. xpack.security.experimental.fipsMode.enabled is set to true and the configured Node.js environment has FIPS disabled", | ||
], | ||
] | ||
`); | ||
}); | ||
|
||
it('should log an error message if FIPS mode is misconfigured - xpack.security.experimental.fipsMode.enabled false, Nodejs FIPS mode true', async () => { | ||
mockGetFipsFn.mockImplementationOnce(() => { | ||
return 1; | ||
}); | ||
|
||
config = { experimental: { fipsMode: { enabled: false } } }; | ||
const logger = loggingSystemMock.create().get(); | ||
|
||
try { | ||
checkFipsConfig(config, logger); | ||
} catch (e) { | ||
expect(mockExit).toHaveBeenNthCalledWith(1, 78); | ||
} | ||
|
||
expect(loggingSystemMock.collect(logger).error).toMatchInlineSnapshot(` | ||
Array [ | ||
Array [ | ||
"Configuration mismatch error. xpack.security.experimental.fipsMode.enabled is set to false and the configured Node.js environment has FIPS enabled", | ||
], | ||
] | ||
`); | ||
}); | ||
|
||
it('should log an info message if FIPS mode is properly configured - xpack.security.experimental.fipsMode.enabled true, Nodejs FIPS mode true', async () => { | ||
mockGetFipsFn.mockImplementationOnce(() => { | ||
return 1; | ||
}); | ||
|
||
config = { experimental: { fipsMode: { enabled: true } } }; | ||
const logger = loggingSystemMock.create().get(); | ||
|
||
try { | ||
checkFipsConfig(config, logger); | ||
} catch (e) { | ||
logger.error('Should not throw error!'); | ||
} | ||
|
||
expect(loggingSystemMock.collect(logger).info).toMatchInlineSnapshot(` | ||
Array [ | ||
Array [ | ||
"Kibana is running in FIPS mode.", | ||
], | ||
] | ||
`); | ||
}); | ||
}); | ||
}); |
35 changes: 35 additions & 0 deletions
35
packages/core/security/core-security-server-internal/src/fips/fips.ts
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,35 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
|
||
import type { Logger } from '@kbn/logging'; | ||
import { getFips } from 'crypto'; | ||
import { SecurityServiceConfigType } from '../utils'; | ||
|
||
export function isFipsEnabled(config: SecurityServiceConfigType): boolean { | ||
return config?.experimental?.fipsMode?.enabled ?? false; | ||
} | ||
|
||
export function checkFipsConfig(config: SecurityServiceConfigType, logger: Logger) { | ||
const isFipsConfigEnabled = isFipsEnabled(config); | ||
const isNodeRunningWithFipsEnabled = getFips() === 1; | ||
|
||
// Check if FIPS is enabled in either setting | ||
if (isFipsConfigEnabled || isNodeRunningWithFipsEnabled) { | ||
// FIPS must be enabled on both or log and error an exit Kibana | ||
if (isFipsConfigEnabled !== isNodeRunningWithFipsEnabled) { | ||
logger.error( | ||
`Configuration mismatch error. xpack.security.experimental.fipsMode.enabled is set to ${isFipsConfigEnabled} and the configured Node.js environment has FIPS ${ | ||
isNodeRunningWithFipsEnabled ? 'enabled' : 'disabled' | ||
}` | ||
); | ||
process.exit(78); | ||
} else { | ||
logger.info('Kibana is running in FIPS mode.'); | ||
} | ||
} | ||
} |
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
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
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
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
Oops, something went wrong.