GNU bug report logs - #48803
[PATCH] strongswan: provide a service definition and configuration interface.

Previous Next

Package: guix-patches;

Reported by: Domagoj Stolfa <ds815 <at> gmx.com>

Date: Wed, 2 Jun 2021 23:12:02 UTC

Severity: normal

Tags: patch

Done: Tobias Geerinckx-Rice <me <at> tobias.gr>

Bug is archived. No further changes may be made.

Full log


View this message in rfc822 format

From: help-debbugs <at> gnu.org (GNU bug Tracking System)
To: Tobias Geerinckx-Rice <me <at> tobias.gr>
Cc: tracker <at> debbugs.gnu.org
Subject: bug#48803: closed ([PATCH] strongswan: provide a service
 definition and configuration interface.)
Date: Thu, 24 Jun 2021 23:18:02 +0000
[Message part 1 (text/plain, inline)]
Your message dated Fri, 25 Jun 2021 01:17:43 +0200
with message-id <87r1gqsvhk.fsf <at> nckx>
and subject line Re: [bug#48803] [PATCH]    gnu: Add strongswan service.
has caused the debbugs.gnu.org bug report #48803,
regarding [PATCH] strongswan: provide a service definition and configuration interface.
to be marked as done.

(If you believe you have received this mail in error, please contact
help-debbugs <at> gnu.org.)


-- 
48803: http://debbugs.gnu.org/cgi/bugreport.cgi?bug=48803
GNU Bug Tracking System
Contact help-debbugs <at> gnu.org with problems
[Message part 2 (message/rfc822, inline)]
From: Domagoj Stolfa <ds815 <at> gmx.com>
To: guix-patches <at> gnu.org
Subject: [PATCH] strongswan: provide a service definition and configuration
 interface.
Date: Wed, 2 Jun 2021 23:11:03 +0100
[Message part 3 (text/plain, inline)]
This commit adds a strongswan-service-type which allows the user to
start strongswan correctly on Guix. Without this, they would need to
manually write a strongswan.conf file and run it with

`STRONGSWAN_CONF=/path/to/strongswan.conf ipsec start`.

For now, we only support the legacy ipsec.conf/ipsec.secrets interface.
Because ipsec.conf depends on indentation and is a deprecated intreface,
we do not provide an EDSL to configure it, and we do not put the config
file in a Guile string (to avoid indentation issues). Similarly,
ipsec.secrets contains the users authentication token/passwords, and is
for security reasons transmitted separately from the configuration file.

This change allows the user to write something as follows in their
config:

```
    (service strongswan-service-type
	     (strongswan-configuration
	      (use-ipsec? #t)
	      (ipsec-conf "/config-files/ipsec.conf")
	      (ipsec-secrets "/config-files/ipsec.secrets")))
```

This will start the charon daemon and allow them to connect to their
VPNs configured in `/config-files/ipsec.conf`.
---
 gnu/services/vpn.scm | 128 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 128 insertions(+)

diff --git a/gnu/services/vpn.scm b/gnu/services/vpn.scm
index 2bcbf76727..e026f2aa58 100644
--- a/gnu/services/vpn.scm
+++ b/gnu/services/vpn.scm
@@ -4,6 +4,7 @@
 ;;; Copyright © 2017 Mathieu Othacehe <m.othacehe <at> gmail.com>
 ;;; Copyright © 2021 Guillaume Le Vaillant <glv <at> posteo.net>
 ;;; Copyright © 2021 Solene Rapenne <solene <at> perso.pw>
+;;; Copyright © 2021 Domagoj Stolfa <ds815 <at> gmx.com>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -26,6 +27,7 @@
   #:use-module (gnu services shepherd)
   #:use-module (gnu system shadow)
   #:use-module (gnu packages admin)
+  #:use-module (gnu packages networking)
   #:use-module (gnu packages vpn)
   #:use-module (guix packages)
   #:use-module (guix records)
@@ -44,6 +46,9 @@
             generate-openvpn-client-documentation
             generate-openvpn-server-documentation
 
+            strongswan-configuration
+            strongswan-service-type
+
             wireguard-peer
             wireguard-peer?
             wireguard-peer-name
@@ -529,6 +534,129 @@ is truncated and rewritten every minute.")
      (openvpn-remote-configuration ,openvpn-remote-configuration-fields))
    'openvpn-client-configuration))
 
+;;;
+;;; Strongswan.
+;;;
+
+(define-record-type* <strongswan-configuration>
+  strongswan-configuration make-strongswan-configuration
+  strongswan-configuration?
+  (strongswan      strongswan-configuration-strongswan ;<package>
+                   (default strongswan))
+  (use-ipsec?      strongswan-configuration-use-ipsec? ;legacy interface
+                   (default #f))
+  (ipsec-conf      strongswan-configuration-ipsec-conf)
+  (ipsec-secrets   strongswan-configuration-ipsec-secrets))
+
+;; In the future, it might be worth implementing a record type to configure
+;; all of the plugins, but for *most* basic usecases, simply creating the
+;; files will be sufficient. Same is true of charon-plugins.
+(define strongswand-config-files
+  (list "charon" "charon-logging" "pki" "pool" "scepclient"
+        "swanctl" "tnc"))
+
+;; Plugins to load.
+(define charon-plugins
+  (list "aes" "aesni" "attr" "attr-sql" "chapoly" "cmac" "constraints"
+        "counters" "curl" "curve25519" "dhcp" "dnskey" "drbg" "eap-aka-3gpp"
+        "eap-aka" "eap-dynamic" "eap-identity" "eap-md5" "eap-mschapv2"
+        "eap-peap" "eap-radius" "eap-simaka-pseudonym" "eap-simaka-reauth"
+        "eap-simaka-sql" "eap-sim" "eap-sim-file" "eap-tls" "eap-tnc"
+        "eap-ttls" "ext-auth" "farp" "fips-prf" "gmp" "ha" "hmac"
+        "kernel-netlink" "led" "md4" "md5" "mgf1" "nonce" "openssl" "pem"
+        "pgp" "pkcs12" "pkcs1" "pkcs7" "pkcs8" "pubkey" "random" "rc2"
+        "resolve" "revocation" "sha1" "sha2" "socket-default" "soup" "sql"
+        "sqlite" "sshkey" "tnc-tnccs" "vici" "x509" "xauth-eap" "xauth-generic"
+        "xauth-noauth" "xauth-pam" "xcbc"))
+
+(define (strongswan-configuration-file config)
+  (match-record config <strongswan-configuration>
+    (strongswan use-ipsec? ipsec-conf ipsec-secrets)
+    (let* ((strongswan-dir
+            (computed-file
+             "strongswan.d"
+             #~(begin
+                 (mkdir #$output)
+                 ;; Create all of the configuration files in strongswan.d/*.conf
+                 (map (lambda (conf-file)
+                        (let* ((filename (string-append
+                                          #$output "/"
+                                          conf-file ".conf")))
+                          (call-with-output-file filename
+                            (lambda (port)
+                              (display
+                               "# Created by 'strongswan-service'\n"
+                               port)))))
+                      (list #$@strongswand-config-files))
+                 (mkdir (string-append #$output "/charon"))
+                 ;; And all of the strongswan.d/charon/*.conf files (plugins)
+                 (map (lambda (plugin)
+                        (let* ((filename (string-append
+                                          #$output "/charon/"
+                                          plugin ".conf")))
+                          (call-with-output-file filename
+                            (lambda (port)
+                              (format port "~a {
+  load = yes
+}"
+                                      plugin)))))
+                      (list #$@charon-plugins))))))
+      ;; Generate our strongswan.conf to reflect the user configuration.
+      (computed-file
+       "strongswan.conf"
+       #~(begin
+           (call-with-output-file #$output
+             (lambda (port)
+               (display "# Generated by 'strongswan-service'.\n" port)
+               (format port "charon {
+  load_modular = yes
+  plugins {
+    include ~a/charon/*.conf"
+                       #$strongswan-dir)
+               (if #$use-ipsec?
+                   (format port "
+    stroke {
+      load = yes
+      secrets_file = ~a
+    }
+  }
+}
+
+starter {
+  config_file = ~a
+}
+
+include ~a/*.conf"
+                           #$ipsec-secrets
+                           #$ipsec-conf
+                           #$strongswan-dir)
+                   (format port "
+  }
+}
+include ~a/*.conf"
+                           #$strongswan-dir)))))))))
+
+(define (strongswan-shepherd-service config)
+  (let* ((ipsec (file-append strongswan "/sbin/ipsec"))
+        (strongswan-conf-path (strongswan-configuration-file config)))
+    (list (shepherd-service
+           (requirement '(networking))
+           (provision '(strongswan))
+           (start #~(make-forkexec-constructor
+                     (list #$ipsec "start" "--nofork")
+                     #:environment-variables
+                     (list (string-append "STRONGSWAN_CONF="
+                                          #$strongswan-conf-path))))
+           (stop #~(make-kill-destructor))
+           (documentation "Start the charon daemon for IPsec VPN")))))
+
+(define strongswan-service-type
+  (service-type
+   (name 'strongswan)
+   (extensions
+    (list (service-extension shepherd-root-service-type
+                             strongswan-shepherd-service)))))
+
 ;;;
 ;;; Wireguard.
 ;;;
-- 
2.31.1

[signature.asc (application/pgp-signature, inline)]
[Message part 5 (message/rfc822, inline)]
From: Tobias Geerinckx-Rice <me <at> tobias.gr>
To: Domagoj Stolfa <ds815 <at> gmx.com>
Cc: 48803-done <at> debbugs.gnu.org, guix-patches <at> gnu.org
Subject: Re: [bug#48803] [PATCH]    gnu: Add strongswan service.
Date: Fri, 25 Jun 2021 01:17:43 +0200
[Message part 6 (text/plain, inline)]
Domagoj!

This is finally on master with the following changes:

Domagoj Stolfa 写道:
>    * gnu/services/vpn.scm (strongswan-configuration): New record 
>    type.
>    (charon-plugins, strongswan-configuration-file)
>    (strongswan-shepherd-service, strongswan-service-type): New 
>    variables.

I don't know where this extra spacing came from but removed it.

> +@subheading StrongSwan

I'm sure some style guides disapprove, but I changed all usage of 
‘StrongSwan’ to upstream's ‘strongSwan’.

> +Currently, the StrongSwan service only provides legacy-style 
> configuration with
> +ipsec.conf and ipsec.secrets files.

We have cool @file{} mark up so I used it.

> +@defvr {Scheme Variable} strongswan-service-type
> +A service type for StrongSwan configuration.

Added a very brief ‘IPsec VPN’ context.

> +@lisp
> +(service strongswan-service-type
> +         (strongswan-configuration
> +         (ipsec-conf "/etc/ipsec.conf")
> +         (ipsec-secrets "/etc/ipsec.secrets")))

Fixed the indentation.

> +@item @code{ipsec-conf} (default: @code{#f})
> +The path to an ipsec.conf file.  If set to @code{#f}, 
> @code{ipsec-secrets} will
> +also be ignored.

Reworded this to match the exception I added below.  Added moar 
@file{}.

>  @c %end of automatic openvpn-server documentation

This indicates that the author of the previous OpenVPN section 
automated the docs somehow.  I moved it back.

>  @subsubheading Wireguard
> diff --git a/gnu/services/vpn.scm b/gnu/services/vpn.scm
> index 2bcbf76727..691cc3c05a 100644
> --- a/gnu/services/vpn.scm
> +++ b/gnu/services/vpn.scm
> @@ -26,6 +26,7 @@
>    #:use-module (gnu services shepherd)
>    #:use-module (gnu system shadow)
>    #:use-module (gnu packages admin)
> +  #:use-module (gnu packages networking)

Oops, noticed this only now… I don't think it's needed anymore. 
Can you confirm?

‘guix system’ & friends will now throw an inelegant error if 
ipsec-conf & ipsec-secrets are incongruent.  I couldn't get 
meaningful location data out of CONFIG.  This does the job:

+        (throw 'error
+               (G_ "strongSwan ipsec-conf and ipsec-secrets must 
\
+both be (un)set")))))

> +(define strongswan-service-type
> +  (service-type
> +   (name 'strongswan)
> +   (extensions
> +    (list (service-extension shepherd-root-service-type
> +                             strongswan-shepherd-service)))))

I added a default-value so people can simply write

 (service strongswan-service-type)

and a short description.

Thank you very much!

T G-R
[signature.asc (application/pgp-signature, inline)]

This bug report was last modified 3 years and 336 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.