diff --git a/changelog.md b/changelog.md index 7510c79..d15c152 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,12 @@ # Changelog +## 2026-03-27 - 11.12.4 - fix(acme) +use X509 certificate expiry when reporting ACME certificate validity + +- Parse the actual X509 validTo value from the PEM public certificate and fall back to SmartAcme's stored expiry if parsing fails +- Update reported certificate expiry data and event communication timestamps to use the verified validity date +- Bump @push.rocks/smartacme to ^9.3.1 and @push.rocks/smartproxy to ^27.1.0 + ## 2026-03-27 - 11.12.3 - fix(dcrouter) re-trigger auto certificate provisioning after SmartAcme becomes ready diff --git a/package.json b/package.json index 35cb032..b9e5678 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "@push.rocks/lik": "^6.4.0", "@push.rocks/projectinfo": "^5.1.0", "@push.rocks/qenv": "^6.1.3", - "@push.rocks/smartacme": "^9.3.0", + "@push.rocks/smartacme": "^9.3.1", "@push.rocks/smartdata": "^7.1.3", "@push.rocks/smartdb": "^2.0.0", "@push.rocks/smartdns": "^7.9.0", @@ -53,7 +53,7 @@ "@push.rocks/smartnetwork": "^4.5.2", "@push.rocks/smartpath": "^6.0.0", "@push.rocks/smartpromise": "^4.2.3", - "@push.rocks/smartproxy": "^27.0.0", + "@push.rocks/smartproxy": "^27.1.0", "@push.rocks/smartradius": "^1.1.1", "@push.rocks/smartrequest": "^5.0.1", "@push.rocks/smartrx": "^3.0.10", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8facc27..8170120 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -39,8 +39,8 @@ importers: specifier: ^6.1.3 version: 6.1.3 '@push.rocks/smartacme': - specifier: ^9.3.0 - version: 9.3.0(socks@2.8.7) + specifier: ^9.3.1 + version: 9.3.1(socks@2.8.7) '@push.rocks/smartdata': specifier: ^7.1.3 version: 7.1.3(socks@2.8.7) @@ -78,8 +78,8 @@ importers: specifier: ^4.2.3 version: 4.2.3 '@push.rocks/smartproxy': - specifier: ^27.0.0 - version: 27.0.0 + specifier: ^27.1.0 + version: 27.1.0 '@push.rocks/smartradius': specifier: ^1.1.1 version: 1.1.1 @@ -1048,6 +1048,10 @@ packages: resolution: {integrity: sha512-C2Xj8FZ0uHWeCXXqX5B4/gVFQmtSkiuOolzAgutjTfseNOHT3pUjljDZsTSxXFGgio54bCzVFqmEOUrIVk8RDA==} engines: {node: '>=20.0.0'} + '@peculiar/x509@2.0.0': + resolution: {integrity: sha512-r10lkuy6BNfRmyYdRAfgu6dq0HOmyIV2OLhXWE3gDEPBdX1b8miztJVyX/UxWhLwemNyDP3CLZHpDxDwSY0xaA==} + engines: {node: '>=20.0.0'} + '@pnpm/config.env-replace@1.1.0': resolution: {integrity: sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==} engines: {node: '>=12.22.0'} @@ -1092,8 +1096,8 @@ packages: '@push.rocks/qenv@6.1.3': resolution: {integrity: sha512-+z2hsAU/7CIgpYLFqvda8cn9rUBMHqLdQLjsFfRn5jPoD7dJ5rFlpkbhfM4Ws8mHMniwWaxGKo+q/YBhtzRBLg==} - '@push.rocks/smartacme@9.3.0': - resolution: {integrity: sha512-R6+fBNqlIy3fP2ECmOjBB65tl35w2+2vmSierO6oC9/5DW+khwjvFsT0+5WnfyjejEtWzdAprEseYWmBbyTGtA==} + '@push.rocks/smartacme@9.3.1': + resolution: {integrity: sha512-Cl1DVQ+rfpaYkk6VVm/KYVeUYzWfXzSfTXybHfCZ5SuiACuTVHZ6jK8TouELaV1RgrdYnIp0MrbiY2Kqi8ayAw==} '@push.rocks/smartarchive@4.2.4': resolution: {integrity: sha512-uiqVAXPxmr8G5rv3uZvZFMOCt8l7cZC3nzvsy4YQqKf/VkPhKIEX+b7LkAeNlxPSYUiBQUkNRoawg9+5BaMcHg==} @@ -1260,8 +1264,8 @@ packages: '@push.rocks/smartpromise@4.2.3': resolution: {integrity: sha512-Ycg/TJR+tMt+S3wSFurOpEoW6nXv12QBtKXgBcjMZ4RsdO28geN46U09osPn9N9WuwQy1PkmTV5J/V4F9U8qEw==} - '@push.rocks/smartproxy@27.0.0': - resolution: {integrity: sha512-1scXCoXUM0Ify81une5LldTfbKaBFN8aa5xTiFg2PAS6R4QoGsYuj/aCmErVwBDzCF4G+je4Lh0wxLkMKy7QBA==} + '@push.rocks/smartproxy@27.1.0': + resolution: {integrity: sha512-uMtmbT6/9Y+lOnSi4w6SRICWJr9q9bHsYAq6xMLmym3zvnEzEwJWF6sw4Jb/uEFEjI2/e4irNSQ9Ba74DhFRlg==} '@push.rocks/smartpuppeteer@2.0.5': resolution: {integrity: sha512-yK/qSeWVHIGWRp3c8S5tfdGP6WCKllZC4DR8d8CQlEjszOSBmHtlTdyyqOMBZ/BA4kd+eU5f3A1r4K2tGYty1g==} @@ -1339,9 +1343,6 @@ packages: '@push.rocks/taskbuffer@3.5.0': resolution: {integrity: sha512-Y9WwIEIyp6oVFdj06j84tfrZIvjhbMb3DF52rYxlTeYLk3W7RPhSg1bGPCbtkXWeKdBrSe37V90BkOG7Qq8Pqg==} - '@push.rocks/taskbuffer@6.1.2': - resolution: {integrity: sha512-sdqKd8N/GidztQ1k3r8A86rLvD8Afyir5FjYCNJXDD9837JLoqzHaOKGltUSBsCGh2gjsZn6GydsY6HhXQgvZQ==} - '@push.rocks/taskbuffer@8.0.2': resolution: {integrity: sha512-SRCAzrSHysW5XEjwZ494V60ybdpOo/s96jDD3sn7SkYolzg2Pboh+SW5Q7SVNcdkP4b9wCEizOYe9CB3vj3W6w==} @@ -5746,6 +5747,19 @@ snapshots: tslib: 2.8.1 tsyringe: 4.10.0 + '@peculiar/x509@2.0.0': + dependencies: + '@peculiar/asn1-cms': 2.6.1 + '@peculiar/asn1-csr': 2.6.1 + '@peculiar/asn1-ecc': 2.6.1 + '@peculiar/asn1-pkcs9': 2.6.1 + '@peculiar/asn1-rsa': 2.6.1 + '@peculiar/asn1-schema': 2.6.0 + '@peculiar/asn1-x509': 2.6.1 + pvtsutils: 1.3.6 + tslib: 2.8.1 + tsyringe: 4.10.0 + '@pnpm/config.env-replace@1.1.0': {} '@pnpm/network.ca-file@1.0.2': @@ -5853,10 +5867,10 @@ snapshots: '@push.rocks/smartlog': 3.2.1 '@push.rocks/smartpath': 6.0.0 - '@push.rocks/smartacme@9.3.0(socks@2.8.7)': + '@push.rocks/smartacme@9.3.1(socks@2.8.7)': dependencies: '@apiclient.xyz/cloudflare': 7.1.0 - '@peculiar/x509': 1.14.3 + '@peculiar/x509': 2.0.0 '@push.rocks/lik': 6.4.0 '@push.rocks/smartdata': 7.1.3(socks@2.8.7) '@push.rocks/smartdelay': 3.0.5 @@ -5866,17 +5880,21 @@ snapshots: '@push.rocks/smartstring': 4.1.0 '@push.rocks/smarttime': 4.2.3 '@push.rocks/smartunique': 3.0.9 - '@push.rocks/taskbuffer': 6.1.2 + '@push.rocks/taskbuffer': 8.0.2 '@tsclass/tsclass': 9.5.0 + reflect-metadata: 0.2.2 transitivePeerDependencies: - '@aws-sdk/credential-providers' - '@mongodb-js/zstd' - '@nuxt/kit' + - bare-abort-controller + - bare-buffer - encoding - gcp-metadata - kerberos - mongodb-client-encryption - react + - react-native-b4a - snappy - socks - supports-color @@ -6382,7 +6400,7 @@ snapshots: '@push.rocks/smartpromise@4.2.3': {} - '@push.rocks/smartproxy@27.0.0': + '@push.rocks/smartproxy@27.1.0': dependencies: '@push.rocks/smartcrypto': 2.0.4 '@push.rocks/smartlog': 3.2.1 @@ -6577,22 +6595,6 @@ snapshots: - supports-color - vue - '@push.rocks/taskbuffer@6.1.2': - dependencies: - '@design.estate/dees-element': 2.2.4 - '@push.rocks/lik': 6.4.0 - '@push.rocks/smartdelay': 3.0.5 - '@push.rocks/smartlog': 3.2.1 - '@push.rocks/smartpromise': 4.2.3 - '@push.rocks/smartrx': 3.0.10 - '@push.rocks/smarttime': 4.2.3 - '@push.rocks/smartunique': 3.0.9 - transitivePeerDependencies: - - '@nuxt/kit' - - react - - supports-color - - vue - '@push.rocks/taskbuffer@8.0.2': dependencies: '@design.estate/dees-element': 2.2.4 diff --git a/ts/00_commitinfo_data.ts b/ts/00_commitinfo_data.ts index 7a03b92..06431aa 100644 --- a/ts/00_commitinfo_data.ts +++ b/ts/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@serve.zone/dcrouter', - version: '11.12.3', + version: '11.12.4', description: 'A multifaceted routing service handling mail and SMS delivery functions.' } diff --git a/ts/classes.dcrouter.ts b/ts/classes.dcrouter.ts index c9bc160..adae43c 100644 --- a/ts/classes.dcrouter.ts +++ b/ts/classes.dcrouter.ts @@ -852,14 +852,22 @@ export class DcRouter { const cert = await this.smartAcme!.getCertificateForDomain(domain, { includeWildcard: !isWildcardDomain, }); - if (cert.validUntil) { - eventComms.setExpiryDate(new Date(cert.validUntil)); + // Parse real X509 expiry from PEM (defense-in-depth over SmartAcme's estimate) + let realValidUntil = cert.validUntil; + if (cert.publicKey) { + try { + const x509 = new plugins.crypto.X509Certificate(cert.publicKey); + realValidUntil = new Date(x509.validTo).getTime(); + } catch { /* fallback to SmartAcme's value */ } + } + if (realValidUntil) { + eventComms.setExpiryDate(new Date(realValidUntil)); } const result = { id: cert.id, domainName: cert.domainName, created: cert.created, - validUntil: cert.validUntil, + validUntil: realValidUntil, privateKey: cert.privateKey, publicKey: cert.publicKey, csr: cert.csr, diff --git a/ts_web/00_commitinfo_data.ts b/ts_web/00_commitinfo_data.ts index 7a03b92..06431aa 100644 --- a/ts_web/00_commitinfo_data.ts +++ b/ts_web/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@serve.zone/dcrouter', - version: '11.12.3', + version: '11.12.4', description: 'A multifaceted routing service handling mail and SMS delivery functions.' }