[ 
https://issues.apache.org/jira/browse/IGNITE-29209?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Anton Vinogradov updated IGNITE-29209:
--------------------------------------
    Description: 
Keep an SSL context and its certificate metadata from the same key-store read. 
Applications can explicitly replace that material without changing their 
context reference. IGNITE-29210 uses the accepted snapshot for reload 
validation and status; IGNITE-29211 uses its certificate expiry dates for 
renewal.

h3. Result and acceptance

* {{init()}} prepares a fresh bundle, verifies that its context can create an 
engine, then publishes context and metadata together. A failed attempt retains 
the previous bundle; a failed first attempt can be retried.
* {{create()}} initializes once, including concurrent first calls, and returns 
one forwarding context. {{sslBundle()}} returns the accepted snapshot. Repeated 
reads do not reload stores; serialization keeps configuration rather than 
runtime contexts.
* New engines and newly obtained socket factories use the replacement. 
Previously obtained engines, socket factories and sockets retain their 
material. Reusing an initialized factory across node restarts retains its 
material until {{init()}}.
* Metadata contains immutable, nonempty X.509 chains of key entries. Unknown 
metadata and an empty set of chains remain distinct. Metadata describes loaded 
material, not the certificate selected for a connection.
* Communication reconnects reuse the retained context, including with a plain 
{{Factory<SSLContext>}}.

h3. Compatibility

Affected subclasses must be updated and recompiled: {{create()}} becomes final; 
{{loadKeyMaterial()}} replaces {{createKeyManagers()}}, and the protected 
{{sslCtx}} field is removed. Custom contexts use {{createSslBundle()}}; 
invoking that loading hook alone does not publish a replacement. See the 
[factory 
contracts|https://github.com/anton-vinogradov/ignite/blob/ignite-29209/modules/commons/src/main/java/org/apache/ignite/ssl/AbstractSslContextFactory.java#L116]
 and [migration 
reference|https://github.com/anton-vinogradov/ignite/blob/ignite-29210/docs/_docs/security/ssl-tls.adoc#migrating-an-existing-factory].

A plain {{Factory<SSLContext>}} remains supported. Empty loaded stores support 
clients without private keys. Loaded stores must remain unchanged while their 
contexts are in use; see [KeyMaterial ownership and metadata 
rules|https://github.com/anton-vinogradov/ignite/blob/ignite-29209/modules/commons/src/main/java/org/apache/ignite/ssl/KeyMaterial.java#L38].
 Unsupported TLS names fail first initialization; certificate-date and 
empty-chain replacement policies belong to IGNITE-29210.

h3. Delivery and validation

[PR #13751|https://github.com/apache/ignite/pull/13751] is the standalone API 
change; IGNITE-29208's peer-address fix is already merged. At {{f6b57b36}}, the 
two startup-regression tests passed, then all 16 API tests passed after scope 
cleanup. Both reactor runs included Checkstyle; Javadoc/doclint passed. These 
are local targeted checks, not full CI.


  was:
Keep an SSL context together with the certificate chains from the same loaded 
key material. IGNITE-29210 needs this information to validate replacement 
certificates and report status; IGNITE-29211 needs certificate expiry dates to 
schedule renewal. Reading the store separately for reporting could describe 
different material from the context in use.

h3. Result

{{AbstractSslContextFactory}} builds an {{SslBundle}} from {{KeyMaterial}} 
containing the loaded key store, key password and manager algorithm. 
{{SslContextFactory}} loads the store. Key managers and certificate metadata 
come from that same store load. The loaded store must remain unchanged while 
any context built from it is in use, because some key-manager providers read it 
during handshakes. Load a new store when replacing certificates.

The bundle contains an initialized context and an immutable map of key-store 
aliases to nonempty X.509 chains. A {{null}} map means certificate metadata is 
unknown; an empty map means no nonempty X.509 chains were found for key 
entries. {{SslBundle}} rejects empty lists, including from custom factories.

{{KeyMaterial}} includes chains from key entries only. It skips entries without 
a nonempty chain or with a non-X.509 certificate, and does not extract keys or 
determine their type for reporting. Multiple chains are supported. The metadata 
describes the loaded material, not the certificate selected for a particular 
connection, and does not establish private-key availability.

For a client context without private keys, supply an empty loaded store. The 
store passed to {{KeyMaterial}} and the result of {{loadKeyMaterial()}} must 
both be non-null. Node reload rejects a known empty chain map and validates the 
included chains. A mixed store is not rejected merely because other entries 
were skipped. {{SSLContextWrapper}} remains responsible only for TLS parameters.

h3. Factory contract and migration

{{AbstractSslContextFactory}} owns the accepted {{SslBundle}}. Its final 
{{create()}} method initializes the factory on first use and returns the same 
forwarding context thereafter, without reloading the stores. {{sslBundle()}} 
returns the accepted snapshot, initializing the factory if necessary.

{{init()}} loads a candidate through {{createSslBundle()}}, checks that its 
context can create an engine, and publishes the context and metadata together. 
A failed call leaves the previous bundle in use. The public 
{{createSslBundle()}} hook still loads a fresh candidate; calling it alone does 
not replace the accepted material. Certificate-date checks and rejection of 
known empty metadata belong to IGNITE-29210.

After initialization, newly created engines and newly obtained socket factories 
use the accepted material. Previously obtained engines, socket factories and 
sockets retain their original material. Configure the factory before its first 
use; runtime contexts are not serialized with its configuration.

Removing the protected {{sslCtx}} field and no-argument {{createKeyManagers()}} 
hook, and making {{create()}} final, requires affected subclasses to be updated 
and recompiled. Remove custom context caching: the base factory retains the 
accepted bundle, and {{init()}} loads a replacement.

Move store loading into {{loadKeyMaterial()}}. For custom key managers, 
override {{createSslBundle()}} to initialize a fresh context with those 
managers, configure its trust and TLS settings, and return matching certificate 
metadata. For customization of an already built context, call 
{{super.createSslBundle()}} and retain its certificate chains in the returned 
bundle.

A source providing a ready-made context can use a plain {{Factory<SSLContext>}} 
with unknown metadata.

Transports that share an {{AbstractSslContextFactory}} instance obtain the same 
forwarding context and accepted material. Communication retains its context 
between connections, so opening a connection does not reload stores. 
IGNITE-29210 adds node registration, manual reload and status without 
introducing a second owner of the bundle.

h3. Verification and consumers

Verify fresh loading through {{init()}}, cached access through {{create()}} and 
{{sslBundle()}}, concurrent first initialization, retry after failure, 
preservation of the accepted bundle when a replacement fails, and forwarding to 
replacement material. Also cover one-load consistency, all included chains from 
key entries, immutable metadata, custom store loaders, TLS parameters, and 
context reuse across communication connections.

Check that missing and non-X.509 chains are omitted, mixed stores keep their 
eligible chains without recovering keys for metadata, empty lists are rejected 
by {{SslBundle}}, and unknown metadata stays {{null}}.

The initialization API is published in [PR 
#13751|https://github.com/apache/ignite/pull/13751] at {{22e3ec58}}. All 16 API 
tests passed locally, and the two strengthened tests passed again; Checkstyle 
and Javadoc/doclint passed. The previous full CI run does not cover this 
rework; no new full CI result is claimed.

IGNITE-29208's independent peer-address fix is already merged. The [prepared 
node 
integration|https://github.com/anton-vinogradov/ignite/compare/ignite-29209...ignite-29210]
 demonstrates transport registration and delegation to the factory-owned 
bundle. IGNITE-29210 owns manual reload, validation and status; IGNITE-29211 
adds automatic renewal; IGNITE-29212 connects HTTP REST to the shared reload 
mechanism. Those changes are outside this API task.



> Add SSL bundle metadata and explicit factory initialization
> -----------------------------------------------------------
>
>                 Key: IGNITE-29209
>                 URL: https://issues.apache.org/jira/browse/IGNITE-29209
>             Project: Ignite
>          Issue Type: Sub-task
>            Reporter: Anton Vinogradov
>            Assignee: Anton Vinogradov
>            Priority: Major
>              Labels: ise
>          Time Spent: 3h 40m
>  Remaining Estimate: 0h
>
> Keep an SSL context and its certificate metadata from the same key-store 
> read. Applications can explicitly replace that material without changing 
> their context reference. IGNITE-29210 uses the accepted snapshot for reload 
> validation and status; IGNITE-29211 uses its certificate expiry dates for 
> renewal.
> h3. Result and acceptance
> * {{init()}} prepares a fresh bundle, verifies that its context can create an 
> engine, then publishes context and metadata together. A failed attempt 
> retains the previous bundle; a failed first attempt can be retried.
> * {{create()}} initializes once, including concurrent first calls, and 
> returns one forwarding context. {{sslBundle()}} returns the accepted 
> snapshot. Repeated reads do not reload stores; serialization keeps 
> configuration rather than runtime contexts.
> * New engines and newly obtained socket factories use the replacement. 
> Previously obtained engines, socket factories and sockets retain their 
> material. Reusing an initialized factory across node restarts retains its 
> material until {{init()}}.
> * Metadata contains immutable, nonempty X.509 chains of key entries. Unknown 
> metadata and an empty set of chains remain distinct. Metadata describes 
> loaded material, not the certificate selected for a connection.
> * Communication reconnects reuse the retained context, including with a plain 
> {{Factory<SSLContext>}}.
> h3. Compatibility
> Affected subclasses must be updated and recompiled: {{create()}} becomes 
> final; {{loadKeyMaterial()}} replaces {{createKeyManagers()}}, and the 
> protected {{sslCtx}} field is removed. Custom contexts use 
> {{createSslBundle()}}; invoking that loading hook alone does not publish a 
> replacement. See the [factory 
> contracts|https://github.com/anton-vinogradov/ignite/blob/ignite-29209/modules/commons/src/main/java/org/apache/ignite/ssl/AbstractSslContextFactory.java#L116]
>  and [migration 
> reference|https://github.com/anton-vinogradov/ignite/blob/ignite-29210/docs/_docs/security/ssl-tls.adoc#migrating-an-existing-factory].
> A plain {{Factory<SSLContext>}} remains supported. Empty loaded stores 
> support clients without private keys. Loaded stores must remain unchanged 
> while their contexts are in use; see [KeyMaterial ownership and metadata 
> rules|https://github.com/anton-vinogradov/ignite/blob/ignite-29209/modules/commons/src/main/java/org/apache/ignite/ssl/KeyMaterial.java#L38].
>  Unsupported TLS names fail first initialization; certificate-date and 
> empty-chain replacement policies belong to IGNITE-29210.
> h3. Delivery and validation
> [PR #13751|https://github.com/apache/ignite/pull/13751] is the standalone API 
> change; IGNITE-29208's peer-address fix is already merged. At {{f6b57b36}}, 
> the two startup-regression tests passed, then all 16 API tests passed after 
> scope cleanup. Both reactor runs included Checkstyle; Javadoc/doclint passed. 
> These are local targeted checks, not full CI.



--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

Reply via email to