[
https://issues.apache.org/jira/browse/IGNITE-29211?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Anton Vinogradov updated IGNITE-29211:
--------------------------------------
Description:
Automatically load certificates delivered by an external system before the
current chain expires. That system issues and publishes replacements; Ignite
loads them at scheduled attempts. Manual file replacement and trust-store-only
changes still use {{--ssl reload}}: renewal does not watch files for changes.
h3. How renewal works
Add opt-in settings to AbstractSslContextFactory, disabled by default. Use the
current {{SslBundle}} to schedule from the earliest expiry across all reported
X.509 chains, including CA certificates. The renewal window is
renewBeforeFraction of the interval from the selected chain's leaf validity
start to its earliest expiry. When expiry dates tie, use the earliest leaf
validity start to determine the window.
Require at least one reported X.509 chain at startup and on every replacement.
A null map means metadata is unknown; an empty map means no eligible chains
were found. Reject both when renewal is enabled because neither supplies an
expiry date. Entries without a nonempty X.509 chain are omitted by
{{KeyMaterial}} and are not monitored.
The factory owns the accepted bundle, replacement checks and reload outcome
from IGNITE-29210. It also owns its renewal planner and unsuccessful-attempt
count; the node supplies and stops the executor. Automatic attempts call
{{renew(expectedContext)}} on the factory, using the same fresh-loading hook
and replacement checks as manual {{init()}}.
Install the whole bundle only when every reported chain is currently valid and
the minimum expiry across all reported chains increases. Aliases may be
renamed, added or removed; no match with the previous alias names is required.
If an entry loses its chain, its alias disappears from metadata and renewal
uses the remaining chains, just as when an alias is removed.
If the minimum expiry does not advance, loading fails or validation rejects the
replacement, retain the current bundle and retry with bounded backoff and
jitter, including after expiry. Show the next attempt in {{--ssl status}} and
log the cause.
Serialize renewal and manual {{init()}} on the factory, replan after a
successful replacement and prevent an obsolete automatic attempt from
installing its result. Direct application calls to {{init()}} use the same
replacement, replan and counter rules. Use the node's operation context so
scheduled work is attributed to the node. Shutdown interrupts and finishes
renewal work; cancellation must neither count as failure nor overwrite the last
reload result.
A factory with renewal enabled may attach to only one running node's renewal
executor. Use a separate factory instance for each running node. After that
executor stops, the same factory may attach to the restarted node with the
renewal settings configured for that restart. Reusing the factory object
retains its accepted material until {{init()}} loads a replacement; restarting
the node does not itself reread stores through that already initialized object.
h3. Monitoring and acceptance
Publish one node metric, {{ssl.ConsecutiveRenewalFailures}}, so monitoring can
detect unsuccessful delivery or loading. Sum consecutive unsuccessful automatic
attempts across distinct factories and count a shared factory once. An
unchanged minimum expiry counts as unsuccessful. Reset only the affected
factory's count when renewal or manual reload installs a bundle whose minimum
expiry across all reported chains is later. Failed manual reloads do not
increment this metric.
Test scheduling across all reported X.509 chains, CA expiry, retries after
expiry, unchanged material, alias changes and omitted chains, metric
aggregation and reset, reload races and shutdown. Cover direct {{init()}}
calls, reuse after the old executor stops and rejection of attachment to two
running renewal executors. Verify that a node with default renewal settings
plans no attempt and starts no renewal thread. Explain delivery prerequisites,
enabling renewal, inspecting failures and recovering with reload.
h3. Dependencies and remaining work
Implementation, tests and documentation are prepared on {{ignite-29211}}. Open
its PR after IGNITE-29210 is merged and run CI on the updated branch. HTTP REST
integration in IGNITE-29212 is independent.
After both IGNITE-29211 and IGNITE-29212 are present, apply the single
[prepared integration
commit|https://github.com/anton-vinogradov/ignite/commit/e1a7c86c428cf775ef86750bfdca746d1cdeb88c]
to the PR that merges second. It replaces the previous integration commits; do
not apply the old patch list as well. It updates HTTP REST renewal
documentation and Javadoc and adds an HTTPS test proving that automatic renewal
presents the replacement certificate on a new connection. On that combined
branch, run JettySslContextReloadTest and SslRenewalNodeTest.
was:
Automatically load certificates delivered by an external system before the
current chain expires. That system issues and publishes replacements; Ignite
loads them at scheduled attempts. Manual file replacement and trust-store-only
changes still use {{--ssl reload}}: renewal does not watch files for changes.
h3. How renewal works
Add opt-in settings to AbstractSslContextFactory, disabled by default. Use the
current {{SslBundle}} to schedule from the earliest expiry across all reported
X.509 chains, including CA certificates. The renewal window is
renewBeforeFraction of the interval from the selected chain's leaf validity
start to its earliest expiry. When expiry dates tie, use the earliest leaf
validity start to determine the window.
Require at least one reported X.509 chain at startup and on every replacement.
A null map means metadata is unknown; an empty map means no eligible chains
were found. Reject both when renewal is enabled because neither supplies an
expiry date. Entries without a nonempty X.509 chain are omitted by
{{KeyMaterial}} and are not monitored.
Request a fresh bundle through the same factory path as manual reload and reuse
IGNITE-29210's validation and replacement. Install the whole bundle only when
every reported chain is currently valid and the minimum expiry across all
reported chains increases. Aliases may be renamed, added or removed; no match
with the previous alias names is required. If an entry loses its chain, its
alias disappears from metadata and renewal uses the remaining chains, just as
when an alias is removed. If the minimum expiry does not advance, loading fails
or validation rejects the replacement, retain the current bundle and retry with
bounded backoff and jitter, including after expiry. Show the next attempt in
{{--ssl status}} and log the cause.
Serialize renewal and manual reload for each factory, replan after a successful
reload and prevent an obsolete automatic attempt from installing its result.
Use the node's operation context so scheduled work is attributed to the node.
Shutdown interrupts and finishes renewal work; cancellation must neither count
as failure nor overwrite the last reload result.
h3. Monitoring and acceptance
Publish one node metric, {{ssl.ConsecutiveRenewalFailures}}, so monitoring can
detect unsuccessful delivery or loading. Sum consecutive unsuccessful automatic
attempts across distinct factories and count a shared factory once. An
unchanged minimum expiry counts as unsuccessful. Reset only the affected
factory's count when renewal or manual reload installs a bundle whose minimum
expiry across all reported chains is later. Failed manual reloads do not
increment this metric.
Test scheduling across all reported X.509 chains, CA expiry, retries after
expiry, unchanged material, alias changes and omitted chains, metric
aggregation and reset, reload races and shutdown. Verify that a node with
default renewal settings plans no attempt and starts no renewal thread. Explain
delivery prerequisites, enabling renewal, inspecting failures and recovering
with reload.
h3. Dependencies and remaining work
Implementation, tests and documentation are prepared on {{ignite-29211}}. Open
its PR after IGNITE-29210 is merged and run CI on the updated branch. HTTP REST
integration in IGNITE-29212 is independent.
Add the [prepared integration
commit|https://github.com/anton-vinogradov/ignite/commit/a32c9b35f8147a62df23726874adb785353abc70]
to whichever of the IGNITE-29211 and IGNITE-29212 PRs merges second. It only
changes documentation and Javadoc, to say that HTTP REST certificates from
httpSslFactory also renew automatically. On that PR's branch, run
JettySslContextReloadTest for HTTP REST reload and SslRenewalNodeTest for
automatic renewal.
> Renew TLS certificates automatically before expiry
> --------------------------------------------------
>
> Key: IGNITE-29211
> URL: https://issues.apache.org/jira/browse/IGNITE-29211
> Project: Ignite
> Issue Type: Sub-task
> Reporter: Anton Vinogradov
> Assignee: Anton Vinogradov
> Priority: Major
> Labels: ise
>
> Automatically load certificates delivered by an external system before the
> current chain expires. That system issues and publishes replacements; Ignite
> loads them at scheduled attempts. Manual file replacement and
> trust-store-only changes still use {{--ssl reload}}: renewal does not watch
> files for changes.
> h3. How renewal works
> Add opt-in settings to AbstractSslContextFactory, disabled by default. Use
> the current {{SslBundle}} to schedule from the earliest expiry across all
> reported X.509 chains, including CA certificates. The renewal window is
> renewBeforeFraction of the interval from the selected chain's leaf validity
> start to its earliest expiry. When expiry dates tie, use the earliest leaf
> validity start to determine the window.
> Require at least one reported X.509 chain at startup and on every
> replacement. A null map means metadata is unknown; an empty map means no
> eligible chains were found. Reject both when renewal is enabled because
> neither supplies an expiry date. Entries without a nonempty X.509 chain are
> omitted by {{KeyMaterial}} and are not monitored.
> The factory owns the accepted bundle, replacement checks and reload outcome
> from IGNITE-29210. It also owns its renewal planner and unsuccessful-attempt
> count; the node supplies and stops the executor. Automatic attempts call
> {{renew(expectedContext)}} on the factory, using the same fresh-loading hook
> and replacement checks as manual {{init()}}.
> Install the whole bundle only when every reported chain is currently valid
> and the minimum expiry across all reported chains increases. Aliases may be
> renamed, added or removed; no match with the previous alias names is
> required. If an entry loses its chain, its alias disappears from metadata and
> renewal uses the remaining chains, just as when an alias is removed.
> If the minimum expiry does not advance, loading fails or validation rejects
> the replacement, retain the current bundle and retry with bounded backoff and
> jitter, including after expiry. Show the next attempt in {{--ssl status}} and
> log the cause.
> Serialize renewal and manual {{init()}} on the factory, replan after a
> successful replacement and prevent an obsolete automatic attempt from
> installing its result. Direct application calls to {{init()}} use the same
> replacement, replan and counter rules. Use the node's operation context so
> scheduled work is attributed to the node. Shutdown interrupts and finishes
> renewal work; cancellation must neither count as failure nor overwrite the
> last reload result.
> A factory with renewal enabled may attach to only one running node's renewal
> executor. Use a separate factory instance for each running node. After that
> executor stops, the same factory may attach to the restarted node with the
> renewal settings configured for that restart. Reusing the factory object
> retains its accepted material until {{init()}} loads a replacement;
> restarting the node does not itself reread stores through that already
> initialized object.
> h3. Monitoring and acceptance
> Publish one node metric, {{ssl.ConsecutiveRenewalFailures}}, so monitoring
> can detect unsuccessful delivery or loading. Sum consecutive unsuccessful
> automatic attempts across distinct factories and count a shared factory once.
> An unchanged minimum expiry counts as unsuccessful. Reset only the affected
> factory's count when renewal or manual reload installs a bundle whose minimum
> expiry across all reported chains is later. Failed manual reloads do not
> increment this metric.
> Test scheduling across all reported X.509 chains, CA expiry, retries after
> expiry, unchanged material, alias changes and omitted chains, metric
> aggregation and reset, reload races and shutdown. Cover direct {{init()}}
> calls, reuse after the old executor stops and rejection of attachment to two
> running renewal executors. Verify that a node with default renewal settings
> plans no attempt and starts no renewal thread. Explain delivery
> prerequisites, enabling renewal, inspecting failures and recovering with
> reload.
> h3. Dependencies and remaining work
> Implementation, tests and documentation are prepared on {{ignite-29211}}.
> Open its PR after IGNITE-29210 is merged and run CI on the updated branch.
> HTTP REST integration in IGNITE-29212 is independent.
> After both IGNITE-29211 and IGNITE-29212 are present, apply the single
> [prepared integration
> commit|https://github.com/anton-vinogradov/ignite/commit/e1a7c86c428cf775ef86750bfdca746d1cdeb88c]
> to the PR that merges second. It replaces the previous integration commits;
> do not apply the old patch list as well. It updates HTTP REST renewal
> documentation and Javadoc and adds an HTTPS test proving that automatic
> renewal presents the replacement certificate on a new connection. On that
> combined branch, run JettySslContextReloadTest and SslRenewalNodeTest.
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)