committed by
GitHub
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 186 additions and 12 deletions
-
150ISSUE_DESCRIPTION.md
-
48acme.sh
@ -0,0 +1,150 @@ |
|||
# Fix: Honor `--days` flag for short-lived certificates |
|||
|
|||
## Issue Description |
|||
|
|||
The `--days` flag in acme.sh is currently ignored for short-lived certificates (typically 5-50 days validity), causing unexpected renewal behavior that differs from user expectations and normal certificate handling. |
|||
|
|||
### Problem Details |
|||
|
|||
**Current Behavior:** |
|||
- For **normal certificates** (90+ days): `--days 60` works as expected, scheduling renewal ~60 days after issuance |
|||
- For **short-lived certificates** (5-50 days): `--days` value is completely ignored, renewal is automatically set to 1 day before expiration regardless of user preference |
|||
|
|||
**Root Cause:** |
|||
The renewal calculation logic has two separate code paths: |
|||
1. **When `_notAfter` is NOT set** (normal certs): Uses `Le_RenewalDays` from `--days` flag |
|||
2. **When `_notAfter` IS set** (short-lived certs): Ignores `Le_RenewalDays` and uses hardcoded fallback logic |
|||
|
|||
This inconsistency exists in the certificate processing logic around lines 5388-5411, where short-lived certificates follow a different renewal calculation that doesn't consider the user's `--days` setting. |
|||
|
|||
### Impact |
|||
|
|||
This affects users working with: |
|||
- Short-lived certificates from CAs like Sectigo InCommon, DigiCert, etc. |
|||
- Testing environments with brief certificate lifespans |
|||
- High-security environments requiring frequent certificate rotation |
|||
- Upcoming industry standards (200 days by 2026, 100 days by 2027, 47 days by 2029) |
|||
|
|||
**Example Issue:** |
|||
```bash |
|||
./acme.sh --issue -d example.com --valid-to "+20d" --days 7 |
|||
# Expected: Renew 7 days after issuance |
|||
# Actual: Renews 1 day before expiration (19 days after issuance), ignoring --days 7 |
|||
``` |
|||
|
|||
## Solution |
|||
|
|||
### Changes Made |
|||
|
|||
**1. Enhanced Renewal Logic for Short-lived Certificates** |
|||
- Modified the `_notAfter` code path to respect user's `--days` setting first |
|||
- Added safety check to prevent renewal after certificate expiration |
|||
- Maintained fallback logic for cases where user's setting is invalid |
|||
|
|||
**2. Added Parameter Validation** |
|||
- Early validation for `--days` parameter (1-398 days range) |
|||
- Aligned maximum with current industry standard (398 days) |
|||
- Clear error messages for invalid values |
|||
|
|||
**3. Improved User Feedback** |
|||
- Added informational messages explaining which renewal logic is being used |
|||
- Warning messages when fallback logic is triggered |
|||
- Clear indication when user's setting conflicts with certificate validity |
|||
|
|||
### Technical Implementation |
|||
|
|||
**Core Logic Change** (lines ~5388-5427): |
|||
```bash |
|||
if [ "$_notAfter" ]; then |
|||
Le_CertExpireTime=$(_date2time "$_notAfter") |
|||
|
|||
# NEW: Calculate renewal time based on user's --days setting first |
|||
Le_UserRenewTime=$(_math "$Le_CertCreateTime" + "$Le_RenewalDays" \* 24 \* 60 \* 60) |
|||
|
|||
# NEW: Check if user's renewal time is after certificate expiration |
|||
if [ "$Le_UserRenewTime" -ge "$Le_CertExpireTime" ]; then |
|||
# Fallback to safe defaults with clear messaging |
|||
# (existing logic for 1 day/1 hour before expiration) |
|||
else |
|||
# NEW: Use user's setting when valid |
|||
Le_NextRenewTime="$Le_UserRenewTime" |
|||
_info "Using user-specified renewal time: $Le_RenewalDays days after issuance" |
|||
fi |
|||
fi |
|||
``` |
|||
|
|||
**Validation Enhancement** (lines ~5351-5364): |
|||
```bash |
|||
# NEW: Reasonable validation for --days parameter |
|||
if [ "$Le_RenewalDays" -gt "398" ]; then |
|||
_err "Invalid --days value: $Le_RenewalDays. Maximum supported is 398 days (current industry standard)." |
|||
return 1 |
|||
fi |
|||
if [ "$Le_RenewalDays" -eq "0" ]; then |
|||
_err "Invalid --days value: $Le_RenewalDays. Minimum supported is 1 day." |
|||
return 1 |
|||
fi |
|||
``` |
|||
|
|||
### Logic Flow |
|||
|
|||
1. **Early Validation**: Check `--days` parameter for reasonable range (1-398 days) |
|||
2. **User Preference**: Calculate renewal time based on user's `--days` setting |
|||
3. **Safety Check**: Verify user's setting doesn't cause renewal after expiration |
|||
4. **Fallback Logic**: Use safe defaults only when user's setting is invalid |
|||
5. **Clear Feedback**: Inform user which logic was applied and why |
|||
|
|||
### Behavior Examples |
|||
|
|||
**Valid User Settings (respected):** |
|||
```bash |
|||
--days 7 with 20-day cert → Renews 7 days after issuance ✓ |
|||
--days 15 with 30-day cert → Renews 15 days after issuance ✓ |
|||
--days 30 with 90-day cert → Renews 30 days after issuance ✓ |
|||
``` |
|||
|
|||
**Invalid User Settings (fallback with warning):** |
|||
```bash |
|||
--days 25 with 20-day cert → Warning + fallback to 1 day before expiration |
|||
--days 0 → Error: "Minimum supported is 1 day" |
|||
--days 500 → Error: "Maximum supported is 398 days" |
|||
``` |
|||
|
|||
### Backward Compatibility |
|||
|
|||
- **Existing behavior preserved** when no `--days` flag is used |
|||
- **Normal certificates** maintain existing renewal logic (with 1-day safety buffer) |
|||
- **Short-lived certificates without `--days`** continue using current fallback logic |
|||
- **No breaking changes** to configuration file format or cron behavior |
|||
|
|||
### Future-Proofing |
|||
|
|||
This fix prepares acme.sh for the industry's transition to shorter certificate lifespans: |
|||
- Current: 398 days maximum |
|||
- March 2026: 200 days maximum |
|||
- March 2027: 100 days maximum |
|||
- March 2029: 47 days maximum |
|||
|
|||
The validation and logic gracefully handle these transitions while respecting user intent. |
|||
|
|||
## Testing |
|||
|
|||
**Test Case 1: Short-lived certificate with valid --days** |
|||
```bash |
|||
./acme.sh --issue -d test.example.com --valid-to "+20d" --days 7 |
|||
Result: Le_RenewalDays='7', renewal scheduled exactly 7 days after issuance ✓ |
|||
``` |
|||
|
|||
**Test Case 2: Short-lived certificate with invalid --days** |
|||
```bash |
|||
./acme.sh --issue -d test.example.com --valid-to "+15d" --days 20 |
|||
Result: Warning message + fallback to 1 day before expiration ✓ |
|||
``` |
|||
|
|||
**Test Case 3: Normal certificate behavior unchanged** |
|||
```bash |
|||
./acme.sh --issue -d test.example.com --days 60 |
|||
Result: Renewal scheduled 59 days after issuance (existing behavior) ✓ |
|||
``` |
|||
|
|||
This fix ensures the `--days` flag works consistently across all certificate types while maintaining safety and providing clear user feedback. |
Write
Preview
Loading…
Cancel
Save
Reference in new issue