Bumped to use Alpine Linux 3.13.0
This commit is contained in:
parent
a4ddcd31ec
commit
51dfaf9a79
@ -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
4
Jenkinsfile
vendored
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
95
smtp2slack4qnap.py.old
Normal 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')
|
||||||
Loading…
Reference in New Issue
Block a user