changing certificate renewal

This commit is contained in:
Artur Kuś 2026-02-19 18:13:40 +01:00
parent 25c7ff7644
commit 969a19f584
1 changed files with 39 additions and 34 deletions

View File

@ -1,9 +1,3 @@
// Define common paths and variables
def baseCertPath = '/_docker_data_/letsencrypt/live'
def letsEncryptCommand = "docker compose --file lets-encrypt.yml --env-file lets.env"
def email = env.LETSENCRYPT_EMAIL ?: 'kusartur@gmail.com'
def workDir = "/_sd_/_programs_/proxy-nginx/deploy-this/lets-encrypt"
def domainsToCert = [ def domainsToCert = [
[ false, 'plecianki.pl'], [ false, 'plecianki.pl'],
[ false, 'kopama.com.pl'], [ false, 'kopama.com.pl'],
@ -15,10 +9,10 @@ def domainsToCert = [
[ false, "katb.pl"], [ false, "katb.pl"],
[ false, "kursy.kopama.pl"], [ false, "kursy.kopama.pl"],
[ false, "statistics.kopama.pl"] [ false, "statistics.kopama.pl"]
] ]
def createCert(domains) { def createCert(domains) {
def baseCertPath = env.CERTS_PATH ?: '/_docker_data_/letsencrypt/live' def baseCertPath = env.CERTS_PATH ?: '/_docker_data_/letsencrypt/live'
def workDir = env.WORK_DIR ?: "/_sd_/_programs_/proxy-nginx/deploy-this/lets-encrypt" def workDir = env.WORK_DIR ?: "/_sd_/_programs_/proxy-nginx/deploy-this/lets-encrypt"
def letsEncryptCommand = "docker compose --file lets-encrypt.yml --env-file lets.env" def letsEncryptCommand = "docker compose --file lets-encrypt.yml --env-file lets.env"
@ -27,6 +21,7 @@ def createCert(domains) {
def toCreateDomains = [] def toCreateDomains = []
for (domain in domains) { for (domain in domains) {
def force = domain[0] def force = domain[0]
def name = domain[1] def name = domain[1]
def fileName = "${baseCertPath}/${name}/cert.pem" def fileName = "${baseCertPath}/${name}/cert.pem"
@ -35,52 +30,61 @@ def createCert(domains) {
def daysLeft = null def daysLeft = null
if (fileExists(fileName)) { if (fileExists(fileName)) {
// ✅ poprawne pobieranie SAN
def certInfo = sh( def certInfo = sh(
script: """ script: """
openssl x509 -in ${fileName} -text -noout \ openssl x509 -in ${fileName} -noout -ext subjectAltName \
| grep 'DNS:' \ | sed -n 's/ *DNS://gp' \
| sed 's/.*DNS://;s/, /\\n/g' | tr ',' '\\n' \
| sed 's/^ *//'
""", """,
returnStdout: true returnStdout: true
).trim() ).trim()
if (certInfo) { if (certInfo) {
currentDomains = certInfo.split('\n').collect { it.trim() } currentDomains = certInfo.split('\\n').collect { it.trim() }
} }
def expiryUnix = sh( // ✅ poprawne liczenie dni
script: "openssl x509 -enddate -noout -in ${fileName} | cut -d= -f2 | xargs -I{} date -d {} +%s", try {
returnStdout: true def expiryUnix = sh(
).trim() script: "date -d \"\$(openssl x509 -enddate -noout -in ${fileName} | cut -d= -f2)\" +%s",
returnStdout: true
).trim().toLong()
if (expiryUnix?.isLong()) {
def nowUnix = sh(script: "date +%s", returnStdout: true).trim().toLong() def nowUnix = sh(script: "date +%s", returnStdout: true).trim().toLong()
daysLeft = (expiryUnix.toLong() - nowUnix) / (60 * 60 * 24) daysLeft = (expiryUnix - nowUnix) / (60 * 60 * 24)
} catch (e) {
echo "Cannot parse expiry for ${name}"
} }
} }
def subList = (domain.size() > 2) ? domain[2..-1] : [] def subList = (domain.size() > 2) ? domain[2..-1] : []
def expectedDomains = [name] + subList.collect { "${it}.${name}" } def expectedDomains = [name] + subList.collect { "${it}.${name}" }
def needsRenewal = force || def needsRenewal =
!fileExists(fileName) || force ||
currentDomains.size() != expectedDomains.size() || !fileExists(fileName) ||
!currentDomains.containsAll(expectedDomains) || currentDomains.size() != expectedDomains.size() ||
(daysLeft != null && daysLeft < 30) !currentDomains.containsAll(expectedDomains) ||
(daysLeft != null && daysLeft < 30)
if (needsRenewal) { if (needsRenewal) {
echo "Certificate for '${name}' needs renewal (force: ${force}, missing: ${expectedDomains - currentDomains}, expires in: ${daysLeft ?: 'unknown'} days)" echo "Renewing '${name}' (force=${force}, expires in=${daysLeft ?: 'unknown'} days)"
toCreateDomains.add(domain) toCreateDomains.add(domain)
} else { } else {
echo "Certificate for '${name}' is OK (expires in ${daysLeft} days)" echo "Certificate for '${name}' OK (expires in ${daysLeft} days)"
} }
} }
echo "Certificates to create/renew: ${toCreateDomains.collect { it[1] }}"
if (!toCreateDomains.isEmpty()) { if (!toCreateDomains.isEmpty()) {
dir(workDir) { dir(workDir) {
for (domain in toCreateDomains) { for (domain in toCreateDomains) {
def name = domain[1] def name = domain[1]
def subList = (domain.size() > 2) ? domain[2..-1] : [] def subList = (domain.size() > 2) ? domain[2..-1] : []
def subDomains = subList.collect { "-d ${it}.${name}" }.join(' ') def subDomains = subList.collect { "-d ${it}.${name}" }.join(' ')
@ -88,22 +92,23 @@ def createCert(domains) {
def cmd = """ def cmd = """
${letsEncryptCommand} run --rm certbot certonly \ ${letsEncryptCommand} run --rm certbot certonly \
--webroot -w /var/www/certbot \ --webroot -w /var/www/certbot \
--cert-name='${name}' \ --cert-name ${name} \
--non-interactive --agree-tos \ --non-interactive --agree-tos \
--preferred-challenges http \ --preferred-challenges http \
--expand \
--email ${email} \ --email ${email} \
--force-renewal \
-d ${name} ${subDomains} -d ${name} ${subDomains}
""".stripIndent() """.stripIndent()
sh(cmd) sh(cmd)
} }
} }
} else { } else {
echo "All certificates are up to date. Nothing to create/renew." echo "All certificates are up to date."
} }
} }
pipeline { pipeline {
agent any agent any
stages { stages {