[
https://issues.apache.org/jira/browse/IGNITE-28867?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Anton Vinogradov updated IGNITE-28867:
--------------------------------------
Description:
Allow administrators to replace TLS certificates and trust stores without
restarting nodes. When an external system supplies new certificates, allow
Ignite to load them automatically before the current chain expires.
h3. What each part provides and what uses it
# IGNITE-29208 preserves the peer address when SSLContextWrapper creates an
engine. This independently fixes existing addressed client engines. [PR
#13750|https://github.com/apache/ignite/pull/13750] is merged.
# IGNITE-29209 makes the factory own an accepted SslBundle built from one
loaded KeyMaterial, containing the context and nonempty X.509 chains from key
entries. create() returns a stable forwarding context; init() loads and
publishes replacement material. Entries without such a chain are omitted.
IGNITE-29210 checks the dates of included chains, reports them in status and
rejects a known empty chain map; a mixed store is not rejected merely because
other entries were skipped. IGNITE-29211 uses the earliest expiry across all
reported chains to schedule renewal. SSLContextWrapper handles TLS parameters
only. [PR #13751|https://github.com/apache/ignite/pull/13751] is open.
# IGNITE-29210 registers factories and their transports and provides manual
reload and status for discovery, communication, the client connector and binary
REST. Its provider delegates to factory-owned state. Factory init() validates
and replaces the context and metadata together, keeping transports sharing a
factory on the same certificates. IGNITE-29211 reuses this replacement
mechanism for scheduled attempts; IGNITE-29212 connects HTTP REST to it.
# IGNITE-29211 adds a factory-owned renewal planner and unsuccessful-attempt
counter, using an executor owned and stopped by the node, plus the
ssl.ConsecutiveRenewalFailures metric. The factory installs an automatic
replacement only when every reported chain is valid and the minimum expiry
across all reported chains advances. A direct init() call also replans renewal.
The certificate source remains responsible for supplying replacements.
# IGNITE-29212 adds httpSslFactory so Jetty HTTP REST can use managed contexts.
This makes HTTPS certificates available to reload and status, and to automatic
renewal once IGNITE-29211 is present.
The factory API change is contained in IGNITE-29209: create() is final,
initializes on first use and then returns the same forwarding context without
rereading stores. init() loads a candidate through createSslBundle() and
publishes its context and metadata together; a failed initialization preserves
the accepted bundle. sslBundle() returns that accepted snapshot. The protected
sslCtx field and no-argument createKeyManagers() hook are removed; affected
subclasses must move store loading to loadKeyMaterial(), remove custom caching
and be recompiled.
Custom key managers require a createSslBundle() override that initializes a
fresh context, configures its trust and TLS settings, and returns matching
certificate metadata. To decorate an already built context, call
super.createSslBundle() and retain its certificate chains in the returned
bundle. Loaded stores must remain unchanged while their contexts are in use.
Sources providing ready-made contexts can use plain Factory<SSLContext> with
unknown metadata; IGNITE-29210 adapts them while retaining the original factory
identity for registration. Communication keeps its context between connections.
Ownership of the accepted bundle remains in the factory throughout the later
parts. Newly created engines and newly obtained socket factories use
replacement material; previously obtained engines, socket factories and sockets
retain their original material.
h3. Review and merge order
All five subtasks are created and their branches are prepared. IGNITE-29208 is
merged. Review and merge IGNITE-29209 next; certificate metadata is carried by
SslBundle and does not depend on SSLContextWrapper.
Open the PR for IGNITE-29210 after IGNITE-29209 merges. Open IGNITE-29211 and
IGNITE-29212 after IGNITE-29210 merges. Automatic renewal and HTTP REST may
then merge in either order.
After both IGNITE-29211 and IGNITE-29212 are present, include the single
[prepared integration
commit|https://github.com/anton-vinogradov/ignite/commit/e1a7c86c428cf775ef86750bfdca746d1cdeb88c]
in the PR that merges second. It replaces the old integration patch list. It
adds HTTP REST renewal documentation and Javadoc and an HTTPS test showing that
automatic renewal presents the replacement certificate on a new connection. Do
not apply earlier integration commits as well. Before merging that second PR,
run JettySslContextReloadTest and SslRenewalNodeTest.
h3. Updating branches after a squash merge
Before opening a dependent PR, create a new review branch from the current
master. Keep the prepared branch and record the exact head of its prerequisite
that was squash-merged. For example, prepare IGNITE-29210 after IGNITE-29209
has been squash-merged. Here upstream is apache/ignite and origin is the
contributor fork:
{code:bash}
git fetch upstream master
git fetch origin refs/heads/ignite-29210:refs/remotes/origin/ignite-29210
git switch -c ignite-29210-review upstream/master
git diff <recorded-ignite-29209-head> origin/ignite-29210 | git apply --index
git diff --cached --check
git diff --cached
{code}
Resolve any rejected hunks, run the relevant tests, then commit and push the
new review branch. This preserves the prepared branches and requires no
force-push. If a PR is already open, merge master into its branch normally
instead. When integrating the API change with master, retain the SSL wrapper
regression and new SSL test registrations in SecurityTestSuite.
When combining automatic renewal and HTTP REST, retain
CurrentSslContext.engineGetDefaultSSLParameters(). It must forward to the
active context so Jetty retains the configured protocols and cipher suites.
JettySslContextReloadTest checks the protocols and cipher suites that Jetty
uses.
h3. Completion criteria
Each PR includes its tests and documentation and passes CI on its current head.
Update dependent branches after their prerequisites merge so reviewers see only
the changes belonging to that task.
The initialization API is published in PR #13751 at 22e3ec58. The combined
implementation passed 86 targeted SSL tests locally, with two existing JMX
variants skipped. These local checks and CI results from earlier revisions do
not establish a full CI result for the current rework.
Reload checks available certificate metadata and supported TLS settings.
Administrators remain responsible for peer trust and testing new connections.
Close this umbrella after all five parts merge and the combined solution passes
SSL tests, including mutual TLS and compatibility with existing configurations.
[PR #13335|https://github.com/apache/ignite/pull/13335] is the original
prototype from which these changes were split. Its factory API is superseded by
IGNITE-29209.
was:
Allow administrators to replace TLS certificates and trust stores without
restarting nodes. When an external system supplies new certificates, allow
Ignite to load them automatically before the current chain expires.
h3. What each part provides and what uses it
# IGNITE-29208 preserves the peer address when SSLContextWrapper creates an
engine. This independently fixes existing addressed client engines. [PR
#13750|https://github.com/apache/ignite/pull/13750] is merged.
# IGNITE-29209 builds a fresh SslBundle from one loaded KeyMaterial, containing
the context and nonempty X.509 chains from key entries. Entries without such a
chain are omitted. IGNITE-29210 checks the dates of included chains, reports
them in status and rejects a known empty chain map; a mixed store is not
rejected merely because other entries were skipped. IGNITE-29211 uses the
earliest expiry across all reported chains to schedule renewal.
SSLContextWrapper handles TLS parameters only. [PR
#13751|https://github.com/apache/ignite/pull/13751] is open.
# IGNITE-29210 owns the current bundle for each factory and provides manual
reload and status for discovery, communication, the client connector and binary
REST. It validates and replaces the context and metadata together, keeping
transports sharing a factory on the same certificates. IGNITE-29211 reuses this
replacement mechanism for scheduled attempts; IGNITE-29212 connects HTTP REST
to it.
# IGNITE-29211 adds scheduling, retries and the ssl.ConsecutiveRenewalFailures
metric. It requests a fresh bundle and uses the reload mechanism to install it
only when every reported chain is valid and the minimum expiry across all
reported chains advances. The certificate source remains responsible for
supplying replacements.
# IGNITE-29212 adds httpSslFactory so Jetty HTTP REST can use managed contexts.
This makes HTTPS certificates available to reload and status, and to automatic
renewal once IGNITE-29211 is present.
The factory API change is contained in IGNITE-29209: create() is final, returns
createSslBundle().context() and always builds a fresh context. The protected
sslCtx cache and no-argument createKeyManagers() hook are removed; affected
subclasses must move store loading to loadKeyMaterial() and be recompiled.
Custom key managers require a createSslBundle() override that initializes a
fresh context, configures its trust and TLS settings, and returns matching
certificate metadata. To decorate an already built context, call
super.createSslBundle() and retain its certificate chains in the returned
bundle. Loaded stores must remain unchanged while their contexts are in use.
Sources providing ready-made contexts can use plain Factory<SSLContext> with
unknown metadata. The API change also keeps a context in communication so new
connections do not reload the store; IGNITE-29210 moves ownership into the
shared node registry.
h3. Review and merge order
All five subtasks are created and their branches are prepared. IGNITE-29208 is
merged. Review and merge IGNITE-29209 next; certificate metadata is carried by
SslBundle and does not depend on SSLContextWrapper.
Open the PR for IGNITE-29210 after IGNITE-29209 merges. Open IGNITE-29211 and
IGNITE-29212 after IGNITE-29210 merges. Automatic renewal and HTTP REST may
then merge in either order.
Include the [prepared integration
commit|https://github.com/anton-vinogradov/ignite/commit/a32c9b35f8147a62df23726874adb785353abc70]
in whichever of IGNITE-29211 and IGNITE-29212 merges second. It adds docs and
Javadoc about automatic renewal for HTTP REST, so it needs both parts. The node
renews the certificates of httpSslFactory the same way as for the other
transports, so HTTPS needs no renewal test of its own. Before merging that
second PR, run JettySslContextReloadTest and SslRenewalNodeTest.
h3. Updating branches after a squash merge
Before opening a dependent PR, create a new review branch from the current
master. Keep the prepared branch and record the exact head of its prerequisite
that was squash-merged. For example, prepare IGNITE-29210 after IGNITE-29209
has been squash-merged. Here upstream is apache/ignite and origin is the
contributor fork:
{code:bash}
git fetch upstream master
git fetch origin refs/heads/ignite-29210:refs/remotes/origin/ignite-29210
git switch -c ignite-29210-review upstream/master
git diff <recorded-ignite-29209-head> origin/ignite-29210 | git apply --index
git diff --cached --check
git diff --cached
{code}
Resolve any rejected hunks, run the relevant tests, then commit and push the
new review branch. This preserves the prepared branches and requires no
force-push. If a PR is already open, merge master into its branch normally
instead. When integrating the API change with master, retain the SSL wrapper
regression and new SSL test registrations in SecurityTestSuite.
When combining automatic renewal and HTTP REST, retain
CurrentSslContext.engineGetDefaultSSLParameters(). It must forward to the
active context so Jetty retains the configured protocols and cipher suites.
JettySslContextReloadTest checks the protocols and cipher suites that Jetty
uses.
h3. Completion criteria
Each PR includes its tests and documentation and passes CI on its current head.
Update dependent branches after their prerequisites merge so reviewers see only
the changes belonging to that task.
Reload checks available certificate metadata and supported TLS settings.
Administrators remain responsible for peer trust and testing new connections.
Close this umbrella after all five parts merge and the combined solution passes
SSL tests, including mutual TLS and compatibility with existing configurations.
[PR #13335|https://github.com/apache/ignite/pull/13335] is the original
prototype from which these changes were split. Its factory API is superseded by
IGNITE-29209.
> [Umbrella] TLS certificate reload and automatic renewal
> -------------------------------------------------------
>
> Key: IGNITE-28867
> URL: https://issues.apache.org/jira/browse/IGNITE-28867
> Project: Ignite
> Issue Type: Task
> Reporter: Mikhail Petrov
> Assignee: Anton Vinogradov
> Priority: Major
> Labels: ise
> Fix For: 2.19
>
> Time Spent: 6h 50m
> Remaining Estimate: 0h
>
> Allow administrators to replace TLS certificates and trust stores without
> restarting nodes. When an external system supplies new certificates, allow
> Ignite to load them automatically before the current chain expires.
> h3. What each part provides and what uses it
> # IGNITE-29208 preserves the peer address when SSLContextWrapper creates an
> engine. This independently fixes existing addressed client engines. [PR
> #13750|https://github.com/apache/ignite/pull/13750] is merged.
> # IGNITE-29209 makes the factory own an accepted SslBundle built from one
> loaded KeyMaterial, containing the context and nonempty X.509 chains from key
> entries. create() returns a stable forwarding context; init() loads and
> publishes replacement material. Entries without such a chain are omitted.
> IGNITE-29210 checks the dates of included chains, reports them in status and
> rejects a known empty chain map; a mixed store is not rejected merely because
> other entries were skipped. IGNITE-29211 uses the earliest expiry across all
> reported chains to schedule renewal. SSLContextWrapper handles TLS parameters
> only. [PR #13751|https://github.com/apache/ignite/pull/13751] is open.
> # IGNITE-29210 registers factories and their transports and provides manual
> reload and status for discovery, communication, the client connector and
> binary REST. Its provider delegates to factory-owned state. Factory init()
> validates and replaces the context and metadata together, keeping transports
> sharing a factory on the same certificates. IGNITE-29211 reuses this
> replacement mechanism for scheduled attempts; IGNITE-29212 connects HTTP REST
> to it.
> # IGNITE-29211 adds a factory-owned renewal planner and unsuccessful-attempt
> counter, using an executor owned and stopped by the node, plus the
> ssl.ConsecutiveRenewalFailures metric. The factory installs an automatic
> replacement only when every reported chain is valid and the minimum expiry
> across all reported chains advances. A direct init() call also replans
> renewal. The certificate source remains responsible for supplying
> replacements.
> # IGNITE-29212 adds httpSslFactory so Jetty HTTP REST can use managed
> contexts. This makes HTTPS certificates available to reload and status, and
> to automatic renewal once IGNITE-29211 is present.
> The factory API change is contained in IGNITE-29209: create() is final,
> initializes on first use and then returns the same forwarding context without
> rereading stores. init() loads a candidate through createSslBundle() and
> publishes its context and metadata together; a failed initialization
> preserves the accepted bundle. sslBundle() returns that accepted snapshot.
> The protected sslCtx field and no-argument createKeyManagers() hook are
> removed; affected subclasses must move store loading to loadKeyMaterial(),
> remove custom caching and be recompiled.
> Custom key managers require a createSslBundle() override that initializes a
> fresh context, configures its trust and TLS settings, and returns matching
> certificate metadata. To decorate an already built context, call
> super.createSslBundle() and retain its certificate chains in the returned
> bundle. Loaded stores must remain unchanged while their contexts are in use.
> Sources providing ready-made contexts can use plain Factory<SSLContext> with
> unknown metadata; IGNITE-29210 adapts them while retaining the original
> factory identity for registration. Communication keeps its context between
> connections. Ownership of the accepted bundle remains in the factory
> throughout the later parts. Newly created engines and newly obtained socket
> factories use replacement material; previously obtained engines, socket
> factories and sockets retain their original material.
> h3. Review and merge order
> All five subtasks are created and their branches are prepared. IGNITE-29208
> is merged. Review and merge IGNITE-29209 next; certificate metadata is
> carried by SslBundle and does not depend on SSLContextWrapper.
> Open the PR for IGNITE-29210 after IGNITE-29209 merges. Open IGNITE-29211 and
> IGNITE-29212 after IGNITE-29210 merges. Automatic renewal and HTTP REST may
> then merge in either order.
> After both IGNITE-29211 and IGNITE-29212 are present, include the single
> [prepared integration
> commit|https://github.com/anton-vinogradov/ignite/commit/e1a7c86c428cf775ef86750bfdca746d1cdeb88c]
> in the PR that merges second. It replaces the old integration patch list. It
> adds HTTP REST renewal documentation and Javadoc and an HTTPS test showing
> that automatic renewal presents the replacement certificate on a new
> connection. Do not apply earlier integration commits as well. Before merging
> that second PR, run JettySslContextReloadTest and SslRenewalNodeTest.
> h3. Updating branches after a squash merge
> Before opening a dependent PR, create a new review branch from the current
> master. Keep the prepared branch and record the exact head of its
> prerequisite that was squash-merged. For example, prepare IGNITE-29210 after
> IGNITE-29209 has been squash-merged. Here upstream is apache/ignite and
> origin is the contributor fork:
> {code:bash}
> git fetch upstream master
> git fetch origin refs/heads/ignite-29210:refs/remotes/origin/ignite-29210
> git switch -c ignite-29210-review upstream/master
> git diff <recorded-ignite-29209-head> origin/ignite-29210 | git apply --index
> git diff --cached --check
> git diff --cached
> {code}
> Resolve any rejected hunks, run the relevant tests, then commit and push the
> new review branch. This preserves the prepared branches and requires no
> force-push. If a PR is already open, merge master into its branch normally
> instead. When integrating the API change with master, retain the SSL wrapper
> regression and new SSL test registrations in SecurityTestSuite.
> When combining automatic renewal and HTTP REST, retain
> CurrentSslContext.engineGetDefaultSSLParameters(). It must forward to the
> active context so Jetty retains the configured protocols and cipher suites.
> JettySslContextReloadTest checks the protocols and cipher suites that Jetty
> uses.
> h3. Completion criteria
> Each PR includes its tests and documentation and passes CI on its current
> head. Update dependent branches after their prerequisites merge so reviewers
> see only the changes belonging to that task.
> The initialization API is published in PR #13751 at 22e3ec58. The combined
> implementation passed 86 targeted SSL tests locally, with two existing JMX
> variants skipped. These local checks and CI results from earlier revisions do
> not establish a full CI result for the current rework.
> Reload checks available certificate metadata and supported TLS settings.
> Administrators remain responsible for peer trust and testing new connections.
> Close this umbrella after all five parts merge and the combined solution
> passes SSL tests, including mutual TLS and compatibility with existing
> configurations.
> [PR #13335|https://github.com/apache/ignite/pull/13335] is the original
> prototype from which these changes were split. Its factory API is superseded
> by IGNITE-29209.
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)