-
Notifications
You must be signed in to change notification settings - Fork 8.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for certificates in PKCS#12 (P12) key stores #53810
Add support for certificates in PKCS#12 (P12) key stores #53810
Conversation
Pinging @elastic/kibana-security (Team:Security) |
160111e
to
4dc7117
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Author's notes for reviewers
export const ES_P12_PATH = resolve(__dirname, '../certs/elasticsearch.p12'); | ||
export const ES_P12_PASSWORD = 'storepass'; | ||
export const ES_EMPTYPASSWORD_P12_PATH = resolve( | ||
__dirname, | ||
'../certs/elasticsearch_emptypassword.p12' | ||
); | ||
export const ES_NOPASSWORD_P12_PATH = resolve(__dirname, '../certs/elasticsearch_nopassword.p12'); | ||
export const KBN_KEY_PATH = resolve(__dirname, '../certs/kibana.key'); | ||
export const KBN_CERT_PATH = resolve(__dirname, '../certs/kibana.crt'); | ||
export const KBN_P12_PATH = resolve(__dirname, '../certs/kibana.p12'); | ||
export const KBN_P12_PASSWORD = 'storepass'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a P12 key store that contains the Elasticsearch key / cert / CA cert. I also added other certificates and key stores so we have one place where keys / certs reside for testing purposes. Other unit tests and functional tests now reference these.
esArgs.push(`xpack.security.http.ssl.key=${ES_KEY_PATH}`); | ||
esArgs.push(`xpack.security.http.ssl.certificate=${ES_CERT_PATH}`); | ||
esArgs.push(`xpack.security.http.ssl.certificate_authorities=${CA_CERT_PATH}`); | ||
esArgs.push(`xpack.security.http.ssl.keystore.path=${ES_P12_PATH}`); | ||
esArgs.push(`xpack.security.http.ssl.keystore.type=PKCS12`); | ||
esArgs.push(`xpack.security.http.ssl.keystore.password=${ES_P12_PASSWORD}`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change isn't strictly necessary, but it seemed appropriate to prefer the P12 key store since that is the default output of elasticsearch-certutil.
certificateAuthorities: ['content-of-ca-path-1', 'content-of-ca-path-2'], | ||
certificate: 'content-of-certificate-path', | ||
key: 'content-of-key-path', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ElasticsearchClientConfig
no longer reads the contents of these files -- ElasticsearchConfig
handles that. So we don't need to mock the readFileSync
implementation here and we can assume that the contents of these certs/keys are being passed in to the ElasticsearchClientConfig
params.
|
||
jest.mock('fs', () => ({ | ||
readFileSync: jest.fn(), | ||
})); | ||
|
||
import { readFileSync } from 'fs'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The old behavior of this unit test resulted in the creation of an HttpServer
with SSL enabled, but an undefined key
and certificate
. Technically this worked without errors, but it seemed that this wasn't the original intent of this test. So, I changed this test to use an actual key/cert instead.
9WQ73QKBgQDAYZzplO4TPoPK9AnxoW/HpSwGEO7Fb8fLyPg94CvHn4QBCFJUKuTn | ||
hBp/TJgF6CjQWQMr2FKVFF33Ow7+Qa96YGvmYlEjR/71D4Rlprj5JJpuO154DI3I | ||
YIMNTjvwEQEI+YamMarKsz0Kq+I1EYSAf6bQ4H2PgxDxwTXaLkl0RA== | ||
-----END RSA PRIVATE KEY----- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This key was a copy of the old CA key used in kbn-dev-utils
. I regenerated the P12 key stores in this fixtures directory, using the new CA contained in kbn-dev-utils
, but I decided not to include the new CA key in the repository. This key is outdated and not needed.
4dc7117
to
0ff505d
Compare
Bag Attributes | ||
friendlyName: elasticsearch | ||
localKeyID: 54 69 6D 65 20 31 35 37 37 34 36 36 31 39 38 30 33 37 | ||
Key Attributes: <No Attributes> | ||
Bag Attributes | ||
friendlyName: ca | ||
2.16.840.1.113894.746875.1.1: <Unsupported tag 6> | ||
subject=/CN=Elastic Certificate Tool Autogenerated CA | ||
issuer=/CN=Elastic Certificate Tool Autogenerated CA | ||
-----BEGIN CERTIFICATE----- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These bag attributes are included because the certificate was generated as part of a P12 key store, then exported from that key store using OpenSSL. Any code that reads a PEM-formatted certificate or key will ignore this.
e8ec4f9
to
0593259
Compare
`--server.ssl.key=${ES_KEY_PATH}`, | ||
`--server.ssl.certificate=${ES_CERT_PATH}`, | ||
`--server.ssl.key=${KBN_KEY_PATH}`, | ||
`--server.ssl.certificate=${KBN_CERT_PATH}`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kbn/dev-utils
now provides a separate certificate/key for Kibana, switched to those to avoid confusion.
0593259
to
b3ec790
Compare
💚 Build Succeeded
To update your PR or re-run it, just comment with: |
Added Kibana certificate/keypair, and also added P12 formats for both Kibana and Elasticsearch. Removed obsolete dev certs/keys, and changed files and tests where appropriate.
Not positive that this code should remain here, open to suggestions.
The Kibana Platform supports configuration deprecations now, so we can remove the custom deprecation logging that we had previously.
Logger was previously optional to avoid changing tests. Now it is mandatory and the tests have been changed to mock the logger.
This test started failing until I accepted these changes.
These never should have been grouped together. Split them out to improve maintainability and reduce clutter.
This includes: * HTTPS server * HTTPS redirect server * BasePath proxy server
7afb594
to
c4d5163
Compare
Also changed readPkcs12Keystore to determine which end-entity key and cert to return based on if they have a matching public key. The old behavior would simply return the first key and cert as the EE key and cert.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM for platform changes
@kobelb ready for re-review! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking and working great! As discussed on Slack, the only configuration that we'll want to manually verify works properly is a CA that uses an intermediate certificate
Also simplified README regarding cert generation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM on green CI
💚 Build SucceededHistory
To update your PR or re-run it, just comment with: |
Kibana now supports the usage of PKCS#12 (P12) key stores and trust stores for certificates and keys.
The Elasticsearch config should error out if a PKCS12 keystore does not contain a key *or* a certificate. This was intended to be the functionality in PR elastic#53810, but it was overlooked. Changing it now since this PR is changing code in the same file.
Summary
This PR allows Kibana to read certificates and keys from P12 key stores (and trust stores). It adds the following configuration options:
elasticsearch.ssl.keystore.path
elasticsearch.ssl.keystore.password
elasticsearch.ssl.truststore.path
elasticsearch.ssl.truststore.password
server.ssl.keystore.path
server.ssl.keystore.password
server.ssl.truststore.path
server.ssl.truststore.password
Details
I implemented this feature by using node-forge to parse each P12 key store and convert the keys/certs to PEM format. This means that all clients that currently rely on these files do not need any changes made -- at the end of the day, they will still use PEM-formatted keys/certs.
I regenerated the existing certificates in Kibana dev utils, adding some extra ones that weren't included before. Each P12 key store was generated using elasticsearch-certutil, and I extracted PEM certificates / keys from those key stores. The PEM and P12 formats can be used interchangeably (e.g., PEM CA and P12 end-entity key store). I chose not to include the CA private key; if anyone experimenting with Kibana chooses to add that CA to their system's trusted root certificates, it would be trivial to MITM TLS connections for that system. If these certificates need to be regenerated in the future, that can be done using the new instructions detailed in
packages/kbn-dev-utils/certs/README.md
.In creating this PR, I made a few design decisions:
src/core/utils/crypto
) to handle PKCS12 read operations. I'm not opposed to moving this somewhere else, but this seemed to be the most logical place to put this code.kbn-dev-utils
.NOTE: It will be much easier to review this PR commit by commit.
Resolves: #17039
"Release note: Kibana now supports the usage of PKCS#12 (P12) key stores and trust stores for certificates and keys."