# Needed explanation for keystore's PrivateKey entries

**URL:** <https://discuss.elastic.co/t/needed-explanation-for-keystores-privatekey-entries/380600>\
**Category:** Elasticsearch\
**Tags:** elastic-stack-security\
**Created:** [July 30, 2025, 5:15pm UTC](https://discuss.elastic.co/t/needed-explanation-for-keystores-privatekey-entries/380600 "2025-07-30T17:15:16Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![HarimbolaSantatra](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/harimbolasantatra/32/136974_2.png) [@HarimbolaSantatra](https://discuss.elastic.co/u/HarimbolaSantatra)\
**Post date:** [July 30, 2025, 5:15pm UTC](https://discuss.elastic.co/t/needed-explanation-for-keystores-privatekey-entries/380600/1 "2025-07-30T17:15:16Z")

</div>

I encountered the following issue when I try to enroll a token for Kibana:

```bash
$ ./bin/elasticsearch-create-enrollment-token --scope kibana
Unable to create enrollment token for scope [kibana]

ERROR: Unable to create an enrollment token. Elasticsearch node HTTP layer SSL configuration Keystore doesn't contain any PrivateKey entries where the associated certificate is a CA certificate, with exit code 73

```

So I found [this thread](https://discuss.elastic.co/t/import-ca-cert-as-privatekeyentry-to-http-keystore-solve-unable-to-create-enrollment-token-error/313780).

When I follow the author's instruction, after the command

```bash
./jdk/bin/keytool -importkeystore -destkeystore /etc/elasticsearch/certs/new-keystore.p12 -srckeystore /etc/elasticsearch/certs/http.p12 -srcstoretype PKCS12

```

, it yields the error:

```auto
keytool error: java.security.UnrecoverableKeyException: Get Key failed: Given final block not properly padded. Such issues can arise if a bad key is used during decryption

```

[Another post](https://discuss.elastic.co/t/elasticsearch-ssl-certificate-error-javax-crypto-badpaddingexception-given-final-block-not-properly-padded/247783) suggests me to set  
`xpack.security.transport.ssl.keystore.secure_password` and `xpack.security.transport.ssl.truststore.secure_password`.

But at this point, I want to understand what is really going on.

What does the error "_Elasticsearch node HTTP layer SSL configuration Keystore doesn't contain any PrivateKey entries where the associated certificate is a CA certificate_" really mean ?

I don't understand since when I do `keytool -keystore /etc/elasticsearch/certs/http.ca -list`, it shows that I have one entry `PrivateKeyEntry`:

```auto
Your keystore contains 1 entry

http, Jul 5, 2025, PrivateKeyEntry, 
Certificate chain length: 0

```

Continuing the discussion from [Import CA Cert as PrivateKeyEntry to HTTP Keystore - Solve Unable to create enrollment token Error](https://discuss.elastic.co/t/import-ca-cert-as-privatekeyentry-to-http-keystore-solve-unable-to-create-enrollment-token-error/313780), the author wrote that:

> [@Import CA Cert as PrivateKeyEntry to HTTP Keystore - Solve Unable to create enrollment token Error](https://discuss.elastic.co/t/import-ca-cert-as-privatekeyentry-to-http-keystore-solve-unable-to-create-enrollment-token-error/313780/1):
>
> This step changes the CA Cert that was automatically imported into the original HTTP Keystore as TrustCertEntry to PrivateKeyEntry, and this is exactly what that ERROR tells us to do.

... but I still does not understand that sentence.

Thank you!

---

<div class="post-metadata">

**Author:** ![aold619](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/aold619/32/110521_2.png) [@aold619](https://discuss.elastic.co/u/aold619)\
**Post date:** [July 31, 2025, 1:24am UTC](https://discuss.elastic.co/t/needed-explanation-for-keystores-privatekey-entries/380600/2 "2025-07-31T01:24:29Z")

</div>

Apologies if my previous post was unclear — English is not my first language, and I realize I could have explained it better.

What I meant to is that the error message indicates that the HTTPS configuration in Elasticsearch expects a **PrivateKeyEntry** , not a **trustedCertEntry**. This means the keystore used must contain a private key (typically from a CA-signed certificate), not just trusted certificates.

In the context of Elasticsearch 7 and 8, you can inspect the keystore using the command:

```bash
keytool -keystore <your-http-pkcs-path.p12> -list

```

Here’s an example of what you might see when the keystore contains a `trustedCertEntry`:

```txt
Keystore type: PKCS12
Keystore provider: SUN

Your keystore contains 2 entries
   ca, Sep 6, 2022, trustedCertEntry,
   Certificate fingerprint (SHA-256): 25:27:7D:EE:FE:F6:54:57:47:BE:B5:10:C4:90:DF:28:BF:1B:3B:F9:5E:47:F5:34:5F:03:38:1E:84:0A:23:E7
   http, Sep 6, 2022, PrivateKeyEntry,
   Certificate fingerprint (SHA-256): D4:EF:60:2C:E5:2D:4C:A8:33:C0:49:44:F4:B5:38:19:92:97:72:CB:5D:85:20:A4:97:9B:90:24:D0:0C:D1:FB

```

But what we actually need is something like this — both entries must be of type `PrivateKeyEntry`:

```txt
Keystore type: PKCS12
Keystore provider: SUN

Your keystore contains 2 entries
   ca, Sep 5, 2022, PrivateKeyEntry,
   Certificate fingerprint (SHA-256): 53:F4:9A:9D:56:A9:3A:AF:90:94:41:FA:D7:15:3F:DF:C1:39:AC:BA:FF:12:44:C0:36:4D:15:4C:20:14:1E:3D
   http, Sep 5, 2022, PrivateKeyEntry,
   Certificate fingerprint (SHA-256): EF:8D:78:EC:F0:C5:97:1B:7B:58:EF:5F:E3:73:A5:D0:7E:1B:FE:B3:75:B0:B4:D9:CB:80:FC:B3:8E:5D:A5:74

```

The key point is that your HTTP certificate must be imported in a way that includes both the private key and its full chain of trust, resulting in entries marked as `PrivateKeyEntry`.

According to the documentation for Elasticsearch 7.x and 8.x, we usually receive a **.p12** file that contains the CA certificate — by default, it's named `elastic-stack-ca.p12`. We also get a ZIP file intended for HTTPS usage, which contains `http.p12` after extraction.

To replace the existing **trustedCertEntry** with a valid **PrivateKeyEntry** , you can run the following command:

```bash
keytool -importkeystore -destkeystore http.p12 -srckeystore elastic-stack-ca.p12 -srcstoretype PKCS12

```

* * *

If you're working with Elasticsearch 9.0+, I recommend following the [latest official documentation](https://www.elastic.co/docs/deploy-manage/security/set-up-basic-security-plus-https), as some of the commands have changed. I haven’t verified whether the same process works in newer versions — this explanation is mainly meant to clarify my previous post and provide additional context.

I hope this time my explanation is clear enough.

---

<div class="post-metadata">

**Author:** ![TimV](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/timv/32/13162_2.png) [@TimV](https://discuss.elastic.co/u/TimV)\
**Post date:** [July 31, 2025, 3:42am UTC](https://discuss.elastic.co/t/needed-explanation-for-keystores-privatekey-entries/380600/3 "2025-07-31T03:42:55Z")

</div>

The short answer is that you're trying to use enrollment tokens on a cluster that doesn't use security auto-configuration.

That _can_ be made to work, but it requires following a number of undocumented steps.

The general premise is:

- If you let the cluster auto configure security, then use the enrollment utilities
- If you configured security yourself, then configure everything yourself, including Kibana.

It would be nice to support more middle ground, but that's not the case right now.

Rather than messing about with keystores, what you really want is to just configure Kibana yourself.

I would love to be able to point you to a simple set of instructions for that, but I think it has been lost in multiple rounds of docs updates.

The short answer:

**Step 1** :  
Create a service token for Kibana

- [Create a service account token | Elasticsearch API documentation](https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-security-create-service-token)

```auto
POST /_security/service/elastic/kibana/credential/token/kibana1

```

**Step 2** :  
Copy the `value` from that API into your Kibana YAML settings under `elasticsearch.serviceAccountToken`

**`kibana.yml`**

```YAML
elasticsearch.serviceAccountToken: "AAEAAWVsYXN0aWM...vZmxlZXQtc2VydmVyL3Rva2VuMTo3TFdaSDZ" 

```

**Step 3** :  
Configure TLS trust between Kibana and Elasticsearch if necessary.  
I can't give you direct instructions for this step without knowing what your Elasticsearch SSL configuration looks like.  
You probably want to configure `elasticsearch.ssl.certificateAuthorities` in your `kibana.yml` to point to the PEM encoded CA for Elasticsearch (something like `ca.crt` or `ca.pem`)

That's all the enrollment token is really doing, and you could try and make it work, but it's probably easier to do it by hand.

---

<div class="post-metadata">

**Author:** ![HarimbolaSantatra](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/harimbolasantatra/32/136974_2.png) [@HarimbolaSantatra](https://discuss.elastic.co/u/HarimbolaSantatra)\
**Post date:** [August 4, 2025, 7:36pm UTC](https://discuss.elastic.co/t/needed-explanation-for-keystores-privatekey-entries/380600/4 "2025-08-04T19:36:59Z")

</div>

Kibana opens successfully now but I did some things that you didn't mention so I want to make sure I did the right thing and followed best practice.

1. Create a service token for Kibana via the API
2. Copy the `value` from that API into your Kibana YAML settings under `elasticsearch.serviceAccountToken`
3. Configure TLS between Kibana and ES. For that I set `elasticsearch.ssl.certificateAuthorities` to `http_ca.crt` (The certificate of the ES instance)
4. After these steps were done, Kibana still asked for the token on the webUI **despite me doing Step 2**. I put the same token from _step 2_ on the form.
5. Kibana also asked me if I trust the certificate **despite me doing Step 3**.

Why was step 4 and 5 necessary ? Or is it because I misconfigured _step 2_ and _step 3_ so these two steps were not considered by Kibana ?

---

<div class="post-metadata">

**Author:** ![stephenb](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/stephenb/32/40856_2.png) [@stephenb](https://discuss.elastic.co/u/stephenb)\
**Post date:** [August 4, 2025, 8:38pm UTC](https://discuss.elastic.co/t/needed-explanation-for-keystores-privatekey-entries/380600/5 "2025-08-04T20:38:58Z")

</div>

Hi @HarimbolaSantatra  
Please share your kibana.yml

---

<div class="post-metadata">

**Author:** ![HarimbolaSantatra](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/harimbolasantatra/32/136974_2.png) [@HarimbolaSantatra](https://discuss.elastic.co/u/HarimbolaSantatra)\
**Post date:** [August 5, 2025, 4:01pm UTC](https://discuss.elastic.co/t/needed-explanation-for-keystores-privatekey-entries/380600/6 "2025-08-05T16:01:35Z")

</div>

Here is my `kibana.yml`:

```yaml
elasticsearch.ssl.certificateAuthorities: [/var/lib/kibana/ca_1754335525818.crt]
logging.appenders.file.type: file
logging.appenders.file.fileName: /var/log/kibana/kibana.log
logging.appenders.file.layout.type: json
logging.root.appenders: [default, file]
pid.file: /run/kibana/kibana.pid
elasticsearch.hosts: [https://192.168.3.1:9200]
elasticsearch.username: kibana_system
elasticsearch.password: <THE_PASSWORD_FROM_LAST_STEP>
xpack.fleet.outputs: [{id: fleet-default-output, name: default, is_default: true, is_default_monitoring: true, type: elasticsearch, hosts: [https://192.168.3.1:9200], ca_trusted_fingerprint: 722eea01ba32bd8e2f4fa0a802b2023c1ce55ec1411ba401ca610635261cec27}]

```

Thank you for your support!

---

<div class="post-metadata">

**Author:** ![stephenb](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/stephenb/32/40856_2.png) [@stephenb](https://discuss.elastic.co/u/stephenb)\
**Post date:** [August 5, 2025, 6:22pm UTC](https://discuss.elastic.co/t/needed-explanation-for-keystores-privatekey-entries/380600/7 "2025-08-05T18:22:22Z")

</div>

I do not see where you added the service account in your yaml file

`elasticsearch.serviceAccountToken`

Well so you still have the username and password which you wouldn't need with the service account.

---

<div class="post-metadata">

**Author:** ![HarimbolaSantatra](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/harimbolasantatra/32/136974_2.png) [@HarimbolaSantatra](https://discuss.elastic.co/u/HarimbolaSantatra)\
**Post date:** [August 6, 2025, 3:45pm UTC](https://discuss.elastic.co/t/needed-explanation-for-keystores-privatekey-entries/380600/8 "2025-08-06T15:45:09Z")

</div>

Sorry I didn't pay attention.

The `elasticsearch.serviceAccountToken` and the `elasticsearch.ssl.certificateAuthorities` that I configured was automatically commented.

In `kibana.yml` there is also these lines before the snippets I inserted:

```auto
### >>>>>>> BACKUP END: Kibana interactive setup (2025-08-04T19:25:25.822Z)

# This section was automatically generated during setup.

```

So I guess the configuration that I did was discarded automatically after the configuration on the Web UI.
