Browse Source

Fix up StrongSwan support

master
Lauri Võsandi 1 year ago
parent
commit
f793ae07a1
  1. 6
      Dockerfile
  2. 12
      entrypoint-openvpn.sh
  3. 12
      entrypoint-strongswan.sh
  4. 5
      entrypoint.sh
  5. 67
      pinecrypt/client/cli.py
  6. 5
      pinecrypt/client/const.py

6
Dockerfile

@ -10,9 +10,11 @@ RUN echo "Dpkg::Use-Pty=0;" > /etc/apt/apt.conf.d/99quieter @@ -10,9 +10,11 @@ RUN echo "Dpkg::Use-Pty=0;" > /etc/apt/apt.conf.d/99quieter
RUN apt-get update -qq
RUN apt-get install -y -qq \
python3-pip \
openvpn
openvpn \
strongswan
COPY entrypoint.sh /entrypoint.sh
COPY entrypoint-openvpn.sh /entrypoint-openvpn.sh
COPY entrypoint-strongswan.sh /entrypoint-strongswan.sh
COPY pinecrypt/client/. /src/pinecrypt/client
COPY setup.py /src/
COPY README.md /src/

12
entrypoint-openvpn.sh

@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
#!/bin/sh
sleep 10
set -e
$@
AUTHORITY=$3
echo "Client config:"
cat /etc/certidude/client.conf
echo
echo "Generated VPN config:"
cat /etc/openvpn/$AUTHORITY.conf
echo
openvpn --config /etc/openvpn/$AUTHORITY.conf

12
entrypoint-strongswan.sh

@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
#!/bin/sh
sleep 10
set -e
$@
AUTHORITY=$3
echo "Client config:"
cat /etc/certidude/client.conf
echo
echo "Generated VPN config:"
cat /etc/ipsec.conf
echo
/usr/sbin/ipsec start --nofork

5
entrypoint.sh

@ -1,5 +0,0 @@ @@ -1,5 +0,0 @@
#!/bin/sh
$@
AUTHORITY=$3
cat /etc/openvpn/$AUTHORITY.conf
openvpn --config /etc/openvpn/$AUTHORITY.conf

67
pinecrypt/client/cli.py

@ -3,6 +3,7 @@ @@ -3,6 +3,7 @@
import click
import hashlib
import logging
import ipsecparse
import json
import os
import random
@ -13,7 +14,6 @@ import socket @@ -13,7 +14,6 @@ import socket
import subprocess
import sys
import requests
from ipsecparse import loads
from asn1crypto import pem, x509
from asn1crypto.csr import CertificationRequest
from certbuilder import CertificateBuilder, pem_armor_certificate
@ -51,7 +51,8 @@ class ConfigTreeParser(ConfigParser): @@ -51,7 +51,8 @@ class ConfigTreeParser(ConfigParser):
@click.command("provision", help="Add endpoint to Certidude client config")
@click.argument("authority")
def certidude_provision(authority):
@click.option("-m", "--method", help="Force connection method")
def certidude_provision(authority, method):
client_config = ConfigParser()
try:
os.makedirs(os.path.dirname(const.CLIENT_CONFIG_PATH))
@ -71,6 +72,8 @@ def certidude_provision(authority): @@ -71,6 +72,8 @@ def certidude_provision(authority):
client_config.set(authority, "key path", os.path.join(b, "host_key.pem"))
client_config.set(authority, "certificate path", os.path.join(b, "host_cert.pem"))
client_config.set(authority, "authority path", os.path.join(b, "ca_cert.pem"))
if method:
client_config.set(authority, "method", method)
with open(const.CLIENT_CONFIG_PATH + ".part", 'w') as fh:
client_config.write(fh)
os.rename(const.CLIENT_CONFIG_PATH + ".part", const.CLIENT_CONFIG_PATH)
@ -80,6 +83,7 @@ def certidude_provision(authority): @@ -80,6 +83,7 @@ def certidude_provision(authority):
@click.option("-k", "--kerberos", default=False, is_flag=True, help="Offer system keytab for auth")
@click.option("-f", "--fork", default=False, is_flag=True, help="Fork to background")
@click.option("-nw", "--no-wait", default=False, is_flag=True, help="Return immediately if server doesn't autosign")
def certidude_enroll(fork, no_wait, kerberos):
try:
os.makedirs(const.RUN_DIR)
@ -359,7 +363,11 @@ def certidude_enroll(fork, no_wait, kerberos): @@ -359,7 +363,11 @@ def certidude_enroll(fork, no_wait, kerberos):
##################################
endpoint = authority_name
method = "init/openvpn"
try:
method = clients.get(authority_name, "method")
except NoOptionError:
method = "init/openvpn"
click.echo("Configuring '%s'" % endpoint)
csummer = hashlib.sha1()
@ -375,6 +383,7 @@ def certidude_enroll(fork, no_wait, kerberos): @@ -375,6 +383,7 @@ def certidude_enroll(fork, no_wait, kerberos):
fh.write("client\n")
fh.write("nobind\n")
fh.write("remote %s 1194 udp\n" % endpoint)
fh.write("remote %s 443 tcp\n" % endpoint)
fh.write("tls-version-min 1.2\n")
fh.write("tls-cipher %s\n" % bootstrap["openvpn"]["tls_cipher"])
fh.write("cipher %s\n" % bootstrap["openvpn"]["cipher"])
@ -403,27 +412,37 @@ def certidude_enroll(fork, no_wait, kerberos): @@ -403,27 +412,37 @@ def certidude_enroll(fork, no_wait, kerberos):
# IPSec set up with initscripts
if method == "init/strongswan":
config = loads(open("%s/ipsec.conf" % const.STRONGSWAN_PREFIX).read())
for section_type, section_name in config:
# Identify correct ipsec.conf section by leftcert
if section_type != "conn":
continue
if config[section_type,section_name]["leftcert"] != certificate_path:
continue
if config[section_type,section_name].get("left", "") == "%defaultroute":
config[section_type,section_name]["auto"] = "start" # This is client
elif config[section_type,section_name].get("leftsourceip", ""):
config[section_type,section_name]["auto"] = "add" # This is server
else:
config[section_type,section_name]["auto"] = "route" # This is site-to-site tunnel
with open("%s/ipsec.conf.part" % const.STRONGSWAN_PREFIX, "w") as fh:
fh.write(config.dumps())
os.rename(
"%s/ipsec.conf.part" % const.STRONGSWAN_PREFIX,
"%s/ipsec.conf" % const.STRONGSWAN_PREFIX)
break
strongswan_config_path = os.path.join(const.STRONGSWAN_PREFIX, "ipsec.conf")
strongswan_secrets_path = os.path.join(const.STRONGSWAN_PREFIX, "ipsec.secrets")
with open(strongswan_config_path) as fh:
config = ipsecparse.loads(fh.read())
config["ca", endpoint] = {}
config["ca", endpoint]["cacert"] = authority_path
config["ca", endpoint]["auto"] = "add"
config["conn", endpoint] = {}
config["conn", endpoint]["auto"] = "start"
config["conn", endpoint]["right"] = endpoint
config["conn", endpoint]["keyingtries"] = "%forever"
config["conn", endpoint]["dpdaction"] = "restart"
config["conn", endpoint]["closeaction"] = "restart"
config["conn", endpoint]["ike"] = "%s!" % bootstrap["strongswan"]["ike"]
config["conn", endpoint]["esp"] = "%s!" % bootstrap["strongswan"]["esp"]
config["conn", endpoint]["left"] = "%defaultroute"
config["conn", endpoint]["leftcert"] = certificate_path
# leftca="$AUTHORITY_CERTIFICATE_DISTINGUISHED_NAME"
# rightca="$AUTHORITY_CERTIFICATE_DISTINGUISHED_NAME"
with open(strongswan_secrets_path + ".part", "w") as fh:
fh.write(": %s %s`n" % (
"ECDSA" if authority_public_key.algorithm == "ec" else "RSA",
key_path
))
with open(strongswan_config_path + ".part", "w") as fh:
fh.write(config.dumps())
os.rename(strongswan_secrets_path + ".part", strongswan_secrets_path)
os.rename(strongswan_config_path + ".part", strongswan_config_path)
# Tune AppArmor profile, TODO: retain contents
if os.path.exists("/etc/apparmor.d/local"):

5
pinecrypt/client/const.py

@ -20,3 +20,8 @@ try: @@ -20,3 +20,8 @@ try:
except ValueError: # If FQDN is not configured
HOSTNAME = FQDN
DOMAIN = None
if os.path.exists("/etc/strongswan/ipsec.conf"):
STRONGSWAN_PREFIX = "/etc/strongswan"
else:
STRONGSWAN_PREFIX = "/etc"

Loading…
Cancel
Save