E-Mail Relay
Muchos servicios requieren enviar notificaciones de tipo e-mail, para ello se requiere un servidor de SMTP e indicar los datos de conexión en cada servicio.
Cuando se tienen pocos servicios puede ser práctico configurarlos directamente, pero no cuando crecen, ya que un simple cambio en uno de los datos puede requerir demasiado tiempo. Para solucionar estos problemas se utiliza un servicio intermedio que recibe los mensajes y los reenvía al SMTP correcto.
Este servicio únicamente es un redirector, no es capaz de enviar e-mails por sí mismo, así que necesitamos un servidor de SMTP real. Este suele ofrecerlo la misma empresa donde contratamos nuestro dominio.
Despliegue
Más detalles en Artifact Hub.
Añadimos el repositorio.
helm repo add djjudas21 https://djjudas21.github.io/charts/
helm repo update
Este Helm crea configuraciones y secret para la contraseña, pero debemos pasarle todos estos datos al desplegarlo, así que es más seguro indicarlos en un fichero.
vi email-relay-values.yaml
Indicamos la configuración acorde a nuestro servidor de SMTP.
smtp:
host: "smtp.domain.cat"
username: "[email protected]"
password: "password"
mynetworks:
- 127.0.0.0/8
- 0.0.0.0/0
Desplegamos el servicio.
helm upgrade --install smtp-relay djjudas21/smtp-relay \
-f email-relay-values.yaml \
--namespace email-relay-mngmt --create-namespace
Es recomendable borrar el fichero de configuración para limitar el acceso a la contraseña.
Pruebas
Los servicios dentro del clúster podrán utilizar este servicio acorde al nombre de servicio y namespace. Para probarlo imitaremos lo mismo utilizando un contenedor temporal con busybox
.
kubectl run busybox -i --tty --image=busybox --restart=Never --rm -- sh
Dentro de él tendremos que conectar al servicio acorde a su nombre y el namespace, y de ahí rellenar los datos para enviar un e-mail. Hay que actualizar el siguiente ejemplo con datos reales.
# telnet smtp-relay.email-relay-mngmt 25
Connected to smtp-relay.email-relay-mngmt
220 smtp-relay ESMTP Postfix
# helo localhost
250 smtp-relay
# mail from: [email protected]
250 2.1.0 Ok
# rcpt to: [email protected]
250 2.1.5 Ok
# data
354 End data with <CR><LF>.<CR><LF>
# Subject: Test
# Hello World!
# .
250 2.0.0 Ok: queued as CC3ED2C1681
# quit
221 2.0.0 Bye
Connection closed by foreign host
Según el servidor de SMTP, el e-mail utilizado por el remitente puede ser cualquier nombre, incluso si no existe, o deberá ser el mismo que se utiliza para iniciar sesión. En cualquier caso, el dominio será el mismo del usuario.
Al terminar nos llegará el e-mail, en caso contrario habrá que revisar los logs del servicio.
Restricción de servicios
Cualquier servicio dentro del clúster podrá utilizar este servicio, lo que puede ser un peligro si un servicio malicioso lo encuentra. Para evitar problemas, bloquearemos todo el acceso y lo abriremos a los servicios escogidos.
Primero denegamos todo tipo de acceso.
vi email-relay-np-deny.yaml
Cualquier acceso desde cualquier red hacia el servicio quedará bloqueado.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
namespace: email-relay-mngmt
spec:
podSelector:
matchLabels:
app.kubernetes.io/instance: smtp-relay
policyTypes:
- Ingress
Aplicamos la restricción.
kubectl apply -f email-relay-np-deny.yaml
Para cada servicio que necesite acceder, se creará una nueva excepción.
vi email-relay-np-allow-hello-world.yaml
Este ejemplo permite que cualquier pod que tenga el label hello: world
y que esté desplegado en el namespace default
pueda acceder. Si no cumple las 2 condiciones al mismo tiempo, será denegado.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-hello-world
namespace: email-relay-mngmt
spec:
podSelector:
matchLabels:
app.kubernetes.io/instance: smtp-relay
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: default
podSelector:
matchLabels:
hello: world
ports:
- protocol: TCP
port: 25
Tras aplicarlo aquellos pods que coincidan podrán acceder.
kubectl apply -f email-relay-np-allow-hello-world.yaml
Si repetimos la prueba anterior con el busybox
, veremos que el telnet
no responde, esto es debido a que está desplegado en el namespace correcto, pero no tiene los labels esperados.
Si lo intentamos con uno que sí tenga el label veremos como accede al servicio.
kubectl run busybox -i --tty --image=busybox --restart=Never --rm -l hello=world -- sh