mirror of
https://github.com/coder/coder.git
synced 2025-07-30 22:19:53 +00:00
chore(coderd/notifications): expand golden file testing for notifications (#15032)
This PR aims to close https://github.com/coder/coder/issues/14913. It expands the golden files for the notifier to include the entire payload serialised as JSON.
This commit is contained in:
18
coderd/notifications/dispatch/smtptest/fixtures/ca.conf
Normal file
18
coderd/notifications/dispatch/smtptest/fixtures/ca.conf
Normal file
@@ -0,0 +1,18 @@
|
||||
[ req ]
|
||||
distinguished_name = req_distinguished_name
|
||||
x509_extensions = v3_ca
|
||||
prompt = no
|
||||
|
||||
[ req_distinguished_name ]
|
||||
C = ZA
|
||||
ST = WC
|
||||
L = Cape Town
|
||||
O = Coder
|
||||
OU = Team Coconut
|
||||
CN = Coder CA
|
||||
|
||||
[ v3_ca ]
|
||||
basicConstraints = critical,CA:TRUE
|
||||
keyUsage = critical,keyCertSign,cRLSign
|
||||
subjectKeyIdentifier = hash
|
||||
authorityKeyIdentifier = keyid:always,issuer:always
|
25
coderd/notifications/dispatch/smtptest/fixtures/ca.crt
Normal file
25
coderd/notifications/dispatch/smtptest/fixtures/ca.crt
Normal file
@@ -0,0 +1,25 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIESjCCAzKgAwIBAgIUceUne8C8ezg1leBzhm5M5QLjBc4wDQYJKoZIhvcNAQEL
|
||||
BQAwaDELMAkGA1UEBhMCWkExCzAJBgNVBAgMAldDMRIwEAYDVQQHDAlDYXBlIFRv
|
||||
d24xDjAMBgNVBAoMBUNvZGVyMRUwEwYDVQQLDAxUZWFtIENvY29udXQxETAPBgNV
|
||||
BAMMCENvZGVyIENBMB4XDTI0MDcxNTEzMzYwOFoXDTM0MDcxMzEzMzYwOFowaDEL
|
||||
MAkGA1UEBhMCWkExCzAJBgNVBAgMAldDMRIwEAYDVQQHDAlDYXBlIFRvd24xDjAM
|
||||
BgNVBAoMBUNvZGVyMRUwEwYDVQQLDAxUZWFtIENvY29udXQxETAPBgNVBAMMCENv
|
||||
ZGVyIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAijVhQfmImkQF
|
||||
kDiBqCdSAaG7dO7slAjJH0jYizYCwVzCKP72Z7DJ2b/ohcGBw1YWZ8dOm88uCpsS
|
||||
oWM5FvxIeaNeGpcFar+wEoR/o5p91DgwvpmkbNyu3uQaNRvIKoqGdTAu5GUNd+Ej
|
||||
MxvwfofgRetziA56sa6ovQV11hPbKxp0YbSJXMRN64sGCqx+VNqpk2A57JCdCjcB
|
||||
T1fc7LIqKc9uoqCaC0Hr2OaBCc8IxLwpwwOz5qCaOGmylXY3YE4lKNJkA1s/HXO/
|
||||
GAZ6aO0GqkO00fxIQwW13BexuaiDJfcAhUmJ8CjFt9qgKfnkP26jU8gfMxOkRkn2
|
||||
qG8sWy3z8wIDAQABo4HrMIHoMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD
|
||||
AgEGMB0GA1UdDgQWBBSk2BGdRQZDMvzOfLQkUmkwzjrOFzCBpQYDVR0jBIGdMIGa
|
||||
gBSk2BGdRQZDMvzOfLQkUmkwzjrOF6FspGowaDELMAkGA1UEBhMCWkExCzAJBgNV
|
||||
BAgMAldDMRIwEAYDVQQHDAlDYXBlIFRvd24xDjAMBgNVBAoMBUNvZGVyMRUwEwYD
|
||||
VQQLDAxUZWFtIENvY29udXQxETAPBgNVBAMMCENvZGVyIENBghRx5Sd7wLx7ODWV
|
||||
4HOGbkzlAuMFzjANBgkqhkiG9w0BAQsFAAOCAQEAFJtks88lruyIIbFpzQ8M932a
|
||||
hNmkm3ZFM8qrjFWCEINmzeeQHV+rviu4Spd4Cltx+lf6+51V68jE730IGEzAu14o
|
||||
U2dmhRxn+w17H6/Qmnxlbz4Da2HvVgL9C4IoEbCTTGEa+hDg3cH6Mah1rfC0zAXH
|
||||
zxe/M2ahM+SOMDxmoUUf6M4tDVqu98FpELfsFe4MqTUbzQ32PyoP4ZOBpma1dl8Y
|
||||
fMm0rJE9/g/9Tkj8WfA4AwedCWUA4e7MLZikmntcein310uSy1sEpA+HVji+Gt68
|
||||
2+TJgIGOX1EHj44SqK5hVExQNzqqi1IIhR05imFaJ426DX82LtOA1bIg7HNCWA==
|
||||
-----END CERTIFICATE-----
|
28
coderd/notifications/dispatch/smtptest/fixtures/ca.key
Normal file
28
coderd/notifications/dispatch/smtptest/fixtures/ca.key
Normal file
@@ -0,0 +1,28 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCKNWFB+YiaRAWQ
|
||||
OIGoJ1IBobt07uyUCMkfSNiLNgLBXMIo/vZnsMnZv+iFwYHDVhZnx06bzy4KmxKh
|
||||
YzkW/Eh5o14alwVqv7AShH+jmn3UODC+maRs3K7e5Bo1G8gqioZ1MC7kZQ134SMz
|
||||
G/B+h+BF63OIDnqxrqi9BXXWE9srGnRhtIlcxE3riwYKrH5U2qmTYDnskJ0KNwFP
|
||||
V9zssiopz26ioJoLQevY5oEJzwjEvCnDA7PmoJo4abKVdjdgTiUo0mQDWz8dc78Y
|
||||
Bnpo7QaqQ7TR/EhDBbXcF7G5qIMl9wCFSYnwKMW32qAp+eQ/bqNTyB8zE6RGSfao
|
||||
byxbLfPzAgMBAAECggEAMPlfYFiDDl8iNYvAbgyY45ki6vmq/X3rftl6WkImUcyD
|
||||
xLEsMWwU6sM1Kwh56fT8dYPLmCyfHQT8YhHd7gYxzGCWfQec1MneI4GuFRQumF/c
|
||||
7f1VpXnBwZvEqaMRl/mEUcxkIWypjBxMM9UnsD6Hu18GjmTLF2FTy78+lUBt/mSZ
|
||||
CptLNIQJ0vncdAlxg9PYxfXhrtWj8I2T7PCAmBM+wbcGzfWTKyo/JMKylnEe4NNg
|
||||
j4elBHhISSUACpZd2pU+iA2nTaaD1Rzlqang/FypIzwLye/Sz2a6spM9yL8H9UN5
|
||||
zdz+QIwNoSC4fhEAlDo7FMBr8ZdR97qadP78XH+3SQKBgQDC5mwvIEoLQSD7H9PT
|
||||
t+J59uq90Dcg7qRxM+jbrtmPmvSuAql2Mx7KO5kf45CO7mLA1oE7YG2ceXQb4hFO
|
||||
HCrIGYtK6iEyizvIOCmbwoPbYXBf2o6iSl1t7f4wQ4N35KjQptviW5CO3ThFI2H4
|
||||
Oco2zR1Bjtig/lPKPv4TlAA4ZwKBgQC1iTZzynr2UP6f2MIByNEzN86BAiHJBya0
|
||||
BCWrl93A66GRSjV/tNikSZ/Me/SU3h44WuiFVRMuDrYrCcrUgmXpVMSnAy6AiwXx
|
||||
ItMsQNJW3JryN7uki/swI0zLWj8B+FMf8nXa2FS545etjOj1w6scoKT4txmVT0C+
|
||||
61l4KNXglQKBgQCQRD3qOE12vTPrjyiePCwxOZuS+1ADWYJxpQoFqwyx5vKc562G
|
||||
p9pvuePjnfAATObedSldyUf5nlFa3mEO33yvd3EK9/mwzy1mTGRIPpiZyCuFWGNi
|
||||
MAeueo9ALIlhMune4NQ8XqjHh2rCiqlXM3fCTtwMDe++Y+Oj/jLWTSRImwKBgDTb
|
||||
UNmCGS9jAeB08ngmipMJKr1xa3jm9iPwGS/PNigX86EkJFOcyn97WGXnqZ0210G9
|
||||
Znp7/OuqKOx7G22o0heQMPoX+RBAamh9pVL7RMM51Hu2MpKEl4y6mn+TNUlTjpB8
|
||||
vkgMOQ8u71j+8E2uvUHGnII2feJ1gvqT+Cb+bNfJAoGAJNK6ufPA0lHJwuDlGlNu
|
||||
eKU0bP3tkz7nM20PS8R2djoNGN+D+pFFR71TB2gTN6YmqBcwP7TjPwNLKSg9xJvY
|
||||
ST1F2QnOyds/OgdFlabcNdmbNivT0rHX6qZs7vYXNVjt7rmIRY2TW3ifRLeCK0Ls
|
||||
5Anq4SkaoH/ctBnP3TYRnQI=
|
||||
-----END PRIVATE KEY-----
|
1
coderd/notifications/dispatch/smtptest/fixtures/ca.srl
Normal file
1
coderd/notifications/dispatch/smtptest/fixtures/ca.srl
Normal file
@@ -0,0 +1 @@
|
||||
0330C6D190E3FE649DAFCDA2F4D765E2D29328DE
|
90
coderd/notifications/dispatch/smtptest/fixtures/generate.sh
Executable file
90
coderd/notifications/dispatch/smtptest/fixtures/generate.sh
Executable file
@@ -0,0 +1,90 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Set filenames
|
||||
CA_KEY="ca.key"
|
||||
CA_CERT="ca.crt"
|
||||
SERVER_KEY="server.key"
|
||||
SERVER_CSR="server.csr"
|
||||
SERVER_CERT="server.crt"
|
||||
CA_CONF="ca.conf"
|
||||
SERVER_CONF="server.conf"
|
||||
V3_EXT_CONF="v3_ext.conf"
|
||||
|
||||
# Generate the CA key
|
||||
openssl genpkey -algorithm RSA -out $CA_KEY -pkeyopt rsa_keygen_bits:2048
|
||||
|
||||
# Create the CA configuration file
|
||||
cat >$CA_CONF <<EOL
|
||||
[ req ]
|
||||
distinguished_name = req_distinguished_name
|
||||
x509_extensions = v3_ca
|
||||
prompt = no
|
||||
|
||||
[ req_distinguished_name ]
|
||||
C = ZA
|
||||
ST = WC
|
||||
L = Cape Town
|
||||
O = Coder
|
||||
OU = Team Coconut
|
||||
CN = Coder CA
|
||||
|
||||
[ v3_ca ]
|
||||
basicConstraints = critical,CA:TRUE
|
||||
keyUsage = critical,keyCertSign,cRLSign
|
||||
subjectKeyIdentifier = hash
|
||||
authorityKeyIdentifier = keyid:always,issuer:always
|
||||
EOL
|
||||
|
||||
# Generate the CA certificate
|
||||
openssl req -new -x509 -key $CA_KEY -out $CA_CERT -days 3650 -config $CA_CONF -extensions v3_ca
|
||||
|
||||
# Generate the server key
|
||||
openssl genpkey -algorithm RSA -out $SERVER_KEY -pkeyopt rsa_keygen_bits:2048
|
||||
|
||||
# Create the server configuration file
|
||||
cat >$SERVER_CONF <<EOL
|
||||
[ req ]
|
||||
distinguished_name = req_distinguished_name
|
||||
req_extensions = v3_req
|
||||
prompt = no
|
||||
|
||||
[ req_distinguished_name ]
|
||||
C = ZA
|
||||
ST = WC
|
||||
L = Cape Town
|
||||
O = Coder
|
||||
OU = Team Coconut
|
||||
CN = myserver.local
|
||||
|
||||
[ v3_req ]
|
||||
subjectAltName = @alt_names
|
||||
|
||||
[ alt_names ]
|
||||
DNS.1 = myserver.local
|
||||
DNS.2 = www.myserver.local
|
||||
IP.1 = 127.0.0.1
|
||||
EOL
|
||||
|
||||
# Generate the server CSR
|
||||
openssl req -new -key $SERVER_KEY -out $SERVER_CSR -config $SERVER_CONF
|
||||
|
||||
# Create the server extensions configuration file
|
||||
cat >$V3_EXT_CONF <<EOL
|
||||
authorityKeyIdentifier=keyid,issuer
|
||||
basicConstraints=CA:FALSE
|
||||
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
|
||||
subjectAltName = @alt_names
|
||||
|
||||
[ alt_names ]
|
||||
DNS.1 = myserver.local
|
||||
DNS.2 = www.myserver.local
|
||||
IP.1 = 127.0.0.1
|
||||
EOL
|
||||
|
||||
# Generate the server certificate signed by the CA with a validity of 825 days
|
||||
openssl x509 -req -in $SERVER_CSR -CA $CA_CERT -CAkey $CA_KEY -CAcreateserial -out $SERVER_CERT -days 825 -extfile $V3_EXT_CONF
|
||||
|
||||
# Verify the server certificate
|
||||
openssl x509 -in $SERVER_CERT -text -noout | grep -A 1 "Subject Alternative Name"
|
||||
|
||||
echo "CA and server certificates generated successfully."
|
@@ -0,0 +1 @@
|
||||
🤫
|
20
coderd/notifications/dispatch/smtptest/fixtures/server.conf
Normal file
20
coderd/notifications/dispatch/smtptest/fixtures/server.conf
Normal file
@@ -0,0 +1,20 @@
|
||||
[ req ]
|
||||
distinguished_name = req_distinguished_name
|
||||
req_extensions = v3_req
|
||||
prompt = no
|
||||
|
||||
[ req_distinguished_name ]
|
||||
C = ZA
|
||||
ST = WC
|
||||
L = Cape Town
|
||||
O = Coder
|
||||
OU = Team Coconut
|
||||
CN = myserver.local
|
||||
|
||||
[ v3_req ]
|
||||
subjectAltName = @alt_names
|
||||
|
||||
[ alt_names ]
|
||||
DNS.1 = myserver.local
|
||||
DNS.2 = www.myserver.local
|
||||
IP.1 = 127.0.0.1
|
24
coderd/notifications/dispatch/smtptest/fixtures/server.crt
Normal file
24
coderd/notifications/dispatch/smtptest/fixtures/server.crt
Normal file
@@ -0,0 +1,24 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIID9TCCAt2gAwIBAgIUAzDG0ZDj/mSdr82i9Ndl4tKTKN4wDQYJKoZIhvcNAQEL
|
||||
BQAwaDELMAkGA1UEBhMCWkExCzAJBgNVBAgMAldDMRIwEAYDVQQHDAlDYXBlIFRv
|
||||
d24xDjAMBgNVBAoMBUNvZGVyMRUwEwYDVQQLDAxUZWFtIENvY29udXQxETAPBgNV
|
||||
BAMMCENvZGVyIENBMB4XDTI0MDcxNTEzMzYwOFoXDTI2MTAxODEzMzYwOFowbjEL
|
||||
MAkGA1UEBhMCWkExCzAJBgNVBAgMAldDMRIwEAYDVQQHDAlDYXBlIFRvd24xDjAM
|
||||
BgNVBAoMBUNvZGVyMRUwEwYDVQQLDAxUZWFtIENvY29udXQxFzAVBgNVBAMMDm15
|
||||
c2VydmVyLmxvY2FsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArvkV
|
||||
9OEO/g3KmKrOzuvF1HQJiF/oR4wvbkLWrpuc4o0+++uJqEwHx/PkkHJLZiYvOuLG
|
||||
1ostI6G8it8pK8FjSLrdBZCMxi3yOAhXJaErTyOm4ACvf27o3HyWEcngUbpGyptZ
|
||||
ey7mcGFmqRsz4a9rzSjtuZQPuugCZfHpdo/w6WAE+W+/8KpUjvv/bsmKbsli1AsY
|
||||
edCcx5ZkYK3j7Dn/M95v/+hHvGdtcTXodWVqnEzblcUBw2zgZFo7B6jJNt6kgzJz
|
||||
ofv4r7st/F0LVOGc+VWkwnhL1yjcdXEsnGvhP4n5qzupVMEDGKThuOkBuYZ7Ug99
|
||||
8tcnuN1usJgvCDk1awIDAQABo4GQMIGNMB8GA1UdIwQYMBaAFKTYEZ1FBkMy/M58
|
||||
tCRSaTDOOs4XMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgTwMDMGA1UdEQQsMCqCDm15
|
||||
c2VydmVyLmxvY2FsghJ3d3cubXlzZXJ2ZXIubG9jYWyHBH8AAAEwHQYDVR0OBBYE
|
||||
FFGiAovKgGehDTXyxtI66xpHuyrSMA0GCSqGSIb3DQEBCwUAA4IBAQAVifeEzc3g
|
||||
wTaogC3GVYn4ty/oA5kMHEXNN39QSElZ0qKordPmjZx/5k5SkneCgN3LYzcJm1l6
|
||||
/t5khedYmtbuUmT91BC8R4+d4aGFGvvR8/4XHKAOyei9w50JIrSf0HkY91cEXzhU
|
||||
N1p/491TvLt/uNgHeSNBRQXXkBZj5ZCPgs6D1vLZUxI4XnVwE01I+Ivhiuo5UMC8
|
||||
AjFzomUVnqH23nTgRlaFQZJOYfWV80VV8oXfHzXKiqfGwizFzKaF01XBVdmzjz2x
|
||||
iL6OoOM/EiBgsmDeb3HP4HYuFDvgWqCNbmP6z7M+rs2XjJLM8Uaywvxdkm/ib3+y
|
||||
rSJnQig8Prw9
|
||||
-----END CERTIFICATE-----
|
18
coderd/notifications/dispatch/smtptest/fixtures/server.csr
Normal file
18
coderd/notifications/dispatch/smtptest/fixtures/server.csr
Normal file
@@ -0,0 +1,18 @@
|
||||
-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIIC+TCCAeECAQAwbjELMAkGA1UEBhMCWkExCzAJBgNVBAgMAldDMRIwEAYDVQQH
|
||||
DAlDYXBlIFRvd24xDjAMBgNVBAoMBUNvZGVyMRUwEwYDVQQLDAxUZWFtIENvY29u
|
||||
dXQxFzAVBgNVBAMMDm15c2VydmVyLmxvY2FsMIIBIjANBgkqhkiG9w0BAQEFAAOC
|
||||
AQ8AMIIBCgKCAQEArvkV9OEO/g3KmKrOzuvF1HQJiF/oR4wvbkLWrpuc4o0+++uJ
|
||||
qEwHx/PkkHJLZiYvOuLG1ostI6G8it8pK8FjSLrdBZCMxi3yOAhXJaErTyOm4ACv
|
||||
f27o3HyWEcngUbpGyptZey7mcGFmqRsz4a9rzSjtuZQPuugCZfHpdo/w6WAE+W+/
|
||||
8KpUjvv/bsmKbsli1AsYedCcx5ZkYK3j7Dn/M95v/+hHvGdtcTXodWVqnEzblcUB
|
||||
w2zgZFo7B6jJNt6kgzJzofv4r7st/F0LVOGc+VWkwnhL1yjcdXEsnGvhP4n5qzup
|
||||
VMEDGKThuOkBuYZ7Ug998tcnuN1usJgvCDk1awIDAQABoEYwRAYJKoZIhvcNAQkO
|
||||
MTcwNTAzBgNVHREELDAqgg5teXNlcnZlci5sb2NhbIISd3d3Lm15c2VydmVyLmxv
|
||||
Y2FshwR/AAABMA0GCSqGSIb3DQEBCwUAA4IBAQCPWO5rV82kb4zI7OR4pjyU/AaD
|
||||
Wo2zIeyFIj+BpOe9jCYSdnPp4lagbV8Nal+rQPc7/pPTkjC+u1OZB2N3wYbICATn
|
||||
vw4lVLtrtIzts7lG+EI5tjqCU2nub5k3nDNGyrK/EuX3c9VJFTw9qmfB48gZWpAV
|
||||
mAkl4BO7HsSaGFXlykmoACERCHT8sVfJOO/rDxMJks+u++EyNQ1cQ9tR3hWaL4I2
|
||||
e1ZAmJ5Citlntwvq5BUDS96yYHZdM8rA0PQPeHi6CTJfgyEdX+yjtv/SZiXGYx1f
|
||||
KjGhgp6ln/DcDIhgp4oSmZID+3P3Kx8Yhv1U+2LbZoC8+4mkDhJw9Yns640O
|
||||
-----END CERTIFICATE REQUEST-----
|
28
coderd/notifications/dispatch/smtptest/fixtures/server.key
Normal file
28
coderd/notifications/dispatch/smtptest/fixtures/server.key
Normal file
@@ -0,0 +1,28 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCu+RX04Q7+DcqY
|
||||
qs7O68XUdAmIX+hHjC9uQtaum5zijT7764moTAfH8+SQcktmJi864sbWiy0jobyK
|
||||
3ykrwWNIut0FkIzGLfI4CFcloStPI6bgAK9/bujcfJYRyeBRukbKm1l7LuZwYWap
|
||||
GzPhr2vNKO25lA+66AJl8el2j/DpYAT5b7/wqlSO+/9uyYpuyWLUCxh50JzHlmRg
|
||||
rePsOf8z3m//6Ee8Z21xNeh1ZWqcTNuVxQHDbOBkWjsHqMk23qSDMnOh+/ivuy38
|
||||
XQtU4Zz5VaTCeEvXKNx1cSyca+E/ifmrO6lUwQMYpOG46QG5hntSD33y1ye43W6w
|
||||
mC8IOTVrAgMBAAECggEACUw2JPmSnOBpvBwTej5gGE6ENSl3g9nIqXDGzKd7OjSs
|
||||
PKHDAlzr6u2kXyKbrBVqXBQx4bOqleKhzLVYEDmqB3LajNGmEV/ep6iVzOuYDBAG
|
||||
bY/Lw5dGq3S5Wr+h+mXOHjUMF7Yhy6X5WRIXey4hqdi7bSmXfmSWwAkPUVwLvrLj
|
||||
gj1Tp8Ll5SxeD1G9eOX1GYVChh2SUsVbLeGrovwcfCZaobEvc2U30SNOW4Sep7P1
|
||||
e+CZlIO02Ts1EroW7G41YvAon3EziaZEb3Esusx1LH+cpbCyDtiA/aCfLVKKJ2Ev
|
||||
YAbZAyBOAcXtIa+RT0Ipph/6fsC1l1uyyUOETGVwpQKBgQDV9mpX+UBmU6vXz1b+
|
||||
cZ116dI1irK8qrF2G62rTtwGEhhaDC1AIISsqm0Huav763KQ2OsM1eJiPUC3/Q/9
|
||||
ouNXPA5pTT524XnZhr3KEkDRgXmw1xbzYcLMVYYsDrvKvVUNlQcYGwxTzxcielMB
|
||||
Jx2F3P90uegMKwUGM5XAChhVpwKBgQDRWaDja7QN6NCrq6o1pAueJnAEGK4IqloS
|
||||
v/6tFJ6XTqCAUXhFkoAyXFUi1QN7PMV5igNF0VQkU90G9e2wTeE4GJr5yKRxBP9+
|
||||
v9KgRkDKz1DJcep2Abm618vGTPIs72sUph9R5eraI161F4AiGv6PLuM4/LbF+6YK
|
||||
/GF6Wz+inQKBgAYaEexSWmjQqAzuh8+X0+LB+VG3k+NXhtoUbf59sD6oE3O19zBl
|
||||
/QKjlZprzCDSFSFWXlWuX9dnYcodeHBGTe918f9EyaxAP+ZZNl5l6N1QsPS/HZNx
|
||||
TUnggoQNI4PjpGJPxrUESHS3ajR8gpN81xWzOMHOb3SxYWJM5E9mukzvAoGBAIZ2
|
||||
2R35maateQoqsqLNgSDNc3lOGMo8EKqmYv/slIh+2hxRN70IAgtWvuAmjZvkRrpv
|
||||
6PY5I6BJtVe5Mjfhbd1IAJKbSvPE0A4rSy/ir88UJcGdx4iQRyk5Xgs6dPpjtRWI
|
||||
Nem2kYgW28fZFlXRnNt+tDdwKj00C0xXGo0qes8JAoGAD9mj697kYV8LIsIk5Eo+
|
||||
NdbcjungM8dk8WKMgDxYnkviY/3liBHuvq99YPna2iVAQ3pHpuInFjbOTYdf26JB
|
||||
5wbuIBFHVGNsKKwIDAZdK1VzPh/E/88sDp63F/nLu8Q4EAVHxTr8VTt/GWV+VJSK
|
||||
RQi4ETleSTjzYeKWjJxlf+4=
|
||||
-----END PRIVATE KEY-----
|
@@ -0,0 +1,9 @@
|
||||
authorityKeyIdentifier=keyid,issuer
|
||||
basicConstraints=CA:FALSE
|
||||
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
|
||||
subjectAltName = @alt_names
|
||||
|
||||
[ alt_names ]
|
||||
DNS.1 = myserver.local
|
||||
DNS.2 = www.myserver.local
|
||||
IP.1 = 127.0.0.1
|
221
coderd/notifications/dispatch/smtptest/server.go
Normal file
221
coderd/notifications/dispatch/smtptest/server.go
Normal file
@@ -0,0 +1,221 @@
|
||||
package smtptest
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
_ "embed"
|
||||
"io"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/emersion/go-sasl"
|
||||
"github.com/emersion/go-smtp"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
// TLS cert files.
|
||||
var (
|
||||
//go:embed fixtures/server.crt
|
||||
certFile []byte
|
||||
//go:embed fixtures/server.key
|
||||
keyFile []byte
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
AuthMechanisms []string
|
||||
AcceptedIdentity, AcceptedUsername, AcceptedPassword string
|
||||
FailOnDataFn func() error
|
||||
}
|
||||
|
||||
type Message struct {
|
||||
AuthMech string
|
||||
Identity, Username, Password string // Auth
|
||||
From string
|
||||
To []string // Address
|
||||
Subject, Contents string // Content
|
||||
}
|
||||
|
||||
type Backend struct {
|
||||
cfg Config
|
||||
|
||||
mu sync.Mutex
|
||||
lastMsg *Message
|
||||
}
|
||||
|
||||
func NewBackend(cfg Config) *Backend {
|
||||
return &Backend{
|
||||
cfg: cfg,
|
||||
}
|
||||
}
|
||||
|
||||
// NewSession is called after client greeting (EHLO, HELO).
|
||||
func (b *Backend) NewSession(c *smtp.Conn) (smtp.Session, error) {
|
||||
return &Session{conn: c, backend: b}, nil
|
||||
}
|
||||
|
||||
func (b *Backend) LastMessage() *Message {
|
||||
return b.lastMsg
|
||||
}
|
||||
|
||||
func (b *Backend) Reset() {
|
||||
b.lastMsg = nil
|
||||
}
|
||||
|
||||
type Session struct {
|
||||
conn *smtp.Conn
|
||||
backend *Backend
|
||||
}
|
||||
|
||||
// AuthMechanisms returns a slice of available auth mechanisms; only PLAIN is
|
||||
// supported in this example.
|
||||
func (s *Session) AuthMechanisms() []string {
|
||||
return s.backend.cfg.AuthMechanisms
|
||||
}
|
||||
|
||||
// Auth is the handler for supported authenticators.
|
||||
func (s *Session) Auth(mech string) (sasl.Server, error) {
|
||||
s.backend.mu.Lock()
|
||||
defer s.backend.mu.Unlock()
|
||||
|
||||
if s.backend.lastMsg == nil {
|
||||
s.backend.lastMsg = &Message{AuthMech: mech}
|
||||
}
|
||||
|
||||
switch mech {
|
||||
case sasl.Plain:
|
||||
return sasl.NewPlainServer(func(identity, username, password string) error {
|
||||
s.backend.lastMsg.Identity = identity
|
||||
s.backend.lastMsg.Username = username
|
||||
s.backend.lastMsg.Password = password
|
||||
|
||||
if s.backend.cfg.AcceptedIdentity != "" && identity != s.backend.cfg.AcceptedIdentity {
|
||||
return xerrors.Errorf("unknown identity: %q", identity)
|
||||
}
|
||||
if username != s.backend.cfg.AcceptedUsername {
|
||||
return xerrors.Errorf("unknown user: %q", username)
|
||||
}
|
||||
if password != s.backend.cfg.AcceptedPassword {
|
||||
return xerrors.Errorf("incorrect password for username: %q", username)
|
||||
}
|
||||
|
||||
return nil
|
||||
}), nil
|
||||
case sasl.Login:
|
||||
return sasl.NewLoginServer(func(username, password string) error {
|
||||
s.backend.lastMsg.Username = username
|
||||
s.backend.lastMsg.Password = password
|
||||
|
||||
if username != s.backend.cfg.AcceptedUsername {
|
||||
return xerrors.Errorf("unknown user: %q", username)
|
||||
}
|
||||
if password != s.backend.cfg.AcceptedPassword {
|
||||
return xerrors.Errorf("incorrect password for username: %q", username)
|
||||
}
|
||||
|
||||
return nil
|
||||
}), nil
|
||||
default:
|
||||
return nil, xerrors.Errorf("unexpected auth mechanism: %q", mech)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Session) Mail(from string, _ *smtp.MailOptions) error {
|
||||
s.backend.mu.Lock()
|
||||
defer s.backend.mu.Unlock()
|
||||
|
||||
if s.backend.lastMsg == nil {
|
||||
s.backend.lastMsg = &Message{}
|
||||
}
|
||||
|
||||
s.backend.lastMsg.From = from
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Session) Rcpt(to string, _ *smtp.RcptOptions) error {
|
||||
s.backend.mu.Lock()
|
||||
defer s.backend.mu.Unlock()
|
||||
|
||||
s.backend.lastMsg.To = append(s.backend.lastMsg.To, to)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Session) Data(r io.Reader) error {
|
||||
s.backend.mu.Lock()
|
||||
defer s.backend.mu.Unlock()
|
||||
|
||||
b, err := io.ReadAll(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if s.backend.cfg.FailOnDataFn != nil {
|
||||
return s.backend.cfg.FailOnDataFn()
|
||||
}
|
||||
|
||||
s.backend.lastMsg.Contents = string(b)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*Session) Reset() {}
|
||||
|
||||
func (*Session) Logout() error { return nil }
|
||||
|
||||
// nolint:revive // Yes, useTLS is a control flag.
|
||||
func CreateMockSMTPServer(be *Backend, useTLS bool) (*smtp.Server, net.Listener, error) {
|
||||
// nolint:gosec
|
||||
tlsCfg := &tls.Config{
|
||||
GetCertificate: readCert,
|
||||
}
|
||||
|
||||
l, err := net.Listen("tcp", "localhost:0")
|
||||
if err != nil {
|
||||
return nil, nil, xerrors.Errorf("connect: tls? %v: %w", useTLS, err)
|
||||
}
|
||||
|
||||
if useTLS {
|
||||
l = tls.NewListener(l, tlsCfg)
|
||||
}
|
||||
|
||||
addr, ok := l.Addr().(*net.TCPAddr)
|
||||
if !ok {
|
||||
return nil, nil, xerrors.Errorf("unexpected address type: %T", l.Addr())
|
||||
}
|
||||
|
||||
s := smtp.NewServer(be)
|
||||
|
||||
s.Addr = addr.String()
|
||||
s.WriteTimeout = 10 * time.Second
|
||||
s.ReadTimeout = 10 * time.Second
|
||||
s.MaxMessageBytes = 1024 * 1024
|
||||
s.MaxRecipients = 50
|
||||
s.AllowInsecureAuth = !useTLS
|
||||
s.TLSConfig = tlsCfg
|
||||
|
||||
return s, l, nil
|
||||
}
|
||||
|
||||
func readCert(_ *tls.ClientHelloInfo) (*tls.Certificate, error) {
|
||||
crt, err := tls.X509KeyPair(certFile, keyFile)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("load x509 cert: %w", err)
|
||||
}
|
||||
|
||||
return &crt, nil
|
||||
}
|
||||
|
||||
func PingClient(listen net.Listener, useTLS bool, startTLS bool) (*smtp.Client, error) {
|
||||
tlsCfg := &tls.Config{
|
||||
// nolint:gosec // It's a test.
|
||||
InsecureSkipVerify: true,
|
||||
}
|
||||
|
||||
switch {
|
||||
case useTLS:
|
||||
return smtp.DialTLS(listen.Addr().String(), tlsCfg)
|
||||
case startTLS:
|
||||
return smtp.DialStartTLS(listen.Addr().String(), tlsCfg)
|
||||
default:
|
||||
return smtp.Dial(listen.Addr().String())
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user