Jacob Bills
March 07, 2020
Hello and welcome to the first tutorial in my blog. For this tutorial I am setting up a 3 node mongodb replica set with TLS and enabling X509 client authentication.
I created 3 ec2 instances running a custom AMI I built for this demo. Heres a blog post that goes into more detail how that AMI was built. TLDR; its a fresh installation of CentOS-7-x86_64-Minimal-1908.iso with a preloaded ssh public key in roots authorized keys
#!/bin/bash
aws ec2 run-instances --image-id ami-00446be8a2dcad866 --count 1 --instance-type t2.micro --key-name id_rsa_vlog --security-group-ids sg-2f055c55 --subnet-id subnet-1ba30952 --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=mongo-rs0-00}]'
aws ec2 run-instances --image-id ami-00446be8a2dcad866 --count 1 --instance-type t2.micro --key-name id_rsa_vlog --security-group-ids sg-2f055c55 --subnet-id subnet-1ba30952 --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=mongo-rs0-01}]'
aws ec2 run-instances --image-id ami-00446be8a2dcad866 --count 1 --instance-type t2.micro --key-name id_rsa_vlog --security-group-ids sg-2f055c55 --subnet-id subnet-1ba30952 --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=mongo-rs0-02}]'
#!/bin/bash
yum install wget libcurl openssl telnet -y
firewall-cmd --permanent --add-port=27017/tcp
firewall-cmd --reload
wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-4.2.3.tgz
tar -xvf mongodb-linux-x86_64-rhel70-4.2.3.tgz
mv mongodb-linux-x86_64-rhel70-4.2.3 /opt
ln -sf /etc/alternatives/mongo /bin/mongo
ln -sf /etc/alternatives/mongod /bin/mongod
ln -sf /opt/mongodb-linux-x86_64-rhel70-4.2.3/bin/mongo /etc/alternatives/mongo
ln -sf /opt/mongodb-linux-x86_64-rhel70-4.2.3/bin/mongod /etc/alternatives/mongod
mkdir /data
#!/bin/bash
openssl req -passout pass:password -new -x509 -days 3650 -extensions v3_ca -keyout ca_private.pem -out ca.pem -subj "/CN=CA/OU=MONGO/O=BUSTEDWARE/L=PAINESVILLE/ST=OH/C=US"
OSX#!/bin/bash
openssl req -passout pass:password -new -x509 -days 3650 -extensions v3_ca -keyout ca_private.pem -out ca.pem -subj "/CN=CA/OU=MONGO/O=BUSTEDWARE/L=PAINESVILLE/ST=OH/C=US" -config /usr/local/etc/openssl@1.1/openssl.cnf
#!/bin/bash
openssl req -newkey rsa:4096 -nodes -out client.csr -keyout client.key -subj '/CN=JacobTBills/OU=MONGO_CLIENTS/O=BUSTEDWARE/L=PAINESVILLE/ST=OH/C=US'
Members of replica set
#!/bin/bash
openssl req -newkey rsa:4096 -nodes -out node1.csr -keyout node1.key -subj '/CN=ip-172-31-7-201.ec2.internal/OU=MONGO/O=BUSTEDWARE/L=PAINESVILLE/ST=OH/C=US'
openssl req -newkey rsa:4096 -nodes -out node2.csr -keyout node2.key -subj '/CN=ip-172-31-5-30.ec2.internal/OU=MONGO/O=BUSTEDWARE/L=PAINESVILLE/ST=OH/C=US'
openssl req -newkey rsa:4096 -nodes -out node3.csr -keyout node3.key -subj '/CN=ip-172-31-4-24.ec2.internal/OU=MONGO/O=BUSTEDWARE/L=PAINESVILLE/ST=OH/C=US'
#!/bin/bash
openssl x509 -passin pass:password -sha256 -req -days 365 -in client.csr -CA ca.pem -CAkey ca_private.pem -CAcreateserial -out client-signed.crt
Server#!/bin/bash
# sign node 1 csr
openssl x509 -passin pass:password -sha256 -req -days 365 -in node1.csr -CA ca.pem -CAkey ca_private.pem -CAcreateserial -out node1-signed.crt -extensions v3_req -extfile <(
cat << EOF
[ v3_req ]
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = 127.0.0.1
DNS.2 = localhost
DNS.3 = ip-172-31-7-201.ec2.internal
EOF
)
# sign node 2 csr
openssl x509 -passin pass:password -sha256 -req -days 365 -in node2.csr -CA ca.pem -CAkey ca_private.pem -CAcreateserial -out node2-signed.crt -extensions v3_req -extfile <(
cat << EOF
[ v3_req ]
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = 127.0.0.1
DNS.2 = localhost
DNS.3 = ip-172-31-5-30.ec2.internal
EOF
)
# sign node 3 csr
openssl x509 -passin pass:password -sha256 -req -days 365 -in node3.csr -CA ca.pem -CAkey ca_private.pem -CAcreateserial -out node3-signed.crt -extensions v3_req -extfile <(
cat << EOF
[ v3_req ]
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = 127.0.0.1
DNS.2 = localhost
DNS.3 = ip-172-31-4-24.ec2.internal
EOF
)
#!/bin/bash
cat client-signed.crt client.key > client.pem
cat node1-signed.crt node1.key > node1.pem
cat node2-signed.crt node2.key > node2.pem
cat node3-signed.crt node3.key > node3.pem
scp node1.pem ca.pem client.pem root@X.X.X.X:/root
scp node2.pem ca.pem root@Y.Y.Y.Y:/root
scp node3.pem ca.pem root@Z.Z.Z.Z:/root
Note that I also copied the CA certificate (ca.pem) to each server. This is a requirement for hostname verification when starting the mongod instance. I also copied the client.pem file to node1 so that I can connect and run administrative commands after creating the user in the x509 authentication database.
#!/bin/bash
mongod --bind_ip 127.0.0.1,172.31.7.201 --replSet rs0 --dbpath /data --logpath /data/mongod.log --port 27017 --fork --wiredTigerCacheSizeGB 1 --sslMode requireSSL --sslPEMKeyFile /root/node1.pem --sslCAFile /root/ca.pem --clusterAuthMode x509
Node2#!/bin/bash
mongod --bind_ip 127.0.0.1,172.31.5.30 --replSet rs0 --dbpath /data --logpath /data/mongod.log --port 27017 --fork --wiredTigerCacheSizeGB 1 --sslMode requireSSL --sslPEMKeyFile /root/node2.pem --sslCAFile /root/ca.pem --clusterAuthMode x509
Node3#!/bin/bash
mongod --bind_ip 127.0.0.1,172.31.4.24 --replSet rs0 --dbpath /data --logpath /data/mongod.log --port 27017 --fork --wiredTigerCacheSizeGB 1 --sslMode requireSSL --sslPEMKeyFile /root/node3.pem --sslCAFile /root/ca.pem --clusterAuthMode x509
Connect with the following command
#!/bin/bash
mongo localhost --ssl --sslPEMKeyFile client.pem --sslCAFile ca.pem
And run initiate to create the replica set
> rs.initiate(
{
_id: "rs0",
version: 1,
members: [
{ _id: 0, host : "ip-172-31-7-201.ec2.internal:27017" },
{ _id: 1, host : "ip-172-31-5-30.ec2.internal:27017" },
{ _id: 2, host : "ip-172-31-4-24.ec2.internal:27017" }
]
}
)
> db.getSiblingDB("$external").runCommand({createUser:"C=US,ST=OH,L=PAINESVILLE,O=BUSTEDWARE,OU=MONGO_CLIENTS,CN=JacobTBills",roles:[{role:"root",db:"admin"}]})
Connect using x509 authentication
#!/bin/bash
mongo ip-172-31-7-201.ec2.internal --ssl --sslPEMKeyFile client.pem --sslCAFile ca.pem --username "C=US,ST=OH,L=PAINESVILLE,O=BUSTEDWARE,OU=MONGO_CLIENTS,CN=JacobTBills" --authenticationMechanism "MONGODB-X509" --authenticationDatabase '$external'