mirror of
https://github.com/laurivosandi/certidude
synced 2024-12-22 16:25:17 +00:00
Bugfixes, OU support and image builder fixes
This commit is contained in:
parent
388f58574b
commit
5cb7f89c1b
@ -44,6 +44,7 @@ class SessionResource(object):
|
|||||||
except IOError:
|
except IOError:
|
||||||
submission_hostname = None
|
submission_hostname = None
|
||||||
yield dict(
|
yield dict(
|
||||||
|
server = authority.server_flags(common_name),
|
||||||
submitted = submitted,
|
submitted = submitted,
|
||||||
common_name = common_name,
|
common_name = common_name,
|
||||||
address = submission_address,
|
address = submission_address,
|
||||||
@ -103,6 +104,7 @@ class SessionResource(object):
|
|||||||
|
|
||||||
yield dict(
|
yield dict(
|
||||||
serial = "%x" % cert.serial_number,
|
serial = "%x" % cert.serial_number,
|
||||||
|
organizational_unit = cert.subject.native.get("organizational_unit_name"),
|
||||||
common_name = common_name,
|
common_name = common_name,
|
||||||
# TODO: key type, key length, key exponent, key modulo
|
# TODO: key type, key length, key exponent, key modulo
|
||||||
signed = signed,
|
signed = signed,
|
||||||
@ -158,10 +160,8 @@ class SessionResource(object):
|
|||||||
request_subnets = config.REQUEST_SUBNETS or None,
|
request_subnets = config.REQUEST_SUBNETS or None,
|
||||||
admin_subnets=config.ADMIN_SUBNETS or None,
|
admin_subnets=config.ADMIN_SUBNETS or None,
|
||||||
signature = dict(
|
signature = dict(
|
||||||
server_certificate_lifetime=config.SERVER_CERTIFICATE_LIFETIME,
|
|
||||||
client_certificate_lifetime=config.CLIENT_CERTIFICATE_LIFETIME,
|
|
||||||
revocation_list_lifetime=config.REVOCATION_LIST_LIFETIME,
|
revocation_list_lifetime=config.REVOCATION_LIST_LIFETIME,
|
||||||
profiles = [dict(organizational_unit=ou, flags=f, lifetime=lt) for f, lt, ou in config.PROFILES.values()]
|
profiles = [dict(name=k, server=v[0]=="server", lifetime=v[1], organizational_unit=v[2], title=v[3]) for k,v in config.PROFILES.items()]
|
||||||
)
|
)
|
||||||
) if req.context.get("user").is_admin() else None,
|
) if req.context.get("user").is_admin() else None,
|
||||||
features=dict(
|
features=dict(
|
||||||
|
@ -21,6 +21,7 @@ class ImageBuilderResource(object):
|
|||||||
suffix = config.cp2.get(profile, "filename")
|
suffix = config.cp2.get(profile, "filename")
|
||||||
|
|
||||||
build = "/var/lib/certidude/builder/" + profile
|
build = "/var/lib/certidude/builder/" + profile
|
||||||
|
log_path = build + "/build.log"
|
||||||
if not os.path.exists(build + "/overlay/etc/uci-defaults"):
|
if not os.path.exists(build + "/overlay/etc/uci-defaults"):
|
||||||
os.makedirs(build + "/overlay/etc/uci-defaults")
|
os.makedirs(build + "/overlay/etc/uci-defaults")
|
||||||
os.system("rsync -av " + overlay_path + "/ " + build + "/overlay/")
|
os.system("rsync -av " + overlay_path + "/ " + build + "/overlay/")
|
||||||
@ -31,12 +32,16 @@ class ImageBuilderResource(object):
|
|||||||
fh.write(template.render(authority_name=const.FQDN))
|
fh.write(template.render(authority_name=const.FQDN))
|
||||||
|
|
||||||
proc = subprocess.Popen(("/bin/bash", build_script_path),
|
proc = subprocess.Popen(("/bin/bash", build_script_path),
|
||||||
stdout=open(build + "/build.log", "w"), stderr=subprocess.STDOUT,
|
stdout=open(log_path, "w"), stderr=subprocess.STDOUT,
|
||||||
close_fds=True, shell=False,
|
close_fds=True, shell=False,
|
||||||
cwd=build,
|
cwd=os.path.dirname(os.path.realpath(build_script_path)),
|
||||||
env={"PROFILE":model, "PATH":"/usr/sbin:/usr/bin:/sbin:/bin"},
|
env={"PROFILE":model, "PATH":"/usr/sbin:/usr/bin:/sbin:/bin",
|
||||||
|
"BUILD":build, "OVERLAY":build + "/overlay/"},
|
||||||
startupinfo=None, creationflags=0)
|
startupinfo=None, creationflags=0)
|
||||||
proc.communicate()
|
proc.communicate()
|
||||||
|
if proc.returncode:
|
||||||
|
logger.info("Build script finished with non-zero exitcode, see %s for more information" % log_path)
|
||||||
|
raise falcon.HTTPInternalServerError("Build script finished with non-zero exitcode")
|
||||||
|
|
||||||
for dname in os.listdir(build):
|
for dname in os.listdir(build):
|
||||||
if dname.startswith("lede-imagebuilder-"):
|
if dname.startswith("lede-imagebuilder-"):
|
||||||
|
@ -33,6 +33,11 @@ class LeaseResource(object):
|
|||||||
@authorize_server
|
@authorize_server
|
||||||
def on_post(self, req, resp):
|
def on_post(self, req, resp):
|
||||||
client_common_name = req.get_param("client", required=True)
|
client_common_name = req.get_param("client", required=True)
|
||||||
|
if "=" in client_common_name: # It's actually DN, resolve it to CN
|
||||||
|
_, client_common_name = client_common_name.split(" CN=", 1)
|
||||||
|
if "," in client_common_name:
|
||||||
|
client_common_name, _ = client_common_name.split(",", 1)
|
||||||
|
|
||||||
path, buf, cert, signed, expires = authority.get_signed(client_common_name) # TODO: catch exceptions
|
path, buf, cert, signed, expires = authority.get_signed(client_common_name) # TODO: catch exceptions
|
||||||
if req.get_param("serial") and cert.serial_number != req.get_param_as_int("serial"): # OCSP-ish solution for OpenVPN, not exposed for StrongSwan
|
if req.get_param("serial") and cert.serial_number != req.get_param_as_int("serial"): # OCSP-ish solution for OpenVPN, not exposed for StrongSwan
|
||||||
raise falcon.HTTPForbidden("Forbidden", "Invalid serial number supplied")
|
raise falcon.HTTPForbidden("Forbidden", "Invalid serial number supplied")
|
||||||
|
@ -225,7 +225,10 @@ class RequestDetailResource(object):
|
|||||||
Sign a certificate signing request
|
Sign a certificate signing request
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
cert, buf = authority.sign(cn, ou=req.get_param("ou"), overwrite=True, signer=req.context.get("user").name)
|
cert, buf = authority.sign(cn,
|
||||||
|
profile=req.get_param("profile", default="default"),
|
||||||
|
overwrite=True,
|
||||||
|
signer=req.context.get("user").name)
|
||||||
# Mailing and long poll publishing implemented in the function above
|
# Mailing and long poll publishing implemented in the function above
|
||||||
except EnvironmentError: # no such CSR
|
except EnvironmentError: # no such CSR
|
||||||
raise falcon.HTTPNotFound()
|
raise falcon.HTTPNotFound()
|
||||||
|
@ -38,6 +38,7 @@ class SignedCertificateDetailResource(object):
|
|||||||
common_name = cn,
|
common_name = cn,
|
||||||
signer = signer_username,
|
signer = signer_username,
|
||||||
serial_number = "%x" % cert.serial_number,
|
serial_number = "%x" % cert.serial_number,
|
||||||
|
organizational_unit = cert.subject.native.get("organizational_unit_name"),
|
||||||
signed = cert["tbs_certificate"]["validity"]["not_before"].native.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "Z",
|
signed = cert["tbs_certificate"]["validity"]["not_before"].native.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "Z",
|
||||||
expires = cert["tbs_certificate"]["validity"]["not_after"].native.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "Z",
|
expires = cert["tbs_certificate"]["validity"]["not_after"].native.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "Z",
|
||||||
sha256sum = hashlib.sha256(buf).hexdigest()))
|
sha256sum = hashlib.sha256(buf).hexdigest()))
|
||||||
|
@ -55,7 +55,7 @@ def self_enroll():
|
|||||||
fh.write(asymmetric.dump_private_key(private_key, None))
|
fh.write(asymmetric.dump_private_key(private_key, None))
|
||||||
else:
|
else:
|
||||||
now = datetime.utcnow()
|
now = datetime.utcnow()
|
||||||
if now - timedelta(days=1) < expires:
|
if now + timedelta(days=1) < expires:
|
||||||
click.echo("Certificate %s still valid, delete to self-enroll again" % path)
|
click.echo("Certificate %s still valid, delete to self-enroll again" % path)
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -307,7 +307,7 @@ def delete_request(common_name):
|
|||||||
config.LONG_POLL_PUBLISH % hashlib.sha256(buf).hexdigest(),
|
config.LONG_POLL_PUBLISH % hashlib.sha256(buf).hexdigest(),
|
||||||
headers={"User-Agent": "Certidude API"})
|
headers={"User-Agent": "Certidude API"})
|
||||||
|
|
||||||
def sign(common_name, skip_notify=False, skip_push=False, overwrite=False, ou=None, signer=None):
|
def sign(common_name, skip_notify=False, skip_push=False, overwrite=False, profile="default", signer=None):
|
||||||
"""
|
"""
|
||||||
Sign certificate signing request by it's common name
|
Sign certificate signing request by it's common name
|
||||||
"""
|
"""
|
||||||
@ -320,13 +320,15 @@ def sign(common_name, skip_notify=False, skip_push=False, overwrite=False, ou=No
|
|||||||
|
|
||||||
|
|
||||||
# Sign with function below
|
# Sign with function below
|
||||||
cert, buf = _sign(csr, csr_buf, skip_notify, skip_push, overwrite, ou, signer)
|
cert, buf = _sign(csr, csr_buf, skip_notify, skip_push, overwrite, profile, signer)
|
||||||
|
|
||||||
os.unlink(req_path)
|
os.unlink(req_path)
|
||||||
return cert, buf
|
return cert, buf
|
||||||
|
|
||||||
def _sign(csr, buf, skip_notify=False, skip_push=False, overwrite=False, ou=None, signer=None):
|
def _sign(csr, buf, skip_notify=False, skip_push=False, overwrite=False, profile="default", signer=None):
|
||||||
# TODO: CRLDistributionPoints, OCSP URL, Certificate URL
|
# TODO: CRLDistributionPoints, OCSP URL, Certificate URL
|
||||||
|
if profile not in config.PROFILES:
|
||||||
|
raise ValueError("Invalid profile supplied '%s'" % profile)
|
||||||
|
|
||||||
assert buf.startswith(b"-----BEGIN CERTIFICATE REQUEST-----")
|
assert buf.startswith(b"-----BEGIN CERTIFICATE REQUEST-----")
|
||||||
assert isinstance(csr, CertificationRequest)
|
assert isinstance(csr, CertificationRequest)
|
||||||
@ -367,8 +369,9 @@ def _sign(csr, buf, skip_notify=False, skip_push=False, overwrite=False, ou=None
|
|||||||
|
|
||||||
# Sign via signer process
|
# Sign via signer process
|
||||||
dn = {u'common_name': common_name }
|
dn = {u'common_name': common_name }
|
||||||
if ou:
|
profile_server_flags, lifetime, dn["organizational_unit_name"], _ = config.PROFILES[profile]
|
||||||
dn["organizational_unit"] = ou
|
lifetime = int(lifetime)
|
||||||
|
|
||||||
builder = CertificateBuilder(dn, csr_pubkey)
|
builder = CertificateBuilder(dn, csr_pubkey)
|
||||||
builder.serial_number = random.randint(
|
builder.serial_number = random.randint(
|
||||||
0x1000000000000000000000000000000000000000,
|
0x1000000000000000000000000000000000000000,
|
||||||
@ -376,16 +379,14 @@ def _sign(csr, buf, skip_notify=False, skip_push=False, overwrite=False, ou=None
|
|||||||
|
|
||||||
now = datetime.utcnow()
|
now = datetime.utcnow()
|
||||||
builder.begin_date = now - timedelta(minutes=5)
|
builder.begin_date = now - timedelta(minutes=5)
|
||||||
builder.end_date = now + timedelta(days=config.SERVER_CERTIFICATE_LIFETIME
|
builder.end_date = now + timedelta(days=lifetime)
|
||||||
if server_flags(common_name)
|
|
||||||
else config.CLIENT_CERTIFICATE_LIFETIME)
|
|
||||||
builder.issuer = certificate
|
builder.issuer = certificate
|
||||||
builder.ca = False
|
builder.ca = False
|
||||||
builder.key_usage = set(["digital_signature", "key_encipherment"])
|
builder.key_usage = set(["digital_signature", "key_encipherment"])
|
||||||
|
|
||||||
# OpenVPN uses CN while StrongSwan uses SAN
|
# If we have FQDN and profile suggests server flags, enable them
|
||||||
if server_flags(common_name):
|
if server_flags(common_name) and profile_server_flags:
|
||||||
builder.subject_alt_domains = [common_name]
|
builder.subject_alt_domains = [common_name] # OpenVPN uses CN while StrongSwan uses SAN to match hostname of the server
|
||||||
builder.extended_key_usage = set(["server_auth", "1.3.6.1.5.5.8.2.2", "client_auth"])
|
builder.extended_key_usage = set(["server_auth", "1.3.6.1.5.5.8.2.2", "client_auth"])
|
||||||
else:
|
else:
|
||||||
builder.extended_key_usage = set(["client_auth"])
|
builder.extended_key_usage = set(["client_auth"])
|
||||||
|
@ -1312,7 +1312,7 @@ def certidude_list(verbose, show_key_type, show_extensions, show_path, show_sign
|
|||||||
def certidude_sign(common_name, overwrite):
|
def certidude_sign(common_name, overwrite):
|
||||||
from certidude import authority
|
from certidude import authority
|
||||||
drop_privileges()
|
drop_privileges()
|
||||||
cert = authority.sign(common_name, overwrite)
|
cert = authority.sign(common_name, overwrite=overwrite)
|
||||||
|
|
||||||
|
|
||||||
@click.command("revoke", help="Revoke certificate")
|
@click.command("revoke", help="Revoke certificate")
|
||||||
|
@ -60,8 +60,6 @@ USER_MULTIPLE_CERTIFICATES = {
|
|||||||
cp.get("authority", "user enrollment")]
|
cp.get("authority", "user enrollment")]
|
||||||
|
|
||||||
REQUEST_SUBMISSION_ALLOWED = cp.getboolean("authority", "request submission allowed")
|
REQUEST_SUBMISSION_ALLOWED = cp.getboolean("authority", "request submission allowed")
|
||||||
CLIENT_CERTIFICATE_LIFETIME = cp.getint("signature", "client certificate lifetime")
|
|
||||||
SERVER_CERTIFICATE_LIFETIME = cp.getint("signature", "server certificate lifetime")
|
|
||||||
AUTHORITY_CERTIFICATE_URL = cp.get("signature", "authority certificate url")
|
AUTHORITY_CERTIFICATE_URL = cp.get("signature", "authority certificate url")
|
||||||
AUTHORITY_CRL_URL = cp.get("signature", "revoked url")
|
AUTHORITY_CRL_URL = cp.get("signature", "revoked url")
|
||||||
AUTHORITY_OCSP_URL = cp.get("signature", "responder url")
|
AUTHORITY_OCSP_URL = cp.get("signature", "responder url")
|
||||||
|
@ -118,7 +118,7 @@ function onRequestSubmitted(e) {
|
|||||||
console.info("Going to prepend:", request);
|
console.info("Going to prepend:", request);
|
||||||
onRequestDeleted(e); // Delete any existing ones just in case
|
onRequestDeleted(e); // Delete any existing ones just in case
|
||||||
$("#pending_requests").prepend(
|
$("#pending_requests").prepend(
|
||||||
env.render('views/request.html', { request: request }));
|
env.render('views/request.html', { request: request, session: session }));
|
||||||
$("#pending_requests time").timeago();
|
$("#pending_requests time").timeago();
|
||||||
},
|
},
|
||||||
error: function(response) {
|
error: function(response) {
|
||||||
|
@ -28,23 +28,105 @@ curl -f -L -H "Content-type: application/pkcs10" --data-binary @client_req.pem \
|
|||||||
http://{{ window.location.hostname }}/api/request/?wait=yes > client_cert.pem</code></pre>
|
http://{{ window.location.hostname }}/api/request/?wait=yes > client_cert.pem</code></pre>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h5>Vanilla OpenWrt/LEDE</h5>
|
<h5>OpenVPN gateway on OpenWrt/LEDE router</h5>
|
||||||
|
|
||||||
<p>On OpenWrt/LEDE router to convert it into VPN gateway:</p>
|
<p>First enroll certificates:</p>
|
||||||
<div class="highlight">
|
<div class="highlight">
|
||||||
<pre class="code"><code>mkdir -p /var/lib/certidude/{{ window.location.hostname }}; \
|
<pre class="code"><code># Derive FQDN from WAN interface's reverse DNS record
|
||||||
grep -c certidude /etc/sysupgrade.conf || echo /var/lib/certidude >> /etc/sysupgrade.conf; \
|
FQDN=$(nslookup $(uci get network.wan.ipaddr) | grep "name =" | head -n1 | cut -d "=" -f 2 | xargs)
|
||||||
curl -f http://{{ window.location.hostname }}/api/certificate/ -o /var/lib/certidude/{{ window.location.hostname }}/ca_cert.pem; \
|
|
||||||
test -e /var/lib/certidude/{{ window.location.hostname }}/client_key.pem || openssl genrsa -out /var/lib/certidude/{{ window.location.hostname }}/client_key.pem 2048; \
|
mkdir -p /etc/certidude/authority/{{ window.location.hostname }}; \
|
||||||
test -e /var/lib/certidude/{{ window.location.hostname }}/client_req.pem || read -p "Enter FQDN: " NAME; openssl req -new -sha256 \
|
grep -c certidude /etc/sysupgrade.conf || echo /etc/certidude >> /etc/sysupgrade.conf; \
|
||||||
-key /var/lib/certidude/{{ window.location.hostname }}/client_key.pem \
|
curl -f http://{{ window.location.hostname }}/api/certificate/ -o /etc/certidude/authority/{{ window.location.hostname }}/ca_cert.pem; \
|
||||||
-out /var/lib/certidude/{{ window.location.hostname }}/client_req.pem -subj "/CN=$NAME"; \
|
test -e /etc/certidude/authority/{{ window.location.hostname }}/server_key.pem \
|
||||||
|
|| openssl genrsa -out /etc/certidude/authority/{{ window.location.hostname }}/server_key.pem 2048; \
|
||||||
|
test -e /etc/certidude/authority/{{ window.location.hostname }}/server_req.pem \
|
||||||
|
|| openssl req -new -sha256 \
|
||||||
|
-key /etc/certidude/authority/{{ window.location.hostname }}/server_key.pem \
|
||||||
|
-out /etc/certidude/authority/{{ window.location.hostname }}/server_req.pem -subj "/CN=$FQDN"; \
|
||||||
curl -f -L -H "Content-type: application/pkcs10" \
|
curl -f -L -H "Content-type: application/pkcs10" \
|
||||||
--data-binary @/var/lib/certidude/{{ window.location.hostname }}/client_req.pem \
|
--data-binary @/etc/certidude/authority/{{ window.location.hostname }}/server_req.pem \
|
||||||
-o /var/lib/certidude/{{ window.location.hostname }}/client_cert.pem \
|
-o /etc/certidude/authority/{{ window.location.hostname }}/server_cert.pem \
|
||||||
http://{{ window.location.hostname }}/api/request/?wait=yes</code></pre>
|
http://{{ window.location.hostname }}/api/request/?wait=yes</code></pre>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<p>Then set up service:</p>
|
||||||
|
<div class="highlight">
|
||||||
|
<pre class="code"><code># Create VPN gateway up/down script for reporting client IP addresses to CA
|
||||||
|
cat <<\EOF > /etc/certidude/updown
|
||||||
|
#!/bin/sh
|
||||||
|
CURL="curl -f --key /etc/certidude/authority/{{ window.location.hostname }}/server_key.pem --cert /etc/certidude/authority/{{ window.location.hostname }}/server_cert.pem --cacert /etc/certidude/authority/{{ window.location.hostname }}/ca_cert.pem https://{{ window.location.hostname }}:8443/api/lease/"
|
||||||
|
|
||||||
|
case $PLUTO_VERB in
|
||||||
|
up-client|down-client) $CURL --data "outer_address=$PLUTO_PEER&inner_address=$PLUTO_PEER_SOURCEIP&client=$PLUTO_PEER_ID" ;;
|
||||||
|
*) $CURL --data "client=$X509_0_CN&outer_address=$untrusted_ip&inner_address=$ifconfig_pool_remote_ip&serial=$tls_serial_0" ;;
|
||||||
|
esac
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod +x /etc/certidude/updown
|
||||||
|
|
||||||
|
|
||||||
|
# Generate Diffie-Hellman parameters file for OpenVPN
|
||||||
|
test -e /etc/certidude/dh.pem \
|
||||||
|
|| openssl dhparam 2048 -out /etc/certidude/dh.pem
|
||||||
|
|
||||||
|
# Create interface definition for tunnel
|
||||||
|
uci set network.vpn=interface
|
||||||
|
uci set network.vpn.name='vpn'
|
||||||
|
uci set network.vpn.ifname=tun_s2c
|
||||||
|
uci set network.vpn.proto='none'
|
||||||
|
|
||||||
|
# Create zone definition for VPN interface
|
||||||
|
uci set firewall.vpn=zone
|
||||||
|
uci set firewall.vpn.name='vpn'
|
||||||
|
uci set firewall.vpn.input='ACCEPT'
|
||||||
|
uci set firewall.vpn.forward='ACCEPT'
|
||||||
|
uci set firewall.vpn.output='ACCEPT'
|
||||||
|
uci set firewall.vpn.network='vpn'
|
||||||
|
|
||||||
|
# Allow UDP 1194 on WAN interface
|
||||||
|
uci set firewall.openvpn=rule
|
||||||
|
uci set firewall.openvpn.name='Allow OpenVPN'
|
||||||
|
uci set firewall.openvpn.src='wan'
|
||||||
|
uci set firewall.openvpn.dest_port=1194
|
||||||
|
uci set firewall.openvpn.proto='udp'
|
||||||
|
uci set firewall.openvpn.target='ACCEPT'
|
||||||
|
|
||||||
|
# Forward traffic from VPN to LAN
|
||||||
|
uci set firewall.c2s=forwarding
|
||||||
|
uci set firewall.c2s.src='vpn'
|
||||||
|
uci set firewall.c2s.dest='lan'
|
||||||
|
|
||||||
|
# Permit DNS queries from VPN
|
||||||
|
uci set dhcp.@dnsmasq[0].localservice='0'
|
||||||
|
|
||||||
|
touch /etc/config/openvpn
|
||||||
|
uci set openvpn.s2c=openvpn
|
||||||
|
uci set openvpn.s2c.local=$(uci get network.wan.ipaddr)
|
||||||
|
uci set openvpn.s2c.script_security=2
|
||||||
|
uci set openvpn.s2c.client_connect='/etc/certidude/updown'
|
||||||
|
uci set openvpn.s2c.tls_version_min='1.2'
|
||||||
|
uci set openvpn.s2c.tls_cipher='TLS-DHE-RSA-WITH-AES-256-GCM-SHA384'
|
||||||
|
uci set openvpn.s2c.cipher='AES-256-CBC'
|
||||||
|
uci set openvpn.s2c.auth='SHA384'
|
||||||
|
uci set openvpn.s2c.dev=tun_s2c
|
||||||
|
uci set openvpn.s2c.server='10.179.43.0 255.255.255.0'
|
||||||
|
uci set openvpn.s2c.key='/etc/certidude/authority/{{ window.location.hostname }}/server_key.pem'
|
||||||
|
uci set openvpn.s2c.cert='/etc/certidude/authority/{{ window.location.hostname }}/server_cert.pem'
|
||||||
|
uci set openvpn.s2c.ca='/etc/certidude/authority/{{ window.location.hostname }}/ca_cert.pem'
|
||||||
|
uci set openvpn.s2c.dh='/etc/certidude/dh.pem'
|
||||||
|
uci set openvpn.s2c.enabled=1
|
||||||
|
uci set openvpn.s2c.comp_lzo=yes
|
||||||
|
uci add_list openvpn.s2c.push="route-metric 1000"
|
||||||
|
uci add_list openvpn.s2c.push="route $(uci get network.lan.ipaddr) $(uci get network.lan.netmask)"
|
||||||
|
uci add_list openvpn.s2c.push="dhcp-option DNS $(uci get network.lan.ipaddr)"
|
||||||
|
uci add_list openvpn.s2c.push="dhcp-option DOMAIN $(uci get dhcp.@dnsmasq[0].domain)"
|
||||||
|
|
||||||
|
/etc/init.d/openvpn restart
|
||||||
|
/etc/init.d/firewall restart</code></pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
{% if session.authority.builder %}
|
{% if session.authority.builder %}
|
||||||
<h5>OpenWrt/LEDE image builder</h5>
|
<h5>OpenWrt/LEDE image builder</h5>
|
||||||
<p>Hit a link to generate machine specific image. Note that this might take couple minutes to finish.</p>
|
<p>Hit a link to generate machine specific image. Note that this might take couple minutes to finish.</p>
|
||||||
|
@ -30,10 +30,11 @@
|
|||||||
</button>
|
</button>
|
||||||
<div class="dropdown-menu">
|
<div class="dropdown-menu">
|
||||||
{% for p in session.authority.signature.profiles %}
|
{% for p in session.authority.signature.profiles %}
|
||||||
<a class="dropdown-item" href="/api/request/?organizational_unit={{ p.organizational_unit }}&lifetime={{ p.lifetime }}&flags={{ p.flags }}">
|
<a class="dropdown-item{% if p.server and not request.server %} disabled{% endif %}"
|
||||||
{% if p.organizational_unit %}
|
{% if p.server and not request.server %}title="Resubmit with FQDN as common name"{% endif %}
|
||||||
{{ p.organizational_unit }} ({{ p.flags }}){% else %}
|
href="#" onclick="javascript:$.ajax({url:'/api/request/{{request.common_name}}/?sha256sum={{ request.sha256sum }}&profile={{ p.name }}',type:'post'});">
|
||||||
{{ p.flags | capitalize }}{% endif %}, expires in {{ p.lifetime }} days</a>
|
{% if p.title %}{{ p.title }} ({% if p.server %}server{% else %}client{% endif %}){% else %}
|
||||||
|
{% if p.server %}Server{% else %}Client{% endif %}{% endif %}, expires in {{ p.lifetime }} days</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
<p>
|
<p>
|
||||||
<div id="certificate-{{ certificate.common_name | replace('@', '--') | replace('.', '-') }}" class="card">
|
<div id="certificate-{{ certificate.common_name | replace('@', '--') | replace('.', '-') }}" class="card">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
|
{% if certificate.organizational_unit %}
|
||||||
|
<i class="fa fa-folder" aria-hidden="true"></i>
|
||||||
|
{{ certificate.organizational_unit }} /
|
||||||
|
{% endif %}
|
||||||
{% if certificate.server %}
|
{% if certificate.server %}
|
||||||
<i class="fa fa-server"></i>
|
<i class="fa fa-server"></i>
|
||||||
{% else %}
|
{% else %}
|
||||||
@ -17,12 +21,9 @@
|
|||||||
</span>
|
</span>
|
||||||
|
|
||||||
Signed
|
Signed
|
||||||
<time class="timeago" datetime="{{ certificate.signed }}">Certificate was signed {{ certificate.signed }}</time>,
|
<time class="timeago" datetime="{{ certificate.signed }}">Certificate was signed {{ certificate.signed }}</time>{% if certificate.signer %} by {{ certificate.signer }}{% endif %},
|
||||||
expires
|
expires
|
||||||
<time class="timeago" datetime="{{ certificate.expires }}">Certificate expires {{ certificate.expires }}</time>.
|
<time class="timeago" datetime="{{ certificate.expires }}">Certificate expires {{ certificate.expires }}</time>.
|
||||||
{% if certificate.organizational_unit %}
|
|
||||||
Part of {{ certificate.organizational_unit }} organizational unit.
|
|
||||||
{% endif %}
|
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
{% if session.authority.tagging %}
|
{% if session.authority.tagging %}
|
||||||
@ -91,10 +92,10 @@ curl --cert client_cert.pem https://{{ window.location.hostname }}:8443/api/sign
|
|||||||
<div style="overflow: auto; max-width: 100%;">
|
<div style="overflow: auto; max-width: 100%;">
|
||||||
<table class="table" id="signed_certificates">
|
<table class="table" id="signed_certificates">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr><th>Common name</th><td>{{ certificate.common_name }}</td></tr>
|
<tr><th>Common name</th><td>{{ certificate.common_name }}</td></tr>
|
||||||
<tr><th>Organizational unit</th><td>{% if certificate.organizational_unit %}{{ certificate.organizational_unit }}{% else %}-{% endif %}</td></tr>
|
<tr><th>Organizational unit</th><td>{% if certificate.organizational_unit %}{{ certificate.organizational_unit }}{% else %}-{% endif %}</td></tr>
|
||||||
<tr><th>Serial number</th><td style="word-wrap:break-word;">{{ certificate.serial | serial }}</td></tr>
|
<tr><th>Serial number</th><td style="word-wrap:break-word;">{{ certificate.serial | serial }}</td></tr>
|
||||||
<tr><th>Signed</th><td>{{ certificate.signed | datetime }}{% if certificate.signer %}, by {{ certificate.signer }}{% endif %}</td></tr>
|
<tr><th>Signed</th><td>{{ certificate.signed | datetime }}{% if certificate.signer %} by {{ certificate.signer }}{% endif %}</td></tr>
|
||||||
<tr><th>Expires</th><td>{{ certificate.expires | datetime }}</td></tr>
|
<tr><th>Expires</th><td>{{ certificate.expires | datetime }}</td></tr>
|
||||||
{% if certificate.lease %}
|
{% if certificate.lease %}
|
||||||
<tr><th>Lease</th><td><a href="http://{{ certificate.lease.inner_address }}">{{ certificate.lease.inner_address }}</a> at {{ certificate.lease.last_seen | datetime }}
|
<tr><th>Lease</th><td><a href="http://{{ certificate.lease.inner_address }}">{{ certificate.lease.inner_address }}</a> at {{ certificate.lease.last_seen | datetime }}
|
||||||
|
@ -191,13 +191,13 @@ lifetime = 30
|
|||||||
# Secret for generating and validating tokens, regenerate occasionally
|
# Secret for generating and validating tokens, regenerate occasionally
|
||||||
secret = {{ token_secret }}
|
secret = {{ token_secret }}
|
||||||
|
|
||||||
|
|
||||||
[profile]
|
[profile]
|
||||||
# title, flags, lifetime, organizational unit
|
# name, flags, lifetime, organizational unit, title
|
||||||
default = client, 120,
|
default = client, 120, Roadwarrior, Roadwarrior
|
||||||
srv = server, 365, Server
|
gw = server, 30, Gateway, Gateway
|
||||||
gw = server, 3, Gateway
|
srv = server, 365, Server,
|
||||||
ap = client, 1825, Access Point
|
ap = client, 1825, Access Point, Access Point
|
||||||
|
mfp = client, 30, MFP, Printers
|
||||||
|
|
||||||
[script]
|
[script]
|
||||||
# Path to the folder with scripts that can be served to the clients, set none to disable scripting
|
# Path to the folder with scripts that can be served to the clients, set none to disable scripting
|
||||||
|
Loading…
Reference in New Issue
Block a user