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 \
|
||||
bash build-essential python3-dev cython3 libffi-dev libssl-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 \
|
||||
&& apt-get clean \
|
||||
&& 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 = {
|
||||
"common_name": common_name,
|
||||
"status": "signed",
|
||||
"disabled": False,
|
||||
"serial_number": "%x" % builder.serial_number,
|
||||
"signed": builder.begin_date,
|
||||
"expires": builder.end_date,
|
||||
|
@ -14,7 +14,6 @@ import logging
|
||||
import os
|
||||
import pymongo
|
||||
import signal
|
||||
import socket
|
||||
import sys
|
||||
import pytz
|
||||
from asn1crypto import pem, x509
|
||||
@ -107,6 +106,36 @@ def pinecone_sign(common_name, overwrite, 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.option("--reason", "-r", default="key_compromise",
|
||||
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")
|
||||
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
|
||||
distinguished_name = cn_to_dn(const.AUTHORITY_COMMON_NAME)
|
||||
@ -432,9 +357,22 @@ def pinecone_provision():
|
||||
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?
|
||||
click.echo("Finished starting up")
|
||||
sleep(86400)
|
||||
sleep(999999999)
|
||||
|
||||
|
||||
@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_provision)
|
||||
entry_point.add_command(pinecone_session)
|
||||
entry_point.add_command(pinecone_disable)
|
||||
entry_point.add_command(pinecone_enable)
|
||||
|
||||
if __name__ == "__main__":
|
||||
entry_point()
|
||||
|
@ -30,9 +30,8 @@ IMAGE_BUILDER_PROFILES = []
|
||||
SERVICE_PROTOCOLS = ["ikev2", "openvpn"]
|
||||
|
||||
MONGO_URI = os.getenv("MONGO_URI")
|
||||
REPLICAS = os.getenv("REPLICAS")
|
||||
REPLICAS = [j for j in os.getenv("REPLICAS", "").split(",") if j]
|
||||
if REPLICAS:
|
||||
REPLICAS = REPLICAS.split(",")
|
||||
if MONGO_URI:
|
||||
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]))
|
||||
@ -147,7 +146,6 @@ CRL_SUBNETS = getenv_subnets("AUTH_CRL_SUBNETS", "0.0.0.0/0 ::/0")
|
||||
OVERWRITE_SUBNETS = getenv_subnets("AUTH_OVERWRITE_SUBNETS", "")
|
||||
MACHINE_ENROLLMENT_SUBNETS = getenv_subnets("AUTH_MACHINE_ENROLLMENT_SUBNETS", "0.0.0.0/0 ::/0")
|
||||
KERBEROS_SUBNETS = getenv_subnets("AUTH_KERBEROS_SUBNETS", "")
|
||||
PROMETHEUS_SUBNETS = getenv_subnets("PROMETHEUS_SUBNETS", "")
|
||||
|
||||
BOOTSTRAP_TEMPLATE = ""
|
||||
USER_ENROLLMENT_ALLOWED = True
|
||||
@ -176,6 +174,3 @@ SESSION_COOKIE = "sha512brownies"
|
||||
SESSION_AGE = 3600
|
||||
|
||||
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