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

Anton Vinogradov updated IGNITE-29211:
--------------------------------------
    Description: 
After IGNITE-29210, administrators can load replacement certificates with 
{{control.sh --ssl reload}}. They still have to run it before the certificates 
expire. Add optional renewal that loads replacements from the configured 
source. If no acceptable replacement is available, keep the working context and 
retry. Ignite does not issue certificates.

h3. When to load a replacement

# Add {{SslContextFactory.setRenewalEnabled(boolean)}} and 
{{isRenewalEnabled()}}. Renewal is off by default; changing the setting 
requires a restart. Each node schedules only enabled factories used by its 
started TCP transports.
# Read certificate chains from the key store used to build the accepted 
context, including stores returned by overridden loaders. A chain contains the 
key's certificate and its issuing certificates. Its usable lifetime ends at the 
earliest expiry in that chain, including CA certificates. Reject startup if 
renewal is enabled but no private-key entry has an X.509 chain.
# Select the key chain with the earliest expiry. Start renewal when it has 15% 
of its lifetime left, measured from the key certificate's validity start to 
that expiry. If several chains share the earliest expiry, use the longest 
lifetime. If the renewal time has passed, attempt immediately.

h3. Which replacements to accept

# An automatic replacement must contain a key chain. Before accepting it, check 
that every certificate in its key chains is within its validity dates and that 
the earliest expiry moves later. Unchanged earliest expiry counts as a failure 
even if other store contents changed.
# Loading or validation failure must preserve the current context and its 
renewal dates. Retry even after expiry: start with a one-minute base delay, 
double it up to one hour, and add a random delay of up to half the base delay.
# Manual and automatic loads of a factory run one at a time. With renewal 
enabled, manual loads also need a key chain, but do not require current 
certificate validity or a later expiry. This permits a manual trust-only 
reload. After any successful manual reload on the node, reread the renewal time 
and attempt immediately if it is due. Nodes sharing a factory keep separate 
schedules and may both query the source in one renewal window.

h3. Factory API

Expose public {{getRenewalTime()}} and {{void renew()}} on 
{{SslContextFactory}}. The getter returns the renewal time in epoch 
milliseconds, or {{0}} when disabled. {{renew()}} rechecks the time, skips 
loading if disabled or not yet due, and throws if loading or validation fails. 
After any normal return, including a skip, the node rereads the renewal time.

h3. Shutdown and operator feedback

* Once shutdown starts, start no further attempts and record no further 
failures. An attempt waiting for another load of the same factory exits without 
reading the source. An attempt already allowed to start may finish and install 
a replacement that passes validation.
* Log the next attempt and failures with the affected transports. Add 
{{ssl.ConsecutiveRenewalFailures}}: the sum of each factory's consecutive 
automatic failures on that node, or zero without renewal. Clear a factory's 
count after an accepted automatic replacement, any successful manual reload or 
a skipped attempt. Manual failures and shutdown cancellation do not increment 
it.
* Document configuration, retries, the metric, recovery and custom loaders 
using {{loadKeyStore()}} or {{openFileInputStream()}}. Custom loaders must 
limit load time: a stuck source call can delay manual reload and node shutdown.

h3. Done when

Tests confirm scheduling from the certificates actually loaded, including a 
custom loader, and rejection at startup without a chain. Verify the public API, 
including zero renewal time and no source load from {{renew()}} when renewal is 
disabled. Cover the disabled default, date calculations, invalid and unchanged 
replacements, retries after expiry, manual reload, shared factories, shutdown 
and counter resets. A new TLS connection must use the renewed material while an 
established connection stays usable.

Depends on IGNITE-29210. IGNITE-29212 adds HTTPS and its renewal test. A 
separate status command and certificate inventory are outside this ticket.

[Implementation plan in PR #13786|https://github.com/apache/ignite/pull/13786]


  was:
Load replacement TLS certificates before the current ones expire. An external 
source supplies the replacements. Ignite schedules the loads and uses accepted 
replacements for new connections.

h3. Configuration and timing

# Add {{SslContextFactory.setRenewalEnabled(boolean)}} and 
{{isRenewalEnabled()}}. Renewal is disabled by default. Changing the setting 
requires a restart.
# Each node schedules renewal for enabled factories used by its started TCP 
transports. Reject startup if an enabled factory's key store has no private-key 
entry with an X.509 chain.
# The renewal window opens when the first key chain to expire has 15% of its 
lifetime left. If that point has passed, start immediately. The lifetime begins 
when the leaf certificate becomes valid. It ends at the earliest expiry in the 
chain, including CA certificates. For chains with the same earliest expiry, use 
the longest lifetime.
# Add public {{SslContextFactory.getRenewalTime()}} and {{renew()}}. 
{{getRenewalTime()}} returns when the current renewal window opens, or {{0}} if 
renewal is disabled. {{renew()}} runs one attempt. It skips the load if renewal 
is disabled or the window has yet to open.

h3. Loading and retries

# An automatic replacement must contain a key chain. Every certificate in its 
key chains must be valid at the time of loading, and the earliest expiry must 
move later.
# If loading or validation fails, {{renew()}} throws and keeps the current 
context. Retry even after expiry. The base delay starts at one minute and 
doubles to a maximum of one hour. Add a random delay of up to half the base 
delay.
# Run manual and automatic loads of each factory one at a time. With renewal 
enabled, manual loads still require a key chain. They can keep the same expiry, 
for example when only trust changes.
# After a successful manual reload, update the schedule on that node. Run the 
next attempt immediately if it is due. Nodes sharing a factory have separate 
schedules and may both query the source in one renewal window.

h3. Shutdown and monitoring

# Once shutdown starts, admit no new attempts and count no more failures. An 
attempt waiting for another load of the same factory exits without loading. An 
attempt admitted earlier may finish and install a replacement that passes the 
checks.
# Log the next attempt and failures with the affected transports. Report 
{{ssl.ConsecutiveRenewalFailures}} as the sum of each factory's consecutive 
automatic failures on the node. Report zero on nodes without renewal.
# Count an automatic attempt with unchanged expiry as a failure. Clear the 
factory's count on that node after an accepted automatic replacement, any 
successful manual reload or a skipped attempt. Manual failures and shutdown 
cancellation do not add to the count.
# Document configuration, the metric, recovery, and overrides of 
{{loadKeyStore()}} or {{openFileInputStream()}}. An override must limit how 
long a load can take because a stuck load can delay node stop and manual reload.

h3. Acceptance

Verify the API, the disabled default, rejection at startup without a chain, 
scheduling and certificate dates from an overridden {{loadKeyStore()}}. Cover 
invalid and unchanged replacements, retries after expiry, manual reload, shared 
factories, shutdown and counters. Verify rotation on a new TLS connection while 
an established one stays usable.

Depends on [IGNITE-29210|https://issues.apache.org/jira/browse/IGNITE-29210]. 
[IGNITE-29212|https://issues.apache.org/jira/browse/IGNITE-29212] adds HTTPS 
renewal and its verification. A separate status command and certificate 
inventory are outside this ticket.

[Implementation plan in PR #13786|https://github.com/apache/ignite/pull/13786]



> 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
>          Time Spent: 1h 10m
>  Remaining Estimate: 0h
>
> After IGNITE-29210, administrators can load replacement certificates with 
> {{control.sh --ssl reload}}. They still have to run it before the 
> certificates expire. Add optional renewal that loads replacements from the 
> configured source. If no acceptable replacement is available, keep the 
> working context and retry. Ignite does not issue certificates.
> h3. When to load a replacement
> # Add {{SslContextFactory.setRenewalEnabled(boolean)}} and 
> {{isRenewalEnabled()}}. Renewal is off by default; changing the setting 
> requires a restart. Each node schedules only enabled factories used by its 
> started TCP transports.
> # Read certificate chains from the key store used to build the accepted 
> context, including stores returned by overridden loaders. A chain contains 
> the key's certificate and its issuing certificates. Its usable lifetime ends 
> at the earliest expiry in that chain, including CA certificates. Reject 
> startup if renewal is enabled but no private-key entry has an X.509 chain.
> # Select the key chain with the earliest expiry. Start renewal when it has 
> 15% of its lifetime left, measured from the key certificate's validity start 
> to that expiry. If several chains share the earliest expiry, use the longest 
> lifetime. If the renewal time has passed, attempt immediately.
> h3. Which replacements to accept
> # An automatic replacement must contain a key chain. Before accepting it, 
> check that every certificate in its key chains is within its validity dates 
> and that the earliest expiry moves later. Unchanged earliest expiry counts as 
> a failure even if other store contents changed.
> # Loading or validation failure must preserve the current context and its 
> renewal dates. Retry even after expiry: start with a one-minute base delay, 
> double it up to one hour, and add a random delay of up to half the base delay.
> # Manual and automatic loads of a factory run one at a time. With renewal 
> enabled, manual loads also need a key chain, but do not require current 
> certificate validity or a later expiry. This permits a manual trust-only 
> reload. After any successful manual reload on the node, reread the renewal 
> time and attempt immediately if it is due. Nodes sharing a factory keep 
> separate schedules and may both query the source in one renewal window.
> h3. Factory API
> Expose public {{getRenewalTime()}} and {{void renew()}} on 
> {{SslContextFactory}}. The getter returns the renewal time in epoch 
> milliseconds, or {{0}} when disabled. {{renew()}} rechecks the time, skips 
> loading if disabled or not yet due, and throws if loading or validation 
> fails. After any normal return, including a skip, the node rereads the 
> renewal time.
> h3. Shutdown and operator feedback
> * Once shutdown starts, start no further attempts and record no further 
> failures. An attempt waiting for another load of the same factory exits 
> without reading the source. An attempt already allowed to start may finish 
> and install a replacement that passes validation.
> * Log the next attempt and failures with the affected transports. Add 
> {{ssl.ConsecutiveRenewalFailures}}: the sum of each factory's consecutive 
> automatic failures on that node, or zero without renewal. Clear a factory's 
> count after an accepted automatic replacement, any successful manual reload 
> or a skipped attempt. Manual failures and shutdown cancellation do not 
> increment it.
> * Document configuration, retries, the metric, recovery and custom loaders 
> using {{loadKeyStore()}} or {{openFileInputStream()}}. Custom loaders must 
> limit load time: a stuck source call can delay manual reload and node 
> shutdown.
> h3. Done when
> Tests confirm scheduling from the certificates actually loaded, including a 
> custom loader, and rejection at startup without a chain. Verify the public 
> API, including zero renewal time and no source load from {{renew()}} when 
> renewal is disabled. Cover the disabled default, date calculations, invalid 
> and unchanged replacements, retries after expiry, manual reload, shared 
> factories, shutdown and counter resets. A new TLS connection must use the 
> renewed material while an established connection stays usable.
> Depends on IGNITE-29210. IGNITE-29212 adds HTTPS and its renewal test. A 
> separate status command and certificate inventory are outside this ticket.
> [Implementation plan in PR #13786|https://github.com/apache/ignite/pull/13786]



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

Reply via email to