Move firewall to external service
This commit is contained in:
parent
6351f8a231
commit
b935a26961
@ -9,7 +9,7 @@ RUN echo force-unsafe-io > /etc/dpkg/dpkg.cfg.d/docker-apt-speedup \
|
|||||||
&& apt-get install -y -qq \
|
&& apt-get install -y -qq \
|
||||||
bash build-essential python3-dev cython3 libffi-dev libssl-dev \
|
bash build-essential python3-dev cython3 libffi-dev libssl-dev \
|
||||||
libkrb5-dev ldap-utils libsasl2-modules-gssapi-mit libsasl2-dev libldap2-dev \
|
libkrb5-dev ldap-utils libsasl2-modules-gssapi-mit libsasl2-dev libldap2-dev \
|
||||||
python python3-pip python3-cffi iptables ipset \
|
python python3-pip python3-cffi \
|
||||||
libncurses5-dev gawk wget unzip git rsync \
|
libncurses5-dev gawk wget unzip git rsync \
|
||||||
&& apt-get clean \
|
&& apt-get clean \
|
||||||
&& rm /etc/dpkg/dpkg.cfg.d/docker-apt-speedup
|
&& rm /etc/dpkg/dpkg.cfg.d/docker-apt-speedup
|
||||||
|
@ -411,6 +411,7 @@ def sign(profile, skip_notify=False, overwrite=False, signer=None, namespace=con
|
|||||||
d = {
|
d = {
|
||||||
"common_name": common_name,
|
"common_name": common_name,
|
||||||
"status": "signed",
|
"status": "signed",
|
||||||
|
"disabled": False,
|
||||||
"serial_number": "%x" % builder.serial_number,
|
"serial_number": "%x" % builder.serial_number,
|
||||||
"signed": builder.begin_date,
|
"signed": builder.begin_date,
|
||||||
"expires": builder.end_date,
|
"expires": builder.end_date,
|
||||||
|
@ -14,7 +14,6 @@ import logging
|
|||||||
import os
|
import os
|
||||||
import pymongo
|
import pymongo
|
||||||
import signal
|
import signal
|
||||||
import socket
|
|
||||||
import sys
|
import sys
|
||||||
import pytz
|
import pytz
|
||||||
from asn1crypto import pem, x509
|
from asn1crypto import pem, x509
|
||||||
@ -107,6 +106,36 @@ def pinecone_sign(common_name, overwrite, profile):
|
|||||||
authority.sign(common_name, overwrite=overwrite, profile=profile)
|
authority.sign(common_name, overwrite=overwrite, profile=profile)
|
||||||
|
|
||||||
|
|
||||||
|
@click.command("disable", help="Disable client node or gateway replica temporarily")
|
||||||
|
@click.argument("common_name")
|
||||||
|
def pinecone_disable(common_name):
|
||||||
|
from pinecrypt.server import db
|
||||||
|
result = db.certificates.update_one({
|
||||||
|
"common_name": common_name
|
||||||
|
}, {
|
||||||
|
"$set": {
|
||||||
|
"disabled": datetime.utcnow()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if result.matched_count != 1:
|
||||||
|
raise click.ClickException("Invalid common name")
|
||||||
|
|
||||||
|
|
||||||
|
@click.command("enable", help="Enable client node or gateway replica")
|
||||||
|
@click.argument("common_name")
|
||||||
|
def pinecone_enable(common_name):
|
||||||
|
from pinecrypt.server import db
|
||||||
|
result = db.certificates.update_one({
|
||||||
|
"common_name": common_name
|
||||||
|
}, {
|
||||||
|
"$set": {
|
||||||
|
"disabled": False
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if result.matched_count != 1:
|
||||||
|
raise click.ClickException("Invalid common name")
|
||||||
|
|
||||||
|
|
||||||
@click.command("revoke", help="Revoke certificate")
|
@click.command("revoke", help="Revoke certificate")
|
||||||
@click.option("--reason", "-r", default="key_compromise",
|
@click.option("--reason", "-r", default="key_compromise",
|
||||||
help="Revocation reason, one of: key_compromise affiliation_changed superseded cessation_of_operation privilege_withdrawn")
|
help="Revocation reason, one of: key_compromise affiliation_changed superseded cessation_of_operation privilege_withdrawn")
|
||||||
@ -185,110 +214,6 @@ def pinecone_serve_builder():
|
|||||||
|
|
||||||
@click.command("provision", help="Provision keys")
|
@click.command("provision", help="Provision keys")
|
||||||
def pinecone_provision():
|
def pinecone_provision():
|
||||||
default_policy = "REJECT" if const.DEBUG else "DROP"
|
|
||||||
|
|
||||||
click.echo("Setting up firewall rules")
|
|
||||||
if const.REPLICAS:
|
|
||||||
# TODO: atomic update with `ipset restore`
|
|
||||||
for replica in const.REPLICAS:
|
|
||||||
for fam, _, _, _, addrs in socket.getaddrinfo(replica, None):
|
|
||||||
if fam == 10:
|
|
||||||
os.system("ipset add ipset6-mongo-replicas %s" % addrs[0])
|
|
||||||
elif fam == 2:
|
|
||||||
os.system("ipset add ipset4-mongo-replicas %s" % addrs[0])
|
|
||||||
|
|
||||||
os.system("ipset create -exist -quiet ipset4-client-ingress hash:ip timeout 3600 counters")
|
|
||||||
os.system("ipset create -exist -quiet ipset6-client-ingress hash:ip family inet6 timeout 3600 counters")
|
|
||||||
|
|
||||||
os.system("ipset create -exist -quiet ipset4-client-egress hash:ip timeout 3600 counters")
|
|
||||||
os.system("ipset create -exist -quiet ipset6-client-egress hash:ip family inet6 timeout 3600 counters")
|
|
||||||
|
|
||||||
os.system("ipset create -exist -quiet ipset4-mongo-replicas hash:ip")
|
|
||||||
os.system("ipset create -exist -quiet ipset6-mongo-replicas hash:ip family inet6")
|
|
||||||
|
|
||||||
os.system("ipset create -exist -quiet ipset4-prometheus-subnets hash:net")
|
|
||||||
os.system("ipset create -exist -quiet ipset6-prometheus-subnets hash:net family inet6")
|
|
||||||
|
|
||||||
for subnet in const.PROMETHEUS_SUBNETS:
|
|
||||||
os.system("ipset add -exist -quiet ipset%d-prometheus-subnets %s" % (subnet.version, subnet))
|
|
||||||
|
|
||||||
def g():
|
|
||||||
yield "*filter"
|
|
||||||
yield ":INBOUND_BLOCKED - [0:0]"
|
|
||||||
yield "-A INBOUND_BLOCKED -j %s -m comment --comment \"Default policy\"" % default_policy
|
|
||||||
|
|
||||||
yield ":OUTBOUND_CLIENT - [0:0]"
|
|
||||||
yield "-A OUTBOUND_CLIENT -m set ! --match-set ipset4-client-ingress dst -j SET --add-set ipset4-client-ingress dst"
|
|
||||||
yield "-A OUTBOUND_CLIENT -j ACCEPT"
|
|
||||||
|
|
||||||
yield ":INBOUND_CLIENT - [0:0]"
|
|
||||||
yield "-A INBOUND_CLIENT -m set ! --match-set ipset4-client-ingress src -j SET --add-set ipset4-client-ingress src"
|
|
||||||
yield "-A INBOUND_CLIENT -j ACCEPT"
|
|
||||||
|
|
||||||
yield ":INPUT DROP [0:0]"
|
|
||||||
yield "-A INPUT -i lo -j ACCEPT -m comment --comment \"Allow loopback\""
|
|
||||||
yield "-A INPUT -p icmp -j ACCEPT -m comment --comment \"Allow ping\""
|
|
||||||
yield "-A INPUT -p esp -j ACCEPT -m comment --comment \"Allow ESP traffic\""
|
|
||||||
yield "-A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT -m comment --comment \"Allow returning packets\""
|
|
||||||
yield "-A INPUT -p tcp --dport 22 -j ACCEPT -m comment --comment \"Allow SSH\""
|
|
||||||
yield "-A INPUT -p udp --dport 53 -j ACCEPT -m comment --comment \"Allow GoreDNS over UDP\""
|
|
||||||
yield "-A INPUT -p tcp --dport 53 -j ACCEPT -m comment --comment \"Allow GoreDNS over TCP\""
|
|
||||||
yield "-A INPUT -p tcp --dport 80 -j ACCEPT -m comment --comment \"Allow insecure HTTP\""
|
|
||||||
yield "-A INPUT -p tcp --dport 443 -j ACCEPT -m comment --comment \"Allow HTTPS / OpenVPN TCP\""
|
|
||||||
yield "-A INPUT -p tcp --dport 8443 -j ACCEPT -m comment --comment \"Allow mutually authenticated HTTPS\""
|
|
||||||
yield "-A INPUT -p udp --dport 1194 -j ACCEPT -m comment --comment \"Allow OpenVPN UDP\""
|
|
||||||
yield "-A INPUT -p udp --dport 500 -j ACCEPT -m comment --comment \"Allow IPsec IKE\""
|
|
||||||
yield "-A INPUT -p udp --dport 4500 -j ACCEPT -m comment --comment \"Allow IPsec NAT traversal\""
|
|
||||||
if const.REPLICAS:
|
|
||||||
yield "-A INPUT -p tcp --dport 27017 -j ACCEPT -m set --match-set ipset4-mongo-replicas src -m comment --comment \"Allow MongoDB internode\""
|
|
||||||
yield "-A INPUT -p tcp --dport 9090 -j ACCEPT -m set --match-set ipset4-prometheus-subnets src -m comment --comment \"Allow Prometheus\""
|
|
||||||
yield "-A INPUT -j INBOUND_BLOCKED"
|
|
||||||
|
|
||||||
yield ":FORWARD DROP [0:0]"
|
|
||||||
yield "-A FORWARD -i tun0 -j INBOUND_CLIENT -m comment --comment \"Inbound traffic from OpenVPN UDP clients\""
|
|
||||||
yield "-A FORWARD -i tun1 -j INBOUND_CLIENT -m comment --comment \"Inbound traffic from OpenVPN TCP clients\""
|
|
||||||
yield "-A FORWARD -m policy --dir in --pol ipsec -j INBOUND_CLIENT -m comment --comment \"Inbound traffic from IPSec clients\""
|
|
||||||
yield "-A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j OUTBOUND_CLIENT -m comment --comment \"Outbound traffic to clients\""
|
|
||||||
yield "-A FORWARD -j %s -m comment --comment \"Default policy\"" % default_policy
|
|
||||||
|
|
||||||
yield ":OUTPUT DROP [0:0]"
|
|
||||||
yield "-A OUTPUT -j ACCEPT"
|
|
||||||
yield "COMMIT"
|
|
||||||
|
|
||||||
yield "*nat"
|
|
||||||
yield ":PREROUTING ACCEPT [0:0]"
|
|
||||||
yield ":INPUT ACCEPT [0:0]"
|
|
||||||
yield ":OUTPUT ACCEPT [0:0]"
|
|
||||||
yield ":POSTROUTING ACCEPT [0:0]"
|
|
||||||
if not const.DISABLE_MASQUERADE:
|
|
||||||
yield "-A POSTROUTING -j MASQUERADE"
|
|
||||||
yield "COMMIT"
|
|
||||||
|
|
||||||
with open("/tmp/rules4", "w") as fh:
|
|
||||||
for line in g():
|
|
||||||
fh.write(line)
|
|
||||||
fh.write("\n")
|
|
||||||
|
|
||||||
if not const.DISABLE_FIREWALL:
|
|
||||||
os.system("iptables-restore < /tmp/rules4")
|
|
||||||
os.system("sed -e 's/ipset4/ipset6/g' -e 's/p icmp/p ipv6-icmp/g' /tmp/rules4 > /tmp/rules6")
|
|
||||||
os.system("ip6tables-restore < /tmp/rules6")
|
|
||||||
os.system("sysctl -w net.ipv6.conf.all.forwarding=1")
|
|
||||||
os.system("sysctl -w net.ipv6.conf.default.forwarding=1")
|
|
||||||
os.system("sysctl -w net.ipv4.ip_forward=1")
|
|
||||||
|
|
||||||
if const.REPLICAS:
|
|
||||||
click.echo("Provisioning MongoDB replicaset")
|
|
||||||
# WTF https://github.com/docker-library/mongo/issues/339
|
|
||||||
c = pymongo.MongoClient("localhost", 27017)
|
|
||||||
config = {"_id": "rs0", "members": [
|
|
||||||
{"_id": index, "host": "%s:27017" % hostname} for index, hostname in enumerate(const.REPLICAS)]}
|
|
||||||
print("Provisioning MongoDB replicaset: %s" % repr(config))
|
|
||||||
try:
|
|
||||||
c.admin.command("replSetInitiate", config)
|
|
||||||
except pymongo.errors.OperationFailure:
|
|
||||||
print("Looks like it's already initialized")
|
|
||||||
pass
|
|
||||||
|
|
||||||
# Expand variables
|
# Expand variables
|
||||||
distinguished_name = cn_to_dn(const.AUTHORITY_COMMON_NAME)
|
distinguished_name = cn_to_dn(const.AUTHORITY_COMMON_NAME)
|
||||||
@ -432,9 +357,22 @@ def pinecone_provision():
|
|||||||
const.SELF_KEY_PATH
|
const.SELF_KEY_PATH
|
||||||
))
|
))
|
||||||
|
|
||||||
|
if const.REPLICAS:
|
||||||
|
click.echo("Provisioning MongoDB replicaset")
|
||||||
|
# WTF https://github.com/docker-library/mongo/issues/339
|
||||||
|
c = pymongo.MongoClient("localhost", 27017)
|
||||||
|
config = {"_id": "rs0", "members": [
|
||||||
|
{"_id": index, "host": "%s:27017" % hostname} for index, hostname in enumerate(const.REPLICAS)]}
|
||||||
|
print("Provisioning MongoDB replicaset: %s" % repr(config))
|
||||||
|
try:
|
||||||
|
c.admin.command("replSetInitiate", config)
|
||||||
|
except pymongo.errors.OperationFailure:
|
||||||
|
print("Looks like it's already initialized")
|
||||||
|
pass
|
||||||
|
|
||||||
# TODO: use this task to send notification emails maybe?
|
# TODO: use this task to send notification emails maybe?
|
||||||
click.echo("Finished starting up")
|
click.echo("Finished starting up")
|
||||||
sleep(86400)
|
sleep(999999999)
|
||||||
|
|
||||||
|
|
||||||
@click.command("backend", help="Serve main backend")
|
@click.command("backend", help="Serve main backend")
|
||||||
@ -572,6 +510,8 @@ entry_point.add_command(pinecone_test)
|
|||||||
entry_point.add_command(pinecone_log)
|
entry_point.add_command(pinecone_log)
|
||||||
entry_point.add_command(pinecone_provision)
|
entry_point.add_command(pinecone_provision)
|
||||||
entry_point.add_command(pinecone_session)
|
entry_point.add_command(pinecone_session)
|
||||||
|
entry_point.add_command(pinecone_disable)
|
||||||
|
entry_point.add_command(pinecone_enable)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
entry_point()
|
entry_point()
|
||||||
|
@ -30,9 +30,8 @@ IMAGE_BUILDER_PROFILES = []
|
|||||||
SERVICE_PROTOCOLS = ["ikev2", "openvpn"]
|
SERVICE_PROTOCOLS = ["ikev2", "openvpn"]
|
||||||
|
|
||||||
MONGO_URI = os.getenv("MONGO_URI")
|
MONGO_URI = os.getenv("MONGO_URI")
|
||||||
REPLICAS = os.getenv("REPLICAS")
|
REPLICAS = [j for j in os.getenv("REPLICAS", "").split(",") if j]
|
||||||
if REPLICAS:
|
if REPLICAS:
|
||||||
REPLICAS = REPLICAS.split(",")
|
|
||||||
if MONGO_URI:
|
if MONGO_URI:
|
||||||
raise ValueError("Simultanously specifying MONGO_URI and REPLICAS doesn't make sense")
|
raise ValueError("Simultanously specifying MONGO_URI and REPLICAS doesn't make sense")
|
||||||
MONGO_URI = "mongodb://%s/default?replicaSet=rs0" % (",".join(["%s:27017" % j for j in REPLICAS]))
|
MONGO_URI = "mongodb://%s/default?replicaSet=rs0" % (",".join(["%s:27017" % j for j in REPLICAS]))
|
||||||
@ -147,7 +146,6 @@ CRL_SUBNETS = getenv_subnets("AUTH_CRL_SUBNETS", "0.0.0.0/0 ::/0")
|
|||||||
OVERWRITE_SUBNETS = getenv_subnets("AUTH_OVERWRITE_SUBNETS", "")
|
OVERWRITE_SUBNETS = getenv_subnets("AUTH_OVERWRITE_SUBNETS", "")
|
||||||
MACHINE_ENROLLMENT_SUBNETS = getenv_subnets("AUTH_MACHINE_ENROLLMENT_SUBNETS", "0.0.0.0/0 ::/0")
|
MACHINE_ENROLLMENT_SUBNETS = getenv_subnets("AUTH_MACHINE_ENROLLMENT_SUBNETS", "0.0.0.0/0 ::/0")
|
||||||
KERBEROS_SUBNETS = getenv_subnets("AUTH_KERBEROS_SUBNETS", "")
|
KERBEROS_SUBNETS = getenv_subnets("AUTH_KERBEROS_SUBNETS", "")
|
||||||
PROMETHEUS_SUBNETS = getenv_subnets("PROMETHEUS_SUBNETS", "")
|
|
||||||
|
|
||||||
BOOTSTRAP_TEMPLATE = ""
|
BOOTSTRAP_TEMPLATE = ""
|
||||||
USER_ENROLLMENT_ALLOWED = True
|
USER_ENROLLMENT_ALLOWED = True
|
||||||
@ -176,6 +174,3 @@ SESSION_COOKIE = "sha512brownies"
|
|||||||
SESSION_AGE = 3600
|
SESSION_AGE = 3600
|
||||||
|
|
||||||
SECRET_STORAGE = getenv_in("SECRET_STORAGE", "fs", "db")
|
SECRET_STORAGE = getenv_in("SECRET_STORAGE", "fs", "db")
|
||||||
|
|
||||||
DISABLE_FIREWALL = os.getenv("DISABLE_FIREWALL")
|
|
||||||
DISABLE_MASQUERADE = os.getenv("DISABLE_MASQUERADE")
|
|
||||||
|
Loading…
Reference in New Issue
Block a user