Bumped to use Alpine Linux 3.13.0

This commit is contained in:
Jonathan Ervine 2021-01-21 11:40:47 +08:00
parent a4ddcd31ec
commit 51dfaf9a79
4 changed files with 104 additions and 6 deletions

View File

@ -1,5 +1,5 @@
# Base on latest (edge) alpine image # Base on latest (edge) alpine image
FROM harbor.ervine.dev/public/x86_64/alpine:v3.12 FROM harbor.ervine.dev/public/x86_64/alpine:v3.13
LABEL maintainer="Jonathan Ervine <docker@ervine.org>" LABEL maintainer="Jonathan Ervine <docker@ervine.org>"
# Install updates # Install updates

4
Jenkinsfile vendored
View File

@ -27,11 +27,11 @@ spec:
stage('Build with Kaniko') { stage('Build with Kaniko') {
git url: 'ssh://git@git.ervine.org/jonny/x86_64-alpine-qnap2slack.git', credentialsId: 'jenkins-to-git' git url: 'ssh://git@git.ervine.org/jonny/x86_64-alpine-qnap2slack.git', credentialsId: 'jenkins-to-git'
container('kaniko') { container('kaniko') {
sh '/kaniko/executor -f `pwd`/Dockerfile -c `pwd` --cache=true --destination=harbor.ervine.dev/public/x86_64/alpine/qnap2slack:v3.12.1 --destination=harbor.ervine.dev/public/x86_64/alpine/qnap2slack:v3.12' sh '/kaniko/executor -f `pwd`/Dockerfile -c `pwd` --cache=true --destination=harbor.ervine.dev/public/x86_64/alpine/qnap2slack:v3.13.0 --destination=harbor.ervine.dev/public/x86_64/alpine/qnap2slack:v3.13'
} }
} }
stage('Notify gchat') { stage('Notify gchat') {
hangoutsNotify message: "QNAP to Slack Notifier Application on Alpine Linux 3.12.1 has built",token: "A2ET831pVslqXTqAx6ycu573r",threadByJob: false hangoutsNotify message: "QNAP to Slack Notifier Application on Alpine Linux 3.13.0 has built",token: "A2ET831pVslqXTqAx6ycu573r",threadByJob: false
} }
} }
} }

View File

@ -39,10 +39,10 @@ WEBHOOK_URL = 'http://slack2chat.ipa.champion/AAAAcMVs3C4?key=AIzaSyDdI0hCZtE6vy
# implemented LOGIN authentication (non-RFC compliant, works with QNAP-NAS) # implemented LOGIN authentication (non-RFC compliant, works with QNAP-NAS)
# overkill for running locally, but mandatory for remote # overkill for running locally, but mandatory for remote
class MyServer(Server): class MyServer(Server):
print("[+] Connection made")
authenticated = False authenticated = False
@syntax('AUTH LOGIN') @syntax('AUTH LOGIN')
async def smtp_AUTH(self, arg): async def smtp_AUTH(self, arg):
print("[+] Connection made")
if arg != 'LOGIN': if arg != 'LOGIN':
await self.push('501 Syntax: AUTH LOGIN') await self.push('501 Syntax: AUTH LOGIN')
return return
@ -64,12 +64,15 @@ class MyServer(Server):
# again, overkill for running locally, but mandatory for remote # again, overkill for running locally, but mandatory for remote
class MyController(Controller): class MyController(Controller):
def factory(self): def factory(self):
print("[+} Starting TLS SMTP service") print("[+] Starting TLS SMTP service")
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
print("[+] Context created")
context.load_cert_chain('cert.pem', 'key.pem') context.load_cert_chain('cert.pem', 'key.pem')
print("[+] Certificate chain loaded")
return MyServer(self.handler, tls_context=context, require_starttls=True) return MyServer(self.handler, tls_context=context, require_starttls=True)
def email2text(data): def email2text(data):
print("[+] Converting email to text")
body = email.message_from_bytes(data).get_payload() body = email.message_from_bytes(data).get_payload()
h = html2text.HTML2Text() h = html2text.HTML2Text()
h.ignore_tables = True h.ignore_tables = True
@ -92,4 +95,4 @@ if __name__ == '__main__':
handler = CustomHandler() handler = CustomHandler()
controller = MyController(handler, hostname=LHOST, port=LPORT) controller = MyController(handler, hostname=LHOST, port=LPORT)
controller.start() controller.start()
input('SMTP server has started ...') input('SMTP server has started ...\n')

95
smtp2slack4qnap.py.old Normal file
View File

@ -0,0 +1,95 @@
#!/usr/bin/env python3
#
# Compact SMTP to HTTP Gateway
# -> targeting Slack for QNAP-NAS notifications
#
# generate self-signed cert (better than nothing):
# openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 3650 -nodes -subj '/CN=localhost'
import ssl
import asyncio
from aiosmtpd.controller import Controller
from aiosmtpd.smtp import SMTP as Server, syntax
from aiosmtpd.handlers import Debugging
from hashlib import sha256
from base64 import b64encode, b64decode
import requests
import email
import json
import html2text
import re
import os
### CONFIG DATA
# for SMTP AUTH LOGIN (SECRET = sha256(password) avoiding storing plaintext)
USER = 'qnap-messenger'
#SECRET = '8fb12c5b36b2287fd66a433bbcb5f5beaa2645cc9e2d1d9f6fd1177426cbc7cd'
SECRET = '72aa07df56098db02abe681d2ed5bfcc81484e228752935fc4caf07fbe78f858'
# SMTP listener (set to localhost if running on QNAP device)
LHOST, LPORT = '0.0.0.0', 1025
# target slack authenticated webhook url (keep confidential!)
WEBHOOK_URL = 'http://slack2chat.ipa.champion/AAAAcMVs3C4?key=AIzaSyDdI0hCZtE6vySjMm-WEfRq3CPzqKqqsHI&token=IAoPWEptPtdR1TOS6XtUhqOWZgPwAhabl_sqSvwjtjk%3D'
### END OF CONFIG DATA
# implemented LOGIN authentication (non-RFC compliant, works with QNAP-NAS)
# overkill for running locally, but mandatory for remote
class MyServer(Server):
authenticated = False
print("[+] Connection made")
@syntax('AUTH LOGIN')
async def smtp_AUTH(self, arg):
if arg != 'LOGIN':
await self.push('501 Syntax: AUTH LOGIN')
return
await self.push('334 VXNlcm5hbWU=') # b64('Username')
username = await self._reader.readline()
username = b64decode(username.rstrip(b'\r\n'))
await self.push('334 UGFzc3dvcmQ=') # b64('Password')
password = await self._reader.readline()
password = b64decode(password.rstrip(b'\r\n'))
if username.decode() == USER and sha256(password).hexdigest() == SECRET:
self.authenticated = True
print("[+] Authenticated")
await self.push('235 2.7.0 Authentication successful')
else:
print("[-] Authentication Failure")
await self.push('535 Invalid credentials')
# requires STARTTLS
# again, overkill for running locally, but mandatory for remote
class MyController(Controller):
def factory(self):
print("[+} Starting TLS SMTP service")
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
context.load_cert_chain('cert.pem', 'key.pem')
return MyServer(self.handler, tls_context=context, require_starttls=True)
def email2text(data):
body = email.message_from_bytes(data).get_payload()
h = html2text.HTML2Text()
h.ignore_tables = True
return re.sub(r'\n\s*\n', '\n\n', h.handle(body))
class CustomHandler:
async def handle_DATA(self, server, session, envelope):
if not server.authenticated:
return '500 Unauthenticated. Could not process your message'
mail_from = envelope.mail_from
data = envelope.content
text = email2text(data)
# tuned for slack, but can be anything else
requests.post(WEBHOOK_URL, data={'payload': json.dumps({'username': mail_from, 'text': text})})
print("[+] Alert sent: {}".format(text.encode()))
return '250 OK'
if __name__ == '__main__':
os.chdir(os.path.dirname(os.path.abspath(__file__)))
handler = CustomHandler()
controller = MyController(handler, hostname=LHOST, port=LPORT)
controller.start()
input('SMTP server has started ...\n')