[ 
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. With renewal enabled, 
reject startup unless the store contains at least one private key and every 
private key 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. At startup, they 
may load the same factory twice, one at a time.

h3. Factory API

Expose public {{getRenewalTime()}} and {{void renew(BooleanSupplier 
cancelled)}} on {{SslContextFactory}}. The getter returns the renewal time in 
epoch milliseconds, or {{0}} when disabled or not initialized. After waiting 
for other loads, {{renew(...)}} checks cancellation and the renewal time inside 
the factory. It skips loading if cancelled, disabled, not initialized 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 automatic attempts and record no 
further failures. An automatic attempt waiting for another load exits without 
reading the source. One already allowed to start may finish and install a 
replacement that passes validation. Startup initialization already waiting for 
the factory may still load material after shutdown starts.
* 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 or cancelled. 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:
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]



> 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. With renewal 
> enabled, reject startup unless the store contains at least one private key 
> and every private key 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. At 
> startup, they may load the same factory twice, one at a time.
> h3. Factory API
> Expose public {{getRenewalTime()}} and {{void renew(BooleanSupplier 
> cancelled)}} on {{SslContextFactory}}. The getter returns the renewal time in 
> epoch milliseconds, or {{0}} when disabled or not initialized. After waiting 
> for other loads, {{renew(...)}} checks cancellation and the renewal time 
> inside the factory. It skips loading if cancelled, disabled, not initialized 
> 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 automatic attempts and record no 
> further failures. An automatic attempt waiting for another load exits without 
> reading the source. One already allowed to start may finish and install a 
> replacement that passes validation. Startup initialization already waiting 
> for the factory may still load material after shutdown starts.
> * 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 or cancelled. 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