;; webid-oidc, implementation of the Solid specification ;; Copyright (C) 2020, 2021 Vivien Kraus ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Affero General Public License as ;; published by the Free Software Foundation, either version 3 of the ;; License, or (at your option) any later version. ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU Affero General Public License for more details. ;; You should have received a copy of the GNU Affero General Public License ;; along with this program. If not, see . (define-module (vkraus services webid-oidc) #:use-module (gnu services) #:use-module (gnu services shepherd) #:use-module (gnu services admin) #:use-module (gnu system shadow) #:use-module (gnu packages admin) #:use-module (vkraus packages webid-oidc) #:use-module (guix gexp) #:use-module (guix modules) #:use-module (guix records) #:use-module (ice-9 match) #:use-module (ice-9 optargs)) (define-record-type* webid-oidc-issuer-configuration make-webid-oidc-issuer-configuration webid-oidc-issuer-configuration? (webid-oidc webid-oidc-issuer-configuration-webid-oidc (default webid-oidc)) (complete-corresponding-source webid-oidc-issuer-configuration-complete-corresponding-source) (issuer webid-oidc-issuer-configuration-issuer) (key-file webid-oidc-issuer-configuration-key-file (default "/var/lib/webid-oidc/issuer/key.jwk")) (subject webid-oidc-issuer-configuration-subject) (encrypted-password webid-oidc-issuer-configuration-encrypted-password) (jwks-uri webid-oidc-issuer-configuration-jwks-uri) (authorization-endpoint-uri webid-oidc-issuer-configuration-authorization-endpoint-uri) (token-endpoint-uri webid-oidc-issuer-configuration-token-endpoint-uri) (port webid-oidc-issuer-configuration-port (default 8088)) (extra-options webid-oidc-issuer-configuration-extra-options (default '()))) (define-record-type* webid-oidc-reverse-proxy-configuration make-webid-oidc-reverse-proxy-configuration webid-oidc-reverse-proxy-configuration? (webid-oidc webid-oidc-reverse-proxy-configuration-webid-oidc (default webid-oidc)) (complete-corresponding-source webid-oidc-reverse-proxy-configuration-complete-corresponding-source) (port webid-oidc-reverse-proxy-port (default 8090)) (inbound-uri webid-oidc-reverse-proxy-configuration-inbound-uri) (outbound-uri webid-oidc-reverse-proxy-configuration-outbound-uri) (header webid-oidc-reverse-proxy-configuration-header (default "XXX-Agent")) (extra-options webid-oidc-reverse-proxy-extra-options (default '()))) (define-record-type* webid-oidc-hello-configuration make-webid-oidc-hello-configuration webid-oidc-hello-configuration? (webid-oidc webid-oidc-hello-configuration-webid-oidc (default webid-oidc)) (complete-corresponding-source webid-oidc-hello-configuration-complete-corresponding-source) (port webid-oidc-hello-configuration-port (default 8089)) (extra-options webid-oidc-hello-configuration-extra-options (default '()))) (define-record-type* webid-oidc-client-service-configuration make-webid-oidc-client-service-configuration webid-oidc-client-service-configuration? (webid-oidc webid-oidc-client-service-configuration-webid-oidc (default webid-oidc)) (complete-corresponding-source webid-oidc-client-service-configuration-complete-corresponding-source) (client-id webid-oidc-client-service-configuration-client-id) (redirect-uri webid-oidc-client-service-configuration-redirect-uri) (client-name webid-oidc-client-service-configuration-client-name (default "Example Solid App")) (client-uri webid-oidc-client-service-configuration-client-uri (default "https://webid-oidc.planete-kraus.eu/Running-a-client.html#Running-a-client")) (port webid-oidc-client-service-configuration-port (default 8088)) (extra-options webid-oidc-client-service-configuration-extra-options (default '()))) (define-record-type* webid-oidc-server-configuration make-webid-oidc-server-configuration webid-oidc-server-configuration? (webid-oidc webid-oidc-server-configuration-webid-oidc (default webid-oidc)) (complete-corresponding-source webid-oidc-server-configuration-complete-corresponding-source) (server-name webid-oidc-server-configuration-server-name) (key-file webid-oidc-server-configuration-key-file (default "/var/lib/webid-oidc/server/key.jwk")) (subject webid-oidc-server-configuration-subject) (encrypted-password webid-oidc-server-configuration-encrypted-password) (jwks-uri webid-oidc-server-configuration-jwks-uri) (authorization-endpoint-uri webid-oidc-server-configuration-authorization-endpoint-uri) (token-endpoint-uri webid-oidc-server-configuration-token-endpoint-uri) (port webid-oidc-server-configuration-port (default 8088)) (extra-options webid-oidc-issuer-configuration-extra-options (default '()))) (export webid-oidc-issuer-configuration make-webid-oidc-issuer-configuration webid-oidc-issuer-configuration? webid-oidc-issuer-configuration-webid-oidc webid-oidc-issuer-configuration-complete-corresponding-source webid-oidc-issuer-configuration-issuer webid-oidc-issuer-configuration-key-file webid-oidc-issuer-configuration-subject webid-oidc-issuer-configuration-encrypted-password webid-oidc-issuer-configuration-jwks-uri webid-oidc-issuer-configuration-authorization-endpoint-uri webid-oidc-issuer-configuration-token-endpoint-uri webid-oidc-issuer-configuration-port webid-oidc-issuer-configuration-extra-options webid-oidc-reverse-proxy-configuration make-webid-oidc-reverse-proxy-configuration webid-oidc-reverse-proxy-configuration? webid-oidc-reverse-proxy-configuration-webid-oidc webid-oidc-reverse-proxy-configuration-complete-corresponding-source webid-oidc-reverse-proxy-configuration-port webid-oidc-reverse-proxy-configuration-inbound-uri webid-oidc-reverse-proxy-configuration-outbound-uri webid-oidc-reverse-proxy-configuration-header webid-oidc-reverse-proxy-configuration-extra-options webid-oidc-hello-configuration make-webid-oidc-hello-configuration webid-oidc-hello-configuration? webid-oidc-hello-configuration-webid-oidc webid-oidc-hello-configuration-complete-corresponding-source webid-oidc-hello-configuration-port webid-oidc-hello-configuration-extra-options webid-oidc-client-service-configuration make-webid-oidc-client-service-configuration webid-oidc-client-service-configuration? webid-oidc-client-service-configuration-webid-oidc webid-oidc-client-service-configuration-complete-corresponding-source webid-oidc-client-service-configuration-client-id webid-oidc-client-service-configuration-redirect-uri webid-oidc-client-service-configuration-client-name webid-oidc-client-service-configuration-client-uri webid-oidc-client-service-configuration-port webid-oidc-client-service-configuration-extra-options webid-oidc-server-configuration make-webid-oidc-server-configuration webid-oidc-server-configuration? webid-oidc-server-configuration-webid-oidc webid-oidc-server-configuration-complete-corresponding-source webid-oidc-server-configuration-server-name webid-oidc-server-configuration-key-file webid-oidc-server-configuration-subject webid-oidc-server-configuration-encrypted-password webid-oidc-server-configuration-jwks-uri webid-oidc-server-configuration-authorization-endpoint-uri webid-oidc-server-configuration-token-endpoint-uri webid-oidc-server-configuration-port webid-oidc-server-configuration-extra-options) (define webid-oidc-issuer-shepherd-service (match-lambda (($ webid-oidc ccs issuer key-file subject encrypted-password jwks-uri authorization-endpoint-uri token-endpoint-uri port extra-options) (with-imported-modules (source-module-closure '((gnu build shepherd) (gnu system file-systems))) (list (shepherd-service (provision '(webid-oidc-issuer)) (documentation "Run the Solid identity provider.") (requirement '(user-processes)) (modules '((gnu build shepherd) (gnu system file-systems))) (start #~(begin (let* ((user (getpwnam "webid-oidc")) (prepare-directory (lambda (dir) (mkdir-p dir) (chown dir (passwd:uid user) (passwd:gid user)) (chmod dir #o700)))) (prepare-directory "/var/log/webid-oidc") (prepare-directory "/var/lib/webid-oidc") (prepare-directory "/var/cache/webid-oidc")) (make-forkexec-constructor (list (string-append #$webid-oidc "/bin/webid-oidc") "identity-provider" "--complete-corresponding-source" #$ccs "--server-name" #$issuer "--key-file" #$key-file "--subject" #$subject "--encrypted-password" #$encrypted-password "--jwks-uri" #$jwks-uri "--authorization-endpoint-uri" #$authorization-endpoint-uri "--token-endpoint-uri" #$token-endpoint-uri "--port" (with-output-to-string (lambda () (display #$port))) "--log-file" "issuer.log" "--error-file" "issuer.err" #$@extra-options) #:user "webid-oidc" #:group "webid-oidc" #:directory "/var/log/webid-oidc" #:environment-variables `("XDG_DATA_HOME=/var/lib" "XDG_CACHE_HOME=/var/cache" "LANG=C")))) (stop #~(make-kill-destructor)))))))) (define webid-oidc-reverse-proxy-shepherd-service (match-lambda (($ webid-oidc ccs port inbound-uri outbound-uri header extra-options) (with-imported-modules (source-module-closure '((gnu build shepherd) (gnu system file-systems))) (list (shepherd-service (provision '(webid-oidc-reverse-proxy)) (documentation "Run a proxy to authenticate with Solid.") (requirement '(user-processes)) (modules '((gnu build shepherd) (gnu system file-systems))) (start #~(begin (let* ((user (getpwnam "webid-oidc")) (prepare-directory (lambda (dir) (mkdir-p dir) (chown dir (passwd:uid user) (passwd:gid user)) (chmod dir #o700)))) (prepare-directory "/var/log/webid-oidc") (prepare-directory "/var/lib/webid-oidc") (prepare-directory "/var/cache/webid-oidc")) (make-forkexec-constructor (list (string-append #$webid-oidc "/bin/webid-oidc") "reverse-proxy" "--complete-corresponding-source" #$ccs "--port" (with-output-to-string (lambda () (display #$port))) "--server-name" #$inbound-uri "--backend-uri" #$outbound-uri "--header" #$header "--log-file" "reverse-proxy.log" "--error-file" "reverse-proxy.err" #$@extra-options) #:user "webid-oidc" #:group "webid-oidc" #:directory "/var/log/webid-oidc" #:environment-variables `("XDG_DATA_HOME=/var/lib" "XDG_CACHE_HOME=/var/cache" "LANG=C")))) (stop #~(make-kill-destructor)))))))) (define webid-oidc-hello-shepherd-service (match-lambda (($ webid-oidc ccs port extra-options) (with-imported-modules (source-module-closure '((gnu build shepherd) (gnu system file-systems))) (list (shepherd-service (provision '(webid-oidc-hello)) (documentation "Run a demonstration Solid server.") (requirement '(user-processes)) (modules '((gnu build shepherd) (gnu system file-systems))) (start #~(begin (let* ((user (getpwnam "webid-oidc")) (prepare-directory (lambda (dir) (mkdir-p dir) (chown dir (passwd:uid user) (passwd:gid user)) (chmod dir #o700)))) (prepare-directory "/var/log/webid-oidc") (prepare-directory "/var/lib/webid-oidc") (prepare-directory "/var/cache/webid-oidc")) (make-forkexec-constructor (list (string-append #$webid-oidc "/bin/webid-oidc-hello") "--complete-corresponding-source" #$ccs "--port" (with-output-to-string (lambda () (display #$port))) "--log-file" "hello.log" "--error-file" "hello.err" #$@extra-options) #:user "webid-oidc" #:group "webid-oidc" #:directory "/var/log/webid-oidc" #:environment-variables `("XDG_DATA_HOME=/var/lib" "XDG_CACHE_HOME=/var/cache" "LANG=C")))) (stop #~(make-kill-destructor)))))))) (define webid-oidc-client-service-shepherd-service (match-lambda (($ webid-oidc ccs client-id redirect-uri client-name client-uri port extra-options) (with-imported-modules (source-module-closure '((gnu build shepherd) (gnu system file-systems))) (list (shepherd-service (provision '(webid-oidc-client-service)) (documentation "Run a server for a Solid application.") (requirement '(user-processes)) (modules '((gnu build shepherd) (gnu system file-systems))) (start #~(begin (let* ((user (getpwnam "webid-oidc")) (prepare-directory (lambda (dir) (mkdir-p dir) (chown dir (passwd:uid user) (passwd:gid user)) (chmod dir #o700)))) (prepare-directory "/var/log/webid-oidc")) (make-forkexec-constructor (list (string-append #$webid-oidc "/bin/webid-oidc") "client-service" "--complete-corresponding-source" #$ccs "--client-id" #$client-id "--redirect-uri" #$redirect-uri "--client-name" #$client-name "--client-uri" #$client-uri "--port" (with-output-to-string (lambda () (display #$port))) "--log-file" "client-service.log" "--error-file" "client-service.err" #$@extra-options) #:user "webid-oidc" #:group "webid-oidc" #:directory "/var/log/webid-oidc" #:environment-variables `("LANG=C")))) (stop #~(make-kill-destructor)))))))) (define webid-oidc-server-shepherd-service (match-lambda (($ webid-oidc ccs server-name key-file subject encrypted-password jwks-uri authorization-endpoint-uri token-endpoint-uri port extra-options) (with-imported-modules (source-module-closure '((gnu build shepherd) (gnu system file-systems))) (list (shepherd-service (provision '(webid-oidc-server)) (documentation "Run the full Solid server.") (requirement '(user-processes)) (modules '((gnu build shepherd) (gnu system file-systems))) (start #~(begin (let* ((user (getpwnam "webid-oidc")) (prepare-directory (lambda (dir) (mkdir-p dir) (chown dir (passwd:uid user) (passwd:gid user)) (chmod dir #o700)))) (prepare-directory "/var/log/webid-oidc") (prepare-directory "/var/lib/webid-oidc") (prepare-directory "/var/cache/webid-oidc")) (make-forkexec-constructor (list (string-append #$webid-oidc "/bin/webid-oidc") "server" "--complete-corresponding-source" #$ccs "--server-name" #$server-name "--key-file" #$key-file "--subject" #$subject "--encrypted-password" #$encrypted-password "--jwks-uri" #$jwks-uri "--authorization-endpoint-uri" #$authorization-endpoint-uri "--token-endpoint-uri" #$token-endpoint-uri "--port" (with-output-to-string (lambda () (display #$port))) "--log-file" "server.log" "--error-file" "server.err" #$@extra-options) #:user "webid-oidc" #:group "webid-oidc" #:directory "/var/log/webid-oidc" #:environment-variables `("XDG_DATA_HOME=/var/lib" "XDG_CACHE_HOME=/var/cache" "LANG=C")))) (stop #~(make-kill-destructor)))))))) (define %webid-oidc-accounts (list (user-group (name "webid-oidc") (system? #t)) (user-account (name "webid-oidc") (group "webid-oidc") (system? #t) (comment "The user that runs the webid-oidc issuer and resource server.") (home-directory "/var/empty") (shell (file-append shadow "/sbin/nologin"))))) (define (%webid-oidc-log-rotation file) (list (log-rotation (frequency 'daily) (files (map (lambda (ext) (string-append "/var/log/webid-oidc/" file "." ext)) '("log" "err"))) (options '("sharedscripts" "storedir /var/log/webid-oidc"))))) (define-public webid-oidc-issuer-service-type (service-type (name 'webid-oidc-issuer) (extensions (list (service-extension account-service-type (const %webid-oidc-accounts)) (service-extension rottlog-service-type (const (%webid-oidc-log-rotation "issuer"))) (service-extension shepherd-root-service-type webid-oidc-issuer-shepherd-service))))) (define-public webid-oidc-reverse-proxy-service-type (service-type (name 'webid-oidc-reverse-proxy) (extensions (list (service-extension account-service-type (const %webid-oidc-accounts)) (service-extension rottlog-service-type (const (%webid-oidc-log-rotation "reverse-proxy"))) (service-extension shepherd-root-service-type webid-oidc-reverse-proxy-shepherd-service))))) (define-public webid-oidc-hello-service-type (service-type (name 'webid-oidc-hello) (extensions (list (service-extension account-service-type (const %webid-oidc-accounts)) (service-extension rottlog-service-type (const (%webid-oidc-log-rotation "hello"))) (service-extension shepherd-root-service-type webid-oidc-hello-shepherd-service))))) (define-public webid-oidc-client-service-service-type (service-type (name 'webid-oidc-client-service) (extensions (list (service-extension account-service-type (const %webid-oidc-accounts)) (service-extension rottlog-service-type (const (%webid-oidc-log-rotation "client-service"))) (service-extension shepherd-root-service-type webid-oidc-client-service-shepherd-service))))) (define-public webid-oidc-server-service-type (service-type (name 'webid-oidc-server) (extensions (list (service-extension account-service-type (const %webid-oidc-accounts)) (service-extension rottlog-service-type (const (%webid-oidc-log-rotation "server"))) (service-extension shepherd-root-service-type webid-oidc-server-shepherd-service)))))