Use AWS SNS with Lambda function to monitor SSL Certificate Expiry.
使用AWS SNS服務搭配Lambda來定時檢查SSL憑證到期狀態。
現在大多數的網站都會使用HTTPS來做加密,未來也會變成主流。
小一點的網站並不一定會使用付費的SSL憑證,轉而使用免費然後天數少一點的免費憑證來做加密,例如Let’s encrypt。天數短的憑證缺點就是,如果忘記Renew,瀏覽器就會顯示不安全,會影響用戶端瀏覽體驗,尤其如果是政府或金融單位萬萬不可讓這件事情發生。大部分的形況下都會搭配Auto renew定期排程方式進行自動更新。但是有時候偶爾會有出錯沒Auto renew,而管理員沒有發現到造成憑證過期的窘況。
這篇主要在介紹:利用AWS SNS通知服務來檢查並且在快到期時利用Telegram Bot來發送通知,如果您會設定想發送Email也是可以的。
這一篇是參考國外原文,有興趣可以參考一下!(原文另開分頁)
會使用到的服務包含:
AWS Lambda、AWS Cloud watch、AWS SNS
運作流程:
Cloud Watch run daily rule → AWS Lambda → 條件符合透過SNS發送TG訊息,不符合沒有動作。
Prerequisites:
- Telegram Bot已申請,取得接收訊息的Chat id和Bot本身的Token
- 已經設定好AWS SNS可以發送通知到Telegram
原文是介紹透過AWS SNS發送Email通知,你可以去這裡看看(另開分頁)
01. 登入AWS Lambda的服務然後點Create function
02.Author from scratch(預設不動)
名稱:自己決定
Runtime:Python 2.7
03. Permission下面點選Choose or create an execution role
點選Create a new role from AWS policy permissions
Role name:自己決定
Policy templates:Amazon SNS publish policy
按下Create function。
04. 建立之後到 Github的這裡去下載這一段Lambda程式碼。程式碼我貼在下方。
import socket
import ssl, boto3
import re,sys,os,datetime
def ssl_expiry_date(domainname):
ssl_date_fmt = r'%b %d %H:%M:%S %Y %Z'
context = ssl.create_default_context()
conn = context.wrap_socket(
socket.socket(socket.AF_INET),
server_hostname=domainname,
)
# 3 second timeout because Lambda has runtime limitations
conn.settimeout(3.0)
conn.connect((domainname, 443))
ssl_info = conn.getpeercert()
return datetime.datetime.strptime(ssl_info['notAfter'], ssl_date_fmt).date()
def ssl_valid_time_remaining(domainname):
"""Number of days left."""
expires = ssl_expiry_date(domainname)
return expires - datetime.datetime.utcnow().date()
def sns_Alert(dName, eDays, sslStatus):
sslStat = dName + ' SSL certificate will be expired in ' + eDays +' days!! '
snsSub = dName + ' SSL Certificate Expiry ' + sslStatus + ' alert'
print sslStat
print snsSub
response = client.publish(
TargetArn="arn:aws:sns:ap-southeast-1:41367:ssl-expiry-alerts",
Message= sslStat,
Subject= snsSub
)
#####Main Section
client = boto3.client('sns')
def lambda_handler(event, context):
f = ['www.google.com']
for dName in f:
print(dName)
expDate = ssl_valid_time_remaining(dName.strip())
(a, b) = str(expDate).split(',')
(c, d) = a.split(' ')
# Critical alerts
if int(c) < 15:
sns_Alert(dName, str(c), 'Critical')
# Frist critical alert on 20 th day
elif int(c) == 20:
sns_Alert(dName, str(c), 'Critical')
#third warning alert on 30th day
elif int(c) == 30:
sns_Alert(dName, str(c), 'Warning')
#second warning alert on 40th day
elif int(c) == 40:
sns_Alert(dName, str(c), 'Warning')
#First warning alert on 50th day
elif int(c) == 50:
sns_Alert(dName, str(c), 'Warning')
else:
print('Everything Fine..')
05. 修改程式碼裡面的ARN,改成你自己的SNS Topic裡面的目標ARN,看你想用TG或是EMail可以在這裡修改。如果想同時發多目標(TG+Email之類的),可能需要修改裡面的程式碼或是另外建一個Function也可以。我就不另外敘述了。
06. 修改檢查的網址,如果有多個網址可以用逗號隔開。
例如:’www.google.com,tw.yahoo.com’
下面的檢查部分,你可以去修改天數。或是增減判斷天數項目。
Save之後停留在這個畫面
07. 打開Cloud Watch到Event / Rules,按Create rule
08. Event Source:Fixed rate of 1 Days ,或著是你可以自己決定縮短檢測時間。不建議把時間拉長,因為根據上面的程式碼判斷,如果兩天以上一次,有可能你不會收到警告通知。
09. 右側Targets下拉選擇Lambda function,選擇你剛剛做好的Function,然後按下Configure detail
10. 取個名字然後Create rule
11. 然後我們回到AWS Lambda剛剛的畫面來做一下測試,下拉選Configure test events
12. 下拉這裡選Amazon CloudWatch,然後Save起來。
13. 回到剛剛頁面由於程式碼是判斷完全等於而不是大於小於,所以先確認你的SSL憑證剩下幾天然後把其中一個判斷式先改成天數跟他一樣。完成後Save,然後按Test。你會看到下面的執行結果。
14. 如果你有設定成功,同時Telegram也會收到傳過來的訊息。
完成後記得要把天數改回去。
這個監控主要是預防SSL憑證Auto renew失效時,至少你會知道要趕快修正或手動Renew。