Azure Application Gateway Üzerindeki Let’s Encrypt Sertifikalarını Yenilemek
Azure üzerindeki projelerimizde API yönetimi ve SSL sonlandırma için Azure Application Gateway servisini kullanıyoruz. SSL sertifikaları için ise aksi yönde iyi bir gerekçe olmadıkça Let’s Encrypt tercih ediyoruz. Let’s Encrypt sertifikaları 90 günlük geçerlilik süresine sahip olduğu ve Application Gateway üzerindeki sertifikaların yenilenmesini elle yaptığımız için bu iş düzenli bir “angarya” olarak önümüze çıkıp duruyordu.
Her “eeh, yeter” dediğimde yaptığım araştırmalar sonucunda hiç de hoşuma gitmeyen çözümler ile karşılaştım. Kimisi bir Azure Automation hesabı açıp, en son 2 yıl önce güncellenmiş bir Powershell betiğini kopyalayıp yapıştırmamı, kimisi bu işe özel bir sanal makine yaratıp, işlemi burada yapmamı ve bu süreci otomatikleştirmemi, kimisi de Azure Devops kullanmamı öneriyordu. Kendimize uygun bir çözüm bulmak için kolları sıvamaktan başka çare yoktu.
Manuel süreç
Çözüme geçmeden önce sorundan da bahsetmek gerekiyor. Azure üzerindeki servislerimizin tamamı App Service platformu üzerinde Docker konteynerleri olarak çalışıyor. Dolayısıyla sıradan sanal makineler gibi SSH yapabileceğimiz veya crontab tanımlayabileceğimiz bir ortama sahip değiliz. SSL sertifikalarımızın geçerlilik sürelerini takip edip yakın zamanda geçersiz hale gelecek sertifikalar için aşağıdaki adımları uygulaman gerekiyordu:
- Kendi bilgisayarımda certbot imajını kullanarak yeni bir konteyner yaratmak
- “certbot certonly –manual” ile yeni sertifika alma sürecini başlatmak
- Doğrulama kodunu kopyalayarak yeni bir dosya yaratmak
- Let’s Encrypt sunucuları tarafından isteğimin onaylanabilmesi için yarattığım dosyayı Azure Blob Storage üzerinde herkese açık bir konteynere koymak
- Sertifikayı alıp “openssl” ile “pfx” olarak kaydetmek
- Terraform projemizdeki eski “pfx” dosyasını yenisiyle değiştirmek
- Terraform değişikliklerini uygulamak
En hafif tabiriyle iğrenç ve hataya çok açık bir süreç izliyordum. Terraform değişiklik planında uygulanmamış bir değişikliği gözden kaçırmak son derece kolaydı ve ciddi sonuçlara yol açabilirdi (bir Azure Application Gateway değişikliği için Terraform’un çıkarttığı planı hiç gördünüz mü?). Aynı zamanda hiçbir şekilde belgelendirilmemiş bir süreçti, zira ne zaman bir belge yazmaya kalksam “eeh, yeter” deyip süreci otomatikleştirme araştırmaları yapmaya koyuluyordum.
Let’s Encrypt güncelleme çözümümüz
Her şey, certbot’un “–manual-auth-hook” özelliğini keşfetmemle kolaylaştı. Bu keşif ile birlikte sürecin tamamını Gitlab CI kullanarak otomatikleştirebildim. “–manual-auth-hook” seçeneğinin yaptığı şey çok basit: Let’s Encrypt’ten dönen doğrulama kodunu belirlediğimiz betiğe yönlendiriyor ve kendi doğrulama mekanizmamızı oluşturmamıza olanak tanıyor. Doğrulama için aşağıdaki gibi bir betik yazdım:
#!/bin/sh ACME_CHALLENGE_DIR=.well-known/acme-challenge ACME_CHALLENGE_PATH="$ACME_CHALLENGE_DIR"/"$CERTBOT_TOKEN" mkdir -p "$ACME_CHALLENGE_DIR" echo "$CERTBOT_VALIDATION" > "$ACME_CHALLENGE_PATH" az storage blob upload \ --connection-string "$ACME_CHALLENGE_BLOB_CONNECTION_STRING" \ --container-name "$ACME_CHALLENGE_BLOB_CONTAINER_NAME" \ --file "$ACME_CHALLENGE_PATH" \ --name "$ACME_CHALLENGE_PATH
Hali hazırda Let’s Encrypt doğrulama isteklerini karşılamak için Blob Storage adresine yönlendirme kurallarımız tanımlıydı. Yukarıdaki betikle de doğrulama sürecini otomatikleştirdikten sonra tek yapmam gereken adımları bir sıraya koymak oldu:
stages: - letsencrypt renew: stage: letsencrypt image: name: certbot/certbot:latest entrypoint: [""] script: - apk update - apk add gcc make python3-dev musl-dev openssl-dev - python -m venv venv - source venv/bin/activate - pip install --upgrade pip setuptools wheel - pip install azure-cli - az login -u $AZ_ACCOUNT_EMAIL -p $AZ_ACCOUNT_PASSWORD - az account set --subscription $AZ_SUBSCRIPTION_ID - certbot certonly --manual --preferred-challenges=http --manual-auth-hook letsencrypt/blob_acme_challenge.sh -d $DOMAIN -m $CERTBOT_CONTACT_EMAIL --agree-tos --non-interactive --manual-public-ip-logging-ok - openssl pkcs12 -export -out $DOMAIN.pfx -inkey /etc/letsencrypt/live/$DOMAIN/privkey.pem -in /etc/letsencrypt/live/$DOMAIN/cert.pem -certfile /etc/letsencrypt/live/$DOMAIN/chain.pem -password env:PFX_PASSWORD - az network application-gateway ssl-cert update --resource-group $AZ_RESOURCE_GROUP_NAME --gateway-name $AZ_APP_GATEWAY_NAME --name $DOMAIN --cert-file $DOMAIN.pfx --cert-password $PFX_PASSWORD only: - web - api
Hepsi bu kadar! Artık kendi kendini belgeleyen ve herkesin rahatlıkla yapabileceği bir sürecimiz oldu.
Süreç, GitLab arayüzünden tetiklenebilir:
Tarayıcı değil de terminal insanıysanız gitlabci aracılığıyla yenilemeyi tetikleyebilirsiniz:
$ gitlabci pipeline create group/project master -e DOMAIN=api.example.com
Gelecekte periyodik tetikleme özelliğini de kullanabilir ve insan faktörünü tamamen devre dışı bırakabiliriz. Bunun için Application Gateway’de gereksiz değişiklikler yapılmasının önüne geçmek gerekiyor. Yine de şu anki haliyle dahi hoşuma giden ve bize uygun bir çözüm bulduğumuzu düşünüyorum.
Geribildirim: Merhaba GitLab, Biz Yeni Çözüm Ortağın: Artistanbul! - Artistanbul