From 8d213e2b1c934f6861f76aad5eb7c11097fa97de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isma=C3=ABl=20Bouya?= Date: Wed, 22 May 2019 20:55:28 +0200 Subject: Move rest of the modules outside of nixops --- nixops/eldiron.nix | 48 +-- nixops/modules/buildbot/common/build_helpers.py | 256 ---------------- nixops/modules/buildbot/common/master.cfg | 69 ----- nixops/modules/buildbot/default.nix | 198 ------------- .../modules/buildbot/projects/caldance/__init__.py | 190 ------------ .../buildbot/projects/cryptoportfolio/__init__.py | 169 ----------- nixops/modules/buildbot/projects/test/__init__.py | 188 ------------ nixops/modules/certificates.nix | 52 ---- nixops/modules/dns.nix | 132 --------- nixops/modules/ftp.nix | 118 -------- nixops/modules/gitolite/default.nix | 63 ---- nixops/modules/gitolite/gitolite_ldap_groups.sh | 15 - nixops/modules/mail.nix | 13 - nixops/modules/mpd.nix | 56 ---- nixops/modules/pub/default.nix | 52 ---- nixops/modules/pub/restrict | 64 ---- nixops/modules/pub/tmux.restrict.conf | 43 --- nixops/modules/ssh/default.nix | 40 --- nixops/modules/ssh/ldap_authorized_keys.sh | 152 ---------- nixops/modules/task/default.nix | 327 --------------------- nixops/modules/task/www/index.php | 157 ---------- 21 files changed, 7 insertions(+), 2395 deletions(-) delete mode 100644 nixops/modules/buildbot/common/build_helpers.py delete mode 100644 nixops/modules/buildbot/common/master.cfg delete mode 100644 nixops/modules/buildbot/default.nix delete mode 100644 nixops/modules/buildbot/projects/caldance/__init__.py delete mode 100644 nixops/modules/buildbot/projects/cryptoportfolio/__init__.py delete mode 100644 nixops/modules/buildbot/projects/test/__init__.py delete mode 100644 nixops/modules/certificates.nix delete mode 100644 nixops/modules/dns.nix delete mode 100644 nixops/modules/ftp.nix delete mode 100644 nixops/modules/gitolite/default.nix delete mode 100755 nixops/modules/gitolite/gitolite_ldap_groups.sh delete mode 100644 nixops/modules/mail.nix delete mode 100644 nixops/modules/mpd.nix delete mode 100644 nixops/modules/pub/default.nix delete mode 100644 nixops/modules/pub/restrict delete mode 100644 nixops/modules/pub/tmux.restrict.conf delete mode 100644 nixops/modules/ssh/default.nix delete mode 100755 nixops/modules/ssh/ldap_authorized_keys.sh delete mode 100644 nixops/modules/task/default.nix delete mode 100644 nixops/modules/task/www/index.php (limited to 'nixops') diff --git a/nixops/eldiron.nix b/nixops/eldiron.nix index 69231d1..51af1f6 100644 --- a/nixops/eldiron.nix +++ b/nixops/eldiron.nix @@ -7,17 +7,8 @@ eldiron = { config, pkgs, myconfig, ... }: { - nixpkgs.overlays = builtins.attrValues (import ../overlays); - _module.args = { - pkgsNext = import {}; - pkgsPrevious = import {}; - myconfig = { - inherit privateFiles; - env = import "${privateFiles}/environment.nix"; - }; - }; - boot.kernelPackages = pkgs.linuxPackages_latest; + _module.args.privateFiles = privateFiles; networking = { firewall.enable = true; @@ -30,30 +21,15 @@ myconfig.env.servers.eldiron.ips); }; - imports = [ - ./modules/ssh - ./modules/certificates.nix - ./modules/gitolite - ./modules/mpd.nix - ./modules/mail.nix - ./modules/ftp.nix - ./modules/pub - ./modules/task - ./modules/buildbot - ./modules/dns.nix - ] ++ (builtins.attrValues (import ../modules)); + imports = builtins.attrValues (import ../modules); + + myServices.buildbot.enable = true; myServices.databases.enable = true; + myServices.gitolite.enable = true; myServices.irc.enable = true; - services.myGitolite.enable = true; + myServices.pub.enable = true; + myServices.tasks.enable = true; services.pure-ftpd.enable = true; - services.pub.enable = true; - services.myTasks.enable = true; - services.buildbot.enable = true; - - services.journald.extraConfig = '' - MaxLevelStore="warning" - MaxRetentionSec="1year" - ''; deployment = { targetEnv = "hetzner"; @@ -75,16 +51,6 @@ }; }; - users.users.root.packages = [ - pkgs.telnet - pkgs.htop - pkgs.iftop - ]; - - environment.systemPackages = [ - pkgs.vim - ]; - services.cron = { enable = true; systemCronJobs = [ diff --git a/nixops/modules/buildbot/common/build_helpers.py b/nixops/modules/buildbot/common/build_helpers.py deleted file mode 100644 index 384b1ac..0000000 --- a/nixops/modules/buildbot/common/build_helpers.py +++ /dev/null @@ -1,256 +0,0 @@ -from buildbot.plugins import util, steps, schedulers -from buildbot_buildslist import BuildsList - -__all__ = [ - "force_scheduler", "deploy_scheduler", "hook_scheduler", - "clean_branch", "package_and_upload", "SlackStatusPush", - "XMPPStatusPush" - ] - -# Small helpers" -@util.renderer -def clean_branch(props): - if props.hasProperty("branch") and len(props["branch"]) > 0: - return props["branch"].replace("/", "_") - else: - return "HEAD" - -def package_and_upload(package, package_dest, package_url): - return [ - steps.ShellCommand(name="build package", - logEnviron=False, haltOnFailure=True, workdir="source", - command=["git", "archive", "HEAD", "-o", package]), - - steps.FileUpload(name="upload package", workersrc=package, - workdir="source", masterdest=package_dest, - url=package_url, mode=0o644), - - steps.ShellCommand(name="cleanup package", logEnviron=False, - haltOnFailure=True, workdir="source", alwaysRun=True, - command=["rm", "-f", package]), - ] - -# Schedulers -def force_scheduler(name, builders): - return schedulers.ForceScheduler(name=name, - label="Force build", buttonName="Force build", - reason=util.StringParameter(name="reason", label="Reason", default="Force build"), - codebases=[ - util.CodebaseParameter("", - branch=util.StringParameter( - name="branch", label="Git reference (tag, branch)", required=True), - revision=util.FixedParameter(name="revision", default=""), - repository=util.FixedParameter(name="repository", default=""), - project=util.FixedParameter(name="project", default=""), - ), - ], - username=util.FixedParameter(name="username", default="Web button"), - builderNames=builders) - -def deploy_scheduler(name, builders): - return schedulers.ForceScheduler(name=name, - builderNames=builders, - label="Deploy built package", buttonName="Deploy", - username=util.FixedParameter(name="username", default="Web button"), - codebases=[ - util.CodebaseParameter(codebase="", - branch=util.FixedParameter(name="branch", default=""), - revision=util.FixedParameter(name="revision", default=""), - repository=util.FixedParameter(name="repository", default=""), - project=util.FixedParameter(name="project", default=""))], - reason=util.FixedParameter(name="reason", default="Deploy"), - properties=[ - util.ChoiceStringParameter(label="Environment", - name="environment", default="integration", - choices=["integration", "production"]), - BuildsList(label="Build to deploy", name="build"), - ] - ) - -def hook_scheduler(project, timer=10): - return schedulers.AnyBranchScheduler( - change_filter=util.ChangeFilter(category="hooks", project=project), - name=project, treeStableTimer=timer, builderNames=["{}_build".format(project)]) - -# Slack/XMPP status push -from buildbot.reporters.http import HttpStatusPushBase -from twisted.internet import defer -from twisted.python import log -from buildbot.util import httpclientservice -from buildbot.reporters import utils -from buildbot.process import results -from twisted.words.protocols.jabber.jid import JID -from wokkel import client, xmppim -from functools import partial - -class SlackStatusPush(HttpStatusPushBase): - name = "SlackStatusPush" - - @defer.inlineCallbacks - def reconfigService(self, serverUrl, **kwargs): - yield HttpStatusPushBase.reconfigService(self, **kwargs) - self._http = yield httpclientservice.HTTPClientService.getService( - self.master, serverUrl) - - @defer.inlineCallbacks - def send(self, build): - yield utils.getDetailsForBuild(self.master, build, wantProperties=True) - response = yield self._http.post("", json=self.format(build)) - if response.code != 200: - log.msg("%s: unable to upload status: %s" % - (response.code, response.content)) - - def format(self, build): - colors = [ - "#36A64F", # success - "#F1E903", # warnings - "#DA0505", # failure - "#FFFFFF", # skipped - "#000000", # exception - "#FFFFFF", # retry - "#D02CA9", # cancelled - ] - - if "environment" in build["properties"]: - msg = "{} environment".format(build["properties"]["environment"][0]) - if "build" in build["properties"]: - msg = "of archive {} in ".format(build["properties"]["build"][0]) + msg - elif len(build["buildset"]["sourcestamps"][0]["branch"]) > 0: - msg = "revision {}".format(build["buildset"]["sourcestamps"][0]["branch"]) - else: - msg = "build" - - if build["complete"]: - timedelta = int((build["complete_at"] - build["started_at"]).total_seconds()) - hours, rest = divmod(timedelta, 3600) - minutes, seconds = divmod(rest, 60) - if hours > 0: - duration = "{}h {}min {}s".format(hours, minutes, seconds) - elif minutes > 0: - duration = "{}min {}s".format(minutes, seconds) - else: - duration = "{}s".format(seconds) - - text = "Build <{}|{}> of {}'s {} was {} in {}.".format( - build["url"], build["buildid"], - build["builder"]["name"], - msg, - results.Results[build["results"]], - duration, - ) - fields = [ - { - "title": "Build", - "value": "<{}|{}>".format(build["url"], build["buildid"]), - "short": True, - }, - { - "title": "Project", - "value": build["builder"]["name"], - "short": True, - }, - { - "title": "Build status", - "value": results.Results[build["results"]], - "short": True, - }, - { - "title": "Build duration", - "value": duration, - "short": True, - }, - ] - if "environment" in build["properties"]: - fields.append({ - "title": "Environment", - "value": build["properties"]["environment"][0], - "short": True, - }) - if "build" in build["properties"]: - fields.append({ - "title": "Archive", - "value": build["properties"]["build"][0], - "short": True, - }) - attachments = [{ - "fallback": "", - "color": colors[build["results"]], - "fields": fields - }] - else: - text = "Build <{}|{}> of {}'s {} started.".format( - build["url"], build["buildid"], - build["builder"]["name"], - msg, - ) - attachments = [] - - return { - "username": "Buildbot", - "icon_url": "http://docs.buildbot.net/current/_static/icon.png", - "text": text, - "attachments": attachments, - } - -class XMPPStatusPush(HttpStatusPushBase): - name = "XMPPStatusPush" - - @defer.inlineCallbacks - def reconfigService(self, password, recipients, **kwargs): - yield HttpStatusPushBase.reconfigService(self, **kwargs) - self.password = password - self.recipients = recipients - - @defer.inlineCallbacks - def send(self, build): - yield utils.getDetailsForBuild(self.master, build, wantProperties=True) - body = self.format(build) - factory = client.DeferredClientFactory(JID("notify_bot@immae.fr/buildbot"), self.password) - d = client.clientCreator(factory) - def send_message(recipient, stream): - message = xmppim.Message(recipient=JID(recipient), body=body) - message.stanzaType = 'chat' - stream.send(message.toElement()) - # To allow chaining - return stream - for recipient in self.recipients: - d.addCallback(partial(send_message, recipient)) - d.addCallback(lambda _: factory.streamManager.xmlstream.sendFooter()) - d.addErrback(log.err) - - def format(self, build): - if "environment" in build["properties"]: - msg = "{} environment".format(build["properties"]["environment"][0]) - if "build" in build["properties"]: - msg = "of archive {} in ".format(build["properties"]["build"][0]) + msg - elif len(build["buildset"]["sourcestamps"][0]["branch"]) > 0: - msg = "revision {}".format(build["buildset"]["sourcestamps"][0]["branch"]) - else: - msg = "build" - - if build["complete"]: - timedelta = int((build["complete_at"] - build["started_at"]).total_seconds()) - hours, rest = divmod(timedelta, 3600) - minutes, seconds = divmod(rest, 60) - if hours > 0: - duration = "{}h {}min {}s".format(hours, minutes, seconds) - elif minutes > 0: - duration = "{}min {}s".format(minutes, seconds) - else: - duration = "{}s".format(seconds) - - text = "Build {} ( {} ) of {}'s {} was {} in {}.".format( - build["buildid"], build["url"], - build["builder"]["name"], - msg, - results.Results[build["results"]], - duration, - ) - else: - text = "Build {} ( {} ) of {}'s {} started.".format( - build["buildid"], build["url"], - build["builder"]["name"], - msg, - ) - - return text diff --git a/nixops/modules/buildbot/common/master.cfg b/nixops/modules/buildbot/common/master.cfg deleted file mode 100644 index abe08e0..0000000 --- a/nixops/modules/buildbot/common/master.cfg +++ /dev/null @@ -1,69 +0,0 @@ -# -*- python -*- -# ex: set filetype=python: - -from buildbot.plugins import secrets, util, webhooks -from buildbot.util import bytes2unicode -import re -import os -from buildbot_config import E, configure -import json - -class CustomBase(webhooks.base): - def getChanges(self, request): - try: - content = request.content.read() - args = json.loads(bytes2unicode(content)) - except Exception as e: - raise ValueError("Error loading JSON: " + str(e)) - - args.setdefault("comments", "") - args.setdefault("repository", "") - args.setdefault("author", args.get("who")) - - return ([args], None) - -userInfoProvider = util.LdapUserInfo( - uri=E.LDAP_URL, - bindUser=E.LDAP_ADMIN_USER, - bindPw=open(E.SECRETS_FILE + "/ldap", "r").read().rstrip(), - accountBase=E.LDAP_BASE, - accountPattern=E.LDAP_PATTERN, - accountFullName='cn', - accountEmail='mail', - avatarData="jpegPhoto", - groupBase=E.LDAP_BASE, - groupName="cn", - groupMemberPattern=E.LDAP_GROUP_PATTERN, - ) - -c = BuildmasterConfig = { - "title": E.TITLE, - "titleURL": E.TITLE_URL, - "db": { - "db_url": "sqlite:///state.sqlite" - }, - "protocols": { "pb": { "port": E.PB_SOCKET } }, - "workers": [], - "change_source": [], - "schedulers": [], - "builders": [], - "services": [], - "secretsProviders": [ - secrets.SecretInAFile(E.SECRETS_FILE), - ], - "www": { - "change_hook_dialects": { "base": { "custom_class": CustomBase } }, - "plugins": { - "waterfall_view": {}, - "console_view": {}, - "grid_view": {}, - "buildslist": {}, - }, - "auth": util.RemoteUserAuth( - header=b"X-Remote-User", - userInfoProvider=userInfoProvider, - headerRegex=re.compile(br"(?P[^ @]+)")), - } - } - -configure(c) diff --git a/nixops/modules/buildbot/default.nix b/nixops/modules/buildbot/default.nix deleted file mode 100644 index 60279b7..0000000 --- a/nixops/modules/buildbot/default.nix +++ /dev/null @@ -1,198 +0,0 @@ -{ lib, pkgs, config, myconfig, ... }: -let - varDir = "/var/lib/buildbot"; - buildbot_common = pkgs.python3Packages.buildPythonPackage rec { - name = "buildbot_common"; - src = ./common; - format = "other"; - installPhase = '' - mkdir -p $out/${pkgs.python3.pythonForBuild.sitePackages} - cp -a $src $out/${pkgs.python3.pythonForBuild.sitePackages}/buildbot_common - ''; - }; - buildbot = pkgs.python3Packages.buildbot-full; -in -{ - options = { - services.buildbot.enable = lib.mkOption { - type = lib.types.bool; - default = false; - description = '' - Whether to enable buildbot. - ''; - }; - }; - - config = lib.mkIf config.services.buildbot.enable { - ids.uids.buildbot = myconfig.env.buildbot.user.uid; - ids.gids.buildbot = myconfig.env.buildbot.user.gid; - - users.groups.buildbot.gid = config.ids.gids.buildbot; - users.users.buildbot = { - name = "buildbot"; - uid = config.ids.uids.buildbot; - group = "buildbot"; - description = "Buildbot user"; - home = varDir; - extraGroups = [ "keys" ]; - }; - - services.websites.tools.vhostConfs.git.extraConfig = lib.attrsets.mapAttrsToList (k: project: '' - RedirectMatch permanent "^/buildbot/${project.name}$" "/buildbot/${project.name}/" - RewriteEngine On - RewriteRule ^/buildbot/${project.name}/ws(.*)$ unix:///run/buildbot/${project.name}.sock|ws://git.immae.eu/ws$1 [P,NE,QSA,L] - ProxyPass /buildbot/${project.name}/ unix:///run/buildbot/${project.name}.sock|http://${project.name}-git.immae.eu/ - ProxyPassReverse /buildbot/${project.name}/ unix:///run/buildbot/${project.name}.sock|http://${project.name}-git.immae.eu/ - - Use LDAPConnect - Require ldap-group cn=users,ou=${project.name},cn=buildbot,ou=services,dc=immae,dc=eu - - SetEnvIf X-Url-Scheme https HTTPS=1 - ProxyPreserveHost On - - - - Require local - Require ldap-group cn=users,ou=${project.name},cn=buildbot,ou=services,dc=immae,dc=eu - Include /var/secrets/buildbot/${project.name}/webhook-httpd-include - - - '') myconfig.env.buildbot.projects; - - system.activationScripts = lib.attrsets.mapAttrs' (k: project: lib.attrsets.nameValuePair "buildbot-${project.name}" { - deps = [ "users" "wrappers" ]; - text = project.activationScript; - }) myconfig.env.buildbot.projects; - - secrets.keys = ( - lib.lists.flatten ( - lib.attrsets.mapAttrsToList (k: project: - lib.attrsets.mapAttrsToList (k: v: - { - permissions = "0600"; - user = "buildbot"; - group = "buildbot"; - text = v; - dest = "buildbot/${project.name}/${k}"; - } - ) project.secrets - ++ [ - { - permissions = "0600"; - user = "wwwrun"; - group = "wwwrun"; - text = lib.optionalString (lib.attrsets.hasAttr "webhookTokens" project) '' - Require expr "req('Access-Key') in { ${builtins.concatStringsSep ", " (map (x: "'${x}'") project.webhookTokens)} }" - ''; - dest = "buildbot/${project.name}/webhook-httpd-include"; - } - ] - ) myconfig.env.buildbot.projects - ) - ) ++ [ - { - permissions = "0600"; - user = "buildbot"; - group = "buildbot"; - text = myconfig.env.buildbot.ldap.password; - dest = "buildbot/ldap"; - } - { - permissions = "0600"; - user = "buildbot"; - group = "buildbot"; - text = builtins.readFile "${myconfig.privateFiles}/buildbot_ssh_key"; - dest = "buildbot/ssh_key"; - } - ]; - - systemd.services = lib.attrsets.mapAttrs' (k: project: lib.attrsets.nameValuePair "buildbot-${project.name}" { - description = "Buildbot Continuous Integration Server ${project.name}."; - after = [ "network-online.target" ]; - wantedBy = [ "multi-user.target" ]; - path = project.packages pkgs ++ (project.pythonPackages buildbot.pythonModule pkgs); - preStart = let - master-cfg = "${buildbot_common}/${pkgs.python3.pythonForBuild.sitePackages}/buildbot_common/master.cfg"; - tac_file = pkgs.writeText "buildbot.tac" '' - import os - - from twisted.application import service - from buildbot.master import BuildMaster - - basedir = '${varDir}/${project.name}' - rotateLength = 10000000 - maxRotatedFiles = 10 - configfile = '${master-cfg}' - - # Default umask for server - umask = None - - # if this is a relocatable tac file, get the directory containing the TAC - if basedir == '.': - import os - basedir = os.path.abspath(os.path.dirname(__file__)) - - # note: this line is matched against to check that this is a buildmaster - # directory; do not edit it. - application = service.Application('buildmaster') - from twisted.python.logfile import LogFile - from twisted.python.log import ILogObserver, FileLogObserver - logfile = LogFile.fromFullPath(os.path.join(basedir, "twistd.log"), rotateLength=rotateLength, - maxRotatedFiles=maxRotatedFiles) - application.setComponent(ILogObserver, FileLogObserver(logfile).emit) - - m = BuildMaster(basedir, configfile, umask) - m.setServiceParent(application) - m.log_rotation.rotateLength = rotateLength - m.log_rotation.maxRotatedFiles = maxRotatedFiles - ''; - in '' - if [ ! -f ${varDir}/${project.name}/buildbot.tac ]; then - ${buildbot}/bin/buildbot create-master -c "${master-cfg}" "${varDir}/${project.name}" - rm -f ${varDir}/${project.name}/master.cfg.sample - rm -f ${varDir}/${project.name}/buildbot.tac - fi - ln -sf ${tac_file} ${varDir}/${project.name}/buildbot.tac - # different buildbots may be trying that simultaneously, add the || true to avoid complaining in case of race - install -Dm600 -o buildbot -g buildbot -T /var/secrets/buildbot/ssh_key ${varDir}/buildbot_key || true - buildbot_secrets=${varDir}/${project.name}/secrets - install -m 0700 -o buildbot -g buildbot -d $buildbot_secrets - install -Dm600 -o buildbot -g buildbot -T /var/secrets/buildbot/ldap $buildbot_secrets/ldap - ${builtins.concatStringsSep "\n" (lib.attrsets.mapAttrsToList - (k: v: "install -Dm600 -o buildbot -g buildbot -T /var/secrets/buildbot/${project.name}/${k} $buildbot_secrets/${k}") project.secrets - )} - ''; - environment = let - project_env = lib.attrsets.mapAttrs' (k: v: lib.attrsets.nameValuePair "BUILDBOT_${k}" v) project.environment; - buildbot_config = pkgs.python3Packages.buildPythonPackage (rec { - name = "buildbot_config-${project.name}"; - src = ./projects + "/${project.name}"; - format = "other"; - installPhase = '' - mkdir -p $out/${pkgs.python3.pythonForBuild.sitePackages} - cp -a $src $out/${pkgs.python3.pythonForBuild.sitePackages}/buildbot_config - ''; - }); - HOME = "${varDir}/${project.name}"; - PYTHONPATH = "${buildbot.pythonModule.withPackages (self: project.pythonPackages self pkgs ++ [ - pkgs.python3Packages.wokkel - pkgs.python3Packages.treq pkgs.python3Packages.ldap3 buildbot - pkgs.python3Packages.buildbot-worker - buildbot_common buildbot_config - ])}/${buildbot.pythonModule.sitePackages}${if project.pythonPathHome then ":${varDir}/${project.name}/.local/${pkgs.python3.pythonForBuild.sitePackages}" else ""}"; - in project_env // { inherit PYTHONPATH HOME; }; - - serviceConfig = { - Type = "forking"; - User = "buildbot"; - Group = "buildbot"; - RuntimeDirectory = "buildbot"; - RuntimeDirectoryPreserve = "yes"; - StateDirectory = "buildbot"; - SupplementaryGroups = "keys"; - WorkingDirectory = "${varDir}/${project.name}"; - ExecStart = "${buildbot}/bin/buildbot start"; - }; - }) myconfig.env.buildbot.projects; - }; -} diff --git a/nixops/modules/buildbot/projects/caldance/__init__.py b/nixops/modules/buildbot/projects/caldance/__init__.py deleted file mode 100644 index 2c0bad5..0000000 --- a/nixops/modules/buildbot/projects/caldance/__init__.py +++ /dev/null @@ -1,190 +0,0 @@ -from buildbot.plugins import * -from buildbot_common.build_helpers import * -import os -from buildbot.util import bytes2unicode -import json - -__all__ = [ "configure", "E" ] - -class E(): - PROJECT = "caldance" - BUILDBOT_URL = "https://git.immae.eu/buildbot/{}/".format(PROJECT) - SOCKET = "unix:/run/buildbot/{}.sock".format(PROJECT) - PB_SOCKET = "unix:address=/run/buildbot/{}_pb.sock".format(PROJECT) - RELEASE_PATH = "/var/lib/ftp/release.immae.eu/{}".format(PROJECT) - RELEASE_URL = "https://release.immae.eu/{}".format(PROJECT) - GIT_URL = "gitolite@git.immae.eu:perso/simon_descarpentries/www.cal-dance.com" - SSH_KEY_PATH = "/var/lib/buildbot/buildbot_key" - SSH_HOST_KEY = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIFbhFTl2A2RJn5L51yxJM4XfCS2ZaiSX/jo9jFSdghF" - LDAP_HOST = "ldap.immae.eu" - LDAP_DN = "cn=buildbot,ou=services,dc=immae,dc=eu" - LDAP_ROLES_BASE = "ou=roles,ou=hosts,dc=immae,dc=eu" - XMPP_RECIPIENTS = os.environ["BUILDBOT_XMPP_RECIPIENTS"].split(" ") - - PUPPET_HOST = { - "integration": "root@caldance.immae.eu", - } - - # master.cfg - SECRETS_FILE = os.getcwd() + "/secrets" - LDAP_URL = "ldaps://ldap.immae.eu:636" - LDAP_ADMIN_USER = "cn=buildbot,ou=services,dc=immae,dc=eu" - LDAP_BASE = "dc=immae,dc=eu" - LDAP_PATTERN = "(uid=%(username)s)" - LDAP_GROUP_PATTERN = "(&(memberOf=cn=groups,ou=caldance,cn=buildbot,ou=services,dc=immae,dc=eu)(member=%(dn)s))" - TITLE_URL = "https://caldance.immae.eu" - TITLE = "Caldance" - -class CustomBase(webhooks.base): - def getChanges(self, request): - try: - content = request.content.read() - args = json.loads(bytes2unicode(content)) - except Exception as e: - raise ValueError("Error loading JSON: " + str(e)) - - args.setdefault("comments", "") - args.setdefault("repository", "") - args.setdefault("author", args.get("who", "unknown")) - - if args["category"] == "deploy_webhook": - args = { - "category": "deploy_webhook", - "comments": "", - "repository": "", - "author": "webhook", - "project": "Caldance", - "properties": { - "environment": args.get("environment", "integration"), - "build": "caldance_{}.tar.gz".format(args.get("build", "master")) - } - } - - return ([args], None) - -def deploy_hook_scheduler(project, timer=1): - return schedulers.AnyBranchScheduler( - change_filter=util.ChangeFilter(category="deploy_webhook", project=project), - name="{}_deploy".format(project), treeStableTimer=timer, builderNames=["{}_deploy".format(project)]) - -def configure(c): - c["buildbotURL"] = E.BUILDBOT_URL - c["www"]["port"] = E.SOCKET - - c["www"]["change_hook_dialects"]["base"] = { - "custom_class": CustomBase - } - c['workers'].append(worker.LocalWorker("generic-worker")) - c['workers'].append(worker.LocalWorker("deploy-worker")) - - c['schedulers'].append(hook_scheduler("Caldance", timer=1)) - c['schedulers'].append(force_scheduler("force_caldance", ["Caldance_build"])) - c['schedulers'].append(deploy_scheduler("deploy_caldance", ["Caldance_deploy"])) - c['schedulers'].append(deploy_hook_scheduler("Caldance", timer=1)) - - c['builders'].append(factory("caldance")) - - c['builders'].append(deploy_factory("caldance")) - - c['services'].append(SlackStatusPush( - name="slack_status_caldance", - builders=["Caldance_build", "Caldance_deploy"], - serverUrl=open(E.SECRETS_FILE + "/slack_webhook", "r").read().rstrip())) - c['services'].append(XMPPStatusPush( - name="xmpp_status_caldance", - builders=["Caldance_build", "Caldance_deploy"], - recipients=E.XMPP_RECIPIENTS, - password=open(E.SECRETS_FILE + "/notify_xmpp_password", "r").read().rstrip())) - -def factory(project, ignore_fails=False): - release_file = "{1}/{0}_%(kw:clean_branch)s.tar.gz" - - package = util.Interpolate("{0}_%(kw:clean_branch)s.tar.gz".format(project), clean_branch=clean_branch) - package_dest = util.Interpolate(release_file.format(project, E.RELEASE_PATH), clean_branch=clean_branch) - package_url = util.Interpolate(release_file.format(project, E.RELEASE_URL), clean_branch=clean_branch) - - factory = util.BuildFactory() - factory.addStep(steps.Git(logEnviron=False, repourl=E.GIT_URL, - sshPrivateKey=open(E.SSH_KEY_PATH).read().rstrip(), - sshHostKey=E.SSH_HOST_KEY, mode="full", method="copy")) - factory.addSteps(package_and_upload(package, package_dest, package_url)) - - return util.BuilderConfig( - name="{}_build".format(project.capitalize()), - workernames=["generic-worker"], factory=factory) - -def compute_build_infos(project): - @util.renderer - def compute(props): - import re, hashlib - build_file = props.getProperty("build") - package_dest = "{1}/{0}".format(build_file, E.RELEASE_PATH) - version = re.match(r"{0}_(.*).tar.gz".format(project), build_file).group(1) - with open(package_dest, "rb") as f: - sha = hashlib.sha256(f.read()).hexdigest() - return { - "build_version": version, - "build_hash": sha, - } - return compute - -@util.renderer -def puppet_host(props): - environment = props["environment"] if props.hasProperty("environment") else "integration" - return E.PUPPET_HOST.get(environment, "host.invalid") - -def deploy_factory(project): - package_dest = util.Interpolate("{0}/%(prop:build)s".format(E.RELEASE_PATH)) - - factory = util.BuildFactory() - factory.addStep(steps.MasterShellCommand(command=["test", "-f", package_dest])) - factory.addStep(steps.SetProperties(properties=compute_build_infos(project))) - factory.addStep(LdapPush(environment=util.Property("environment"), - project=project, build_version=util.Property("build_version"), - build_hash=util.Property("build_hash"), ldap_password=util.Secret("ldap"))) - factory.addStep(steps.MasterShellCommand(command=[ - "ssh", "-o", "UserKnownHostsFile=/dev/null", "-o", "StrictHostKeyChecking=no", "-o", "CheckHostIP=no", "-i", E.SSH_KEY_PATH, puppet_host])) - return util.BuilderConfig(name="{}_deploy".format(project.capitalize()), workernames=["deploy-worker"], factory=factory) - -from twisted.internet import defer -from buildbot.process.buildstep import FAILURE -from buildbot.process.buildstep import SUCCESS -from buildbot.process.buildstep import BuildStep - -class LdapPush(BuildStep): - name = "LdapPush" - renderables = ["environment", "project", "build_version", "build_hash", "ldap_password"] - - def __init__(self, **kwargs): - self.environment = kwargs.pop("environment") - self.project = kwargs.pop("project") - self.build_version = kwargs.pop("build_version") - self.build_hash = kwargs.pop("build_hash") - self.ldap_password = kwargs.pop("ldap_password") - self.ldap_host = kwargs.pop("ldap_host", E.LDAP_HOST) - super().__init__(**kwargs) - - def run(self): - import json - from ldap3 import Reader, Writer, Server, Connection, ObjectDef - server = Server(self.ldap_host) - conn = Connection(server, - user=E.LDAP_DN, - password=self.ldap_password) - conn.bind() - obj = ObjectDef("immaePuppetClass", conn) - r = Reader(conn, obj, - "cn=caldance.{},{}".format(self.environment, E.LDAP_ROLES_BASE)) - r.search() - if len(r) > 0: - w = Writer.from_cursor(r) - for value in w[0].immaePuppetJson.values: - config = json.loads(value) - if "role::caldance::{}_version".format(self.project) in config: - config["role::caldance::{}_version".format(self.project)] = self.build_version - config["role::caldance::{}_sha256".format(self.project)] = self.build_hash - w[0].immaePuppetJson -= value - w[0].immaePuppetJson += json.dumps(config, indent=" ") - w.commit() - return defer.succeed(SUCCESS) - return defer.succeed(FAILURE) diff --git a/nixops/modules/buildbot/projects/cryptoportfolio/__init__.py b/nixops/modules/buildbot/projects/cryptoportfolio/__init__.py deleted file mode 100644 index 5d70f95..0000000 --- a/nixops/modules/buildbot/projects/cryptoportfolio/__init__.py +++ /dev/null @@ -1,169 +0,0 @@ -from buildbot.plugins import * -from buildbot_common.build_helpers import * -import os - -__all__ = [ "configure", "E" ] - -class E(): - PROJECT = "cryptoportfolio" - BUILDBOT_URL = "https://git.immae.eu/buildbot/{}/".format(PROJECT) - SOCKET = "unix:/run/buildbot/{}.sock".format(PROJECT) - PB_SOCKET = "unix:address=/run/buildbot/{}_pb.sock".format(PROJECT) - RELEASE_PATH = "/var/lib/ftp/release.immae.eu/{}".format(PROJECT) - RELEASE_URL = "https://release.immae.eu/{}".format(PROJECT) - GIT_URL = "https://git.immae.eu/perso/Immae/Projets/Cryptomonnaies/Cryptoportfolio/{0}.git" - SSH_KEY_PATH = "/var/lib/buildbot/buildbot_key" - LDAP_HOST = "ldap.immae.eu" - LDAP_DN = "cn=buildbot,ou=services,dc=immae,dc=eu" - LDAP_ROLES_BASE = "ou=roles,ou=hosts,dc=immae,dc=eu" - - PUPPET_HOST = { - "production": "root@cryptoportfolio.immae.eu", - "integration": "root@cryptoportfolio-dev.immae.eu" - } - - # master.cfg - SECRETS_FILE = os.getcwd() + "/secrets" - LDAP_URL = "ldaps://ldap.immae.eu:636" - LDAP_ADMIN_USER = "cn=buildbot,ou=services,dc=immae,dc=eu" - LDAP_BASE = "dc=immae,dc=eu" - LDAP_PATTERN = "(uid=%(username)s)" - LDAP_GROUP_PATTERN = "(&(memberOf=cn=groups,ou=cryptoportfolio,cn=buildbot,ou=services,dc=immae,dc=eu)(member=%(dn)s))" - TITLE_URL = "https://git.immae.eu" - TITLE = "Cryptoportfolio" - -# eval .. dans .zshrc_local -# mkdir -p $BUILD/go -# export GOPATH=$BUILD/go -# go get -u github.com/golang/dep/cmd/dep -# export PATH=$PATH:$BUILD/go/bin -# go get git.immae.eu/Cryptoportfolio/Front.git -# cd $BUILD/go/src/git.immae.eu/Cryptoportfolio/Front.git -# git checkout dev -# dep ensure -def configure(c): - c["buildbotURL"] = E.BUILDBOT_URL - c["www"]["port"] = E.SOCKET - - c['workers'].append(worker.LocalWorker("generic-worker")) - c['workers'].append(worker.LocalWorker("deploy-worker")) - - c['schedulers'].append(hook_scheduler("Trader")) - c['schedulers'].append(hook_scheduler("Front")) - c['schedulers'].append(force_scheduler( - "force_cryptoportfolio", ["Trader_build", "Front_build"])) - c['schedulers'].append(deploy_scheduler("deploy_cryptoportfolio", - ["Trader_deploy", "Front_deploy"])) - - c['builders'].append(factory("trader")) - c['builders'].append(factory("front", ignore_fails=True)) - - c['builders'].append(deploy_factory("trader")) - c['builders'].append(deploy_factory("front")) - - c['services'].append(SlackStatusPush( - name="slack_status_cryptoportfolio", - builders=["Front_build", "Trader_build", "Front_deploy", "Trader_deploy"], - serverUrl=open(E.SECRETS_FILE + "/slack_webhook", "r").read().rstrip())) - -def factory(project, ignore_fails=False): - release_file = "{1}/{0}/{0}_%(kw:clean_branch)s.tar.gz" - - url = E.GIT_URL.format(project.capitalize()) - - package = util.Interpolate("{0}_%(kw:clean_branch)s.tar.gz".format(project), clean_branch=clean_branch) - package_dest = util.Interpolate(release_file.format(project, E.RELEASE_PATH), clean_branch=clean_branch) - package_url = util.Interpolate(release_file.format(project, E.RELEASE_URL), clean_branch=clean_branch) - - factory = util.BuildFactory() - factory.addStep(steps.Git(logEnviron=False, repourl=url, - mode="full", method="copy")) - factory.addStep(steps.ShellCommand(name="make install", - logEnviron=False, haltOnFailure=(not ignore_fails), - warnOnFailure=ignore_fails, flunkOnFailure=(not ignore_fails), - command=["make", "install"])) - factory.addStep(steps.ShellCommand(name="make test", - logEnviron=False, haltOnFailure=(not ignore_fails), - warnOnFailure=ignore_fails, flunkOnFailure=(not ignore_fails), - command=["make", "test"])) - factory.addSteps(package_and_upload(package, package_dest, package_url)) - - return util.BuilderConfig( - name="{}_build".format(project.capitalize()), - workernames=["generic-worker"], factory=factory) - -def compute_build_infos(project): - @util.renderer - def compute(props): - import re, hashlib - build_file = props.getProperty("build") - package_dest = "{2}/{0}/{1}".format(project, build_file, E.RELEASE_PATH) - version = re.match(r"{0}_(.*).tar.gz".format(project), build_file).group(1) - with open(package_dest, "rb") as f: - sha = hashlib.sha256(f.read()).hexdigest() - return { - "build_version": version, - "build_hash": sha, - } - return compute - -@util.renderer -def puppet_host(props): - environment = props["environment"] if props.hasProperty("environment") else "integration" - return E.PUPPET_HOST.get(environment, "host.invalid") - -def deploy_factory(project): - package_dest = util.Interpolate("{1}/{0}/%(prop:build)s".format(project, E.RELEASE_PATH)) - - factory = util.BuildFactory() - factory.addStep(steps.MasterShellCommand(command=["test", "-f", package_dest])) - factory.addStep(steps.SetProperties(properties=compute_build_infos(project))) - factory.addStep(LdapPush(environment=util.Property("environment"), - project=project, build_version=util.Property("build_version"), - build_hash=util.Property("build_hash"), ldap_password=util.Secret("ldap"))) - factory.addStep(steps.MasterShellCommand(command=[ - "ssh", "-o", "UserKnownHostsFile=/dev/null", "-o", "StrictHostKeyChecking=no", "-o", "CheckHostIP=no", "-i", E.SSH_KEY_PATH, puppet_host])) - return util.BuilderConfig(name="{}_deploy".format(project.capitalize()), workernames=["deploy-worker"], factory=factory) - -from twisted.internet import defer -from buildbot.process.buildstep import FAILURE -from buildbot.process.buildstep import SUCCESS -from buildbot.process.buildstep import BuildStep - -class LdapPush(BuildStep): - name = "LdapPush" - renderables = ["environment", "project", "build_version", "build_hash", "ldap_password"] - - def __init__(self, **kwargs): - self.environment = kwargs.pop("environment") - self.project = kwargs.pop("project") - self.build_version = kwargs.pop("build_version") - self.build_hash = kwargs.pop("build_hash") - self.ldap_password = kwargs.pop("ldap_password") - self.ldap_host = kwargs.pop("ldap_host", E.LDAP_HOST) - super().__init__(**kwargs) - - def run(self): - import json - from ldap3 import Reader, Writer, Server, Connection, ObjectDef - server = Server(self.ldap_host) - conn = Connection(server, - user=E.LDAP_DN, - password=self.ldap_password) - conn.bind() - obj = ObjectDef("immaePuppetClass", conn) - r = Reader(conn, obj, - "cn=cryptoportfolio.{},{}".format(self.environment, E.LDAP_ROLES_BASE)) - r.search() - if len(r) > 0: - w = Writer.from_cursor(r) - for value in w[0].immaePuppetJson.values: - config = json.loads(value) - if "role::cryptoportfolio::{}_version".format(self.project) in config: - config["role::cryptoportfolio::{}_version".format(self.project)] = self.build_version - config["role::cryptoportfolio::{}_sha256".format(self.project)] = self.build_hash - w[0].immaePuppetJson -= value - w[0].immaePuppetJson += json.dumps(config, indent=" ") - w.commit() - return defer.succeed(SUCCESS) - return defer.succeed(FAILURE) diff --git a/nixops/modules/buildbot/projects/test/__init__.py b/nixops/modules/buildbot/projects/test/__init__.py deleted file mode 100644 index e6b8d51..0000000 --- a/nixops/modules/buildbot/projects/test/__init__.py +++ /dev/null @@ -1,188 +0,0 @@ -from buildbot.plugins import * -from buildbot_common.build_helpers import * -import os -from buildbot.util import bytes2unicode -import json - -__all__ = [ "configure", "E" ] - -class E(): - PROJECT = "test" - BUILDBOT_URL = "https://git.immae.eu/buildbot/{}/".format(PROJECT) - SOCKET = "unix:/run/buildbot/{}.sock".format(PROJECT) - PB_SOCKET = "unix:address=/run/buildbot/{}_pb.sock".format(PROJECT) - RELEASE_PATH = "/var/lib/ftp/release.immae.eu/{}".format(PROJECT) - RELEASE_URL = "https://release.immae.eu/{}".format(PROJECT) - GIT_URL = "https://git.immae.eu/perso/Immae/TestProject.git" - SSH_KEY_PATH = "/var/lib/buildbot/buildbot_key" - PUPPET_HOST = "root@backup-1.v.immae.eu" - LDAP_HOST = "ldap.immae.eu" - LDAP_DN = "cn=buildbot,ou=services,dc=immae,dc=eu" - LDAP_ROLES_BASE = "ou=roles,ou=hosts,dc=immae,dc=eu" - XMPP_RECIPIENTS = os.environ["BUILDBOT_XMPP_RECIPIENTS"].split(" ") - - # master.cfg - SECRETS_FILE = os.getcwd() + "/secrets" - LDAP_URL = "ldaps://ldap.immae.eu:636" - LDAP_ADMIN_USER = "cn=buildbot,ou=services,dc=immae,dc=eu" - LDAP_BASE = "dc=immae,dc=eu" - LDAP_PATTERN = "(uid=%(username)s)" - LDAP_GROUP_PATTERN = "(&(memberOf=cn=groups,ou=test,cn=buildbot,ou=services,dc=immae,dc=eu)(member=%(dn)s))" - TITLE_URL = "https://git.immae.eu/?p=perso/Immae/TestProject.git;a=summary" - TITLE = "Test project" - -class CustomBase(webhooks.base): - def getChanges(self, request): - try: - content = request.content.read() - args = json.loads(bytes2unicode(content)) - except Exception as e: - raise ValueError("Error loading JSON: " + str(e)) - - args.setdefault("comments", "") - args.setdefault("repository", "") - args.setdefault("author", args.get("who", "unknown")) - - if args["category"] == "deploy_webhook": - args = { - "category": "deploy_webhook", - "comments": "", - "repository": "", - "author": "unknown", - "project": "TestProject", - "properties": { - "environment": args.get("environment", "integration"), - "build": "test_{}.tar.gz".format(args.get("branch", "master")) - } - } - - return ([args], None) - -def deploy_hook_scheduler(project, timer=1): - return schedulers.AnyBranchScheduler( - change_filter=util.ChangeFilter(category="deploy_webhook", project=project), - name="{}_deploy".format(project), treeStableTimer=timer, builderNames=["{}_deploy".format(project)]) - -def configure(c): - c["buildbotURL"] = E.BUILDBOT_URL - c["www"]["port"] = E.SOCKET - - c["www"]["change_hook_dialects"]["base"] = { - "custom_class": CustomBase - } - c['workers'].append(worker.LocalWorker("generic-worker-test")) - c['workers'].append(worker.LocalWorker("deploy-worker-test")) - - c['schedulers'].append(hook_scheduler("TestProject", timer=1)) - c['schedulers'].append(force_scheduler("force_test", ["TestProject_build"])) - c['schedulers'].append(deploy_scheduler("deploy_test", ["TestProject_deploy"])) - c['schedulers'].append(deploy_hook_scheduler("TestProject", timer=1)) - - c['builders'].append(factory()) - c['builders'].append(deploy_factory()) - - c['services'].append(SlackStatusPush( - name="slack_status_test_project", - builders=["TestProject_build", "TestProject_deploy"], - serverUrl=open(E.SECRETS_FILE + "/slack_webhook", "r").read().rstrip())) - c['services'].append(XMPPStatusPush( - name="xmpp_status_test_project", - builders=["TestProject_build", "TestProject_deploy"], - recipients=E.XMPP_RECIPIENTS, - password=open(E.SECRETS_FILE + "/notify_xmpp_password", "r").read().rstrip())) - -def factory(): - package = util.Interpolate("test_%(kw:clean_branch)s.tar.gz", clean_branch=clean_branch) - package_dest = util.Interpolate("{}/test_%(kw:clean_branch)s.tar.gz".format(E.RELEASE_PATH), clean_branch=clean_branch) - package_url = util.Interpolate("{}/test_%(kw:clean_branch)s.tar.gz".format(E.RELEASE_URL), clean_branch=clean_branch) - - factory = util.BuildFactory() - factory.addStep(steps.Git(logEnviron=False, - repourl=E.GIT_URL, mode="full", method="copy")) - factory.addStep(steps.ShellCommand(name="env", - logEnviron=False, command=["env"])) - factory.addStep(steps.ShellCommand(name="pwd", - logEnviron=False, command=["pwd"])) - factory.addStep(steps.ShellCommand(name="true", - logEnviron=False, command=["true"])) - factory.addStep(steps.ShellCommand(name="echo", - logEnviron=False, command=["echo", package])) - factory.addSteps(package_and_upload(package, package_dest, package_url)) - - return util.BuilderConfig(name="TestProject_build", workernames=["generic-worker-test"], factory=factory) - - -def compute_build_infos(): - @util.renderer - def compute(props): - import re, hashlib - build_file = props.getProperty("build") - package_dest = "{}/{}".format(E.RELEASE_PATH, build_file) - version = re.match(r"{0}_(.*).tar.gz".format("test"), build_file).group(1) - with open(package_dest, "rb") as f: - sha = hashlib.sha256(f.read()).hexdigest() - return { - "build_version": version, - "build_hash": sha, - } - return compute - -@util.renderer -def puppet_host(props): - return E.PUPPET_HOST - -def deploy_factory(): - package_dest = util.Interpolate("{}/%(prop:build)s".format(E.RELEASE_PATH)) - - factory = util.BuildFactory() - factory.addStep(steps.MasterShellCommand(command=["test", "-f", package_dest])) - factory.addStep(steps.SetProperties(properties=compute_build_infos())) - factory.addStep(LdapPush(environment=util.Property("environment"), - build_version=util.Property("build_version"), - build_hash=util.Property("build_hash"), - ldap_password=util.Secret("ldap"))) - factory.addStep(steps.MasterShellCommand(command=[ - "ssh", "-o", "UserKnownHostsFile=/dev/null", "-o", "StrictHostKeyChecking=no", "-o", "CheckHostIP=no", "-i", E.SSH_KEY_PATH, puppet_host])) - return util.BuilderConfig(name="TestProject_deploy", workernames=["deploy-worker-test"], factory=factory) - -from twisted.internet import defer -from buildbot.process.buildstep import FAILURE -from buildbot.process.buildstep import SUCCESS -from buildbot.process.buildstep import BuildStep - -class LdapPush(BuildStep): - name = "LdapPush" - renderables = ["environment", "build_version", "build_hash", "ldap_password"] - - def __init__(self, **kwargs): - self.environment = kwargs.pop("environment") - self.build_version = kwargs.pop("build_version") - self.build_hash = kwargs.pop("build_hash") - self.ldap_password = kwargs.pop("ldap_password") - self.ldap_host = kwargs.pop("ldap_host", E.LDAP_HOST) - super().__init__(**kwargs) - - def run(self): - import json - from ldap3 import Reader, Writer, Server, Connection, ObjectDef - server = Server(self.ldap_host) - conn = Connection(server, - user=E.LDAP_DN, - password=self.ldap_password) - conn.bind() - obj = ObjectDef("immaePuppetClass", conn) - r = Reader(conn, obj, - "cn=test.{},{}".format(self.environment, E.LDAP_ROLES_BASE)) - r.search() - if len(r) > 0: - w = Writer.from_cursor(r) - for value in w[0].immaePuppetJson.values: - config = json.loads(value) - if "test_version" in config: - config["test_version"] = self.build_version - config["test_sha256"] = self.build_hash - w[0].immaePuppetJson -= value - w[0].immaePuppetJson += json.dumps(config, indent=" ") - w.commit() - return defer.succeed(SUCCESS) - return defer.succeed(FAILURE) diff --git a/nixops/modules/certificates.nix b/nixops/modules/certificates.nix deleted file mode 100644 index 43f6a23..0000000 --- a/nixops/modules/certificates.nix +++ /dev/null @@ -1,52 +0,0 @@ -{ lib, pkgs, config, ... }: -{ - options.services.myCertificates = { - certConfig = lib.mkOption { - default = { - webroot = "${config.security.acme.directory}/acme-challenge"; - email = "ismael@bouya.org"; - postRun = '' - systemctl reload httpdTools.service httpdInte.service httpdProd.service - ''; - plugins = [ "cert.pem" "chain.pem" "fullchain.pem" "full.pem" "key.pem" "account_key.json" ]; - }; - description = "Default configuration for certificates"; - }; - }; - - config = { - services.websitesCerts = config.services.myCertificates.certConfig; - myServices.databasesCerts = config.services.myCertificates.certConfig; - myServices.ircCerts = config.services.myCertificates.certConfig; - - security.acme.preliminarySelfsigned = true; - - security.acme.certs = { - "eldiron" = config.services.myCertificates.certConfig // { - domain = "eldiron.immae.eu"; - }; - }; - - systemd.services = lib.attrsets.mapAttrs' (k: v: - lib.attrsets.nameValuePair "acme-selfsigned-${k}" (lib.mkBefore { script = - (lib.optionalString (builtins.elem "cert.pem" v.plugins) '' - cp $workdir/server.crt ${config.security.acme.directory}/${k}/cert.pem - chown '${v.user}:${v.group}' ${config.security.acme.directory}/${k}/cert.pem - chmod ${if v.allowKeysForGroup then "750" else "700"} ${config.security.acme.directory}/${k}/cert.pem - '') + - (lib.optionalString (builtins.elem "chain.pem" v.plugins) '' - cp $workdir/ca.crt ${config.security.acme.directory}/${k}/chain.pem - chown '${v.user}:${v.group}' ${config.security.acme.directory}/${k}/chain.pem - chmod ${if v.allowKeysForGroup then "750" else "700"} ${config.security.acme.directory}/${k}/chain.pem - '') - ; }) - ) config.security.acme.certs // { - httpdProd.after = [ "acme-selfsigned-certificates.target" ]; - httpdProd.wants = [ "acme-selfsigned-certificates.target" ]; - httpdTools.after = [ "acme-selfsigned-certificates.target" ]; - httpdTools.wants = [ "acme-selfsigned-certificates.target" ]; - httpdInte.after = [ "acme-selfsigned-certificates.target" ]; - httpdInte.wants = [ "acme-selfsigned-certificates.target" ]; - }; - }; -} diff --git a/nixops/modules/dns.nix b/nixops/modules/dns.nix deleted file mode 100644 index ced8d9b..0000000 --- a/nixops/modules/dns.nix +++ /dev/null @@ -1,132 +0,0 @@ -{ lib, pkgs, config, myconfig, ... }: -{ - config = let - cfg = config.services.bind; - configFile = pkgs.writeText "named.conf" '' - include "/etc/bind/rndc.key"; - controls { - inet 127.0.0.1 allow {localhost;} keys {"rndc-key";}; - }; - - acl cachenetworks { ${lib.concatMapStrings (entry: " ${entry}; ") cfg.cacheNetworks} }; - acl badnetworks { ${lib.concatMapStrings (entry: " ${entry}; ") cfg.blockedNetworks} }; - - options { - listen-on { ${lib.concatMapStrings (entry: " ${entry}; ") cfg.listenOn} }; - listen-on-v6 { ${lib.concatMapStrings (entry: " ${entry}; ") cfg.listenOnIpv6} }; - allow-query { cachenetworks; }; - blackhole { badnetworks; }; - forward first; - forwarders { ${lib.concatMapStrings (entry: " ${entry}; ") cfg.forwarders} }; - directory "/var/run/named"; - pid-file "/var/run/named/named.pid"; - ${cfg.extraOptions} - }; - - ${cfg.extraConfig} - - ${ lib.concatMapStrings - ({ name, file, master ? true, extra ? "", slaves ? [], masters ? [] }: - '' - zone "${name}" { - type ${if master then "master" else "slave"}; - file "${file}"; - ${ if lib.lists.length slaves > 0 then - '' - allow-transfer { - ${lib.concatMapStrings (ip: "${ip};\n") slaves} - }; - '' else ""} - ${ if lib.lists.length masters > 0 then - '' - masters { - ${lib.concatMapStrings (ip: "${ip};\n") masters} - }; - '' else ""} - allow-query { any; }; - ${extra} - }; - '') - cfg.zones } - ''; - in - { - networking.firewall.allowedUDPPorts = [ 53 ]; - networking.firewall.allowedTCPPorts = [ 53 ]; - services.bind = { - enable = true; - cacheNetworks = ["any"]; - configFile = configFile; - extraOptions = '' - allow-recursion { 127.0.0.1; }; - allow-transfer { none; }; - - notify-source ${myconfig.env.servers.eldiron.ips.main.ip4}; - notify-source-v6 ${lib.head myconfig.env.servers.eldiron.ips.main.ip6}; - version none; - hostname none; - server-id none; - ''; - zones = with myconfig.env.dns; - assert (builtins.substring ((builtins.stringLength soa.email)-1) 1 soa.email) != "."; - assert (builtins.substring ((builtins.stringLength soa.primary)-1) 1 soa.primary) != "."; - (map (conf: { - name = conf.name; - master = false; - file = "/var/run/named/${conf.name}.zone"; - masters = if lib.attrsets.hasAttr "masters" conf - then lib.lists.flatten (map (n: lib.attrsets.attrValues ns.${n}) conf.masters) - else []; - }) slaveZones) - ++ (map (conf: { - name = conf.name; - master = true; - extra = if lib.attrsets.hasAttr "extra" conf then conf.extra else ""; - slaves = if lib.attrsets.hasAttr "slaves" conf - then lib.lists.flatten (map (n: lib.attrsets.attrValues ns.${n}) conf.slaves) - else []; - file = pkgs.writeText "${conf.name}.zone" '' - $TTL 10800 - @ IN SOA ${soa.primary}. ${builtins.replaceStrings ["@"] ["."] soa.email}. ${soa.serial} ${soa.refresh} ${soa.retry} ${soa.expire} ${soa.ttl} - - ${lib.concatStringsSep "\n" (map (x: "@ IN NS ${x}.") (lib.concatMap (n: lib.attrsets.mapAttrsToList (k: v: k) ns.${n}) conf.ns))} - - ${conf.entries} - - ${if lib.attrsets.hasAttr "withEmail" conf && lib.lists.length conf.withEmail > 0 then '' - mail IN A ${myconfig.env.servers.immaeEu.ips.main.ip4} - mx-1 IN A ${myconfig.env.servers.eldiron.ips.main.ip4} - ${builtins.concatStringsSep "\n" (map (i: "mail IN AAAA ${i}") myconfig.env.servers.immaeEu.ips.main.ip6)} - ${builtins.concatStringsSep "\n" (map (i: "mx-1 IN AAAA ${i}") myconfig.env.servers.eldiron.ips.main.ip6)} - ${lib.concatStringsSep "\n\n" (map (e: - let - n = if e.domain == "" then "@" else "${e.domain} "; - suffix = if e.domain == "" then "" else ".${e.domain}"; - in - '' - ; ------------------ mail: ${n} --------------------------- - ${if e.receive then "${n} IN MX 10 mail.${conf.name}." else ""} - ;${if e.receive then "${n} IN MX 50 mx-1.${conf.name}." else ""} - - ; Mail sender authentications - ${n} IN TXT "v=spf1 mx ~all" - _dmarc${suffix} IN TXT "v=DMARC1; p=none; adkim=r; aspf=r; fo=1; rua=mailto:postmaster+rua@immae.eu; ruf=mailto:postmaster+ruf@immae.eu;" - ${if e.send then '' - immae_eu._domainkey${suffix} IN TXT ( "v=DKIM1; k=rsa; s=email; " - "p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzl3vLd8W5YAuumC5+ZT9OV7/14Pmh5JYtwyqKI3cfe9NnAqInt3xO4bZ7oqIxRKWN4SD39vm7O/QOvFdBt00ENOOzdP90s5gKw6eIP/4+vPTh0IWltAsmu9B2agzdtWUE7t2xFKIzEn8l9niRE2QYbVaqZv4sub98vY55fIgFoHtjkmNC7325S8fjDJGp6OPbyhAs6Xl5/adjF" - "0ko4Y2p6RaxLQfjlS0bxmK4Qg6C14pIXHtzVeqOuWrwApqt5+AULSn97iUtqV/IJlEEjC6DUR44t3C/G0G/k46iFclCqRRi0hdPrOHCtZDbtMubnTN9eaUiNpkXh1WnCflHwtjQwIDAQAB" ) - '' else ""} - '') conf.withEmail)} - '' + (if conf.name == "immae.eu" then '' - ; ----------------- Accept DMARC reports ------------------- - ${lib.concatStringsSep "\n" ( - lib.flatten ( - map (z: map (e: "${e.domain}${if builtins.stringLength e.domain > 0 then "." else ""}${z.name}._report._dmarc IN TXT \"v=DMARC1;\"") (z.withEmail or [])) masterZones - ) - )} - '' else "") else ""} - ''; - }) masterZones); - }; - }; -} diff --git a/nixops/modules/ftp.nix b/nixops/modules/ftp.nix deleted file mode 100644 index 842d2d6..0000000 --- a/nixops/modules/ftp.nix +++ /dev/null @@ -1,118 +0,0 @@ -{ lib, pkgs, config, myconfig, ... }: -{ - options = { - services.pure-ftpd.enable = lib.mkOption { - type = lib.types.bool; - default = false; - description = '' - Whether to enable pure-ftpd. - ''; - }; - }; - - config = lib.mkIf config.services.pure-ftpd.enable { - security.acme.certs."ftp" = config.services.myCertificates.certConfig // { - domain = "eldiron.immae.eu"; - postRun = '' - systemctl restart pure-ftpd.service - ''; - extraDomains = { "ftp.immae.eu" = null; }; - }; - - networking = { - firewall = { - allowedTCPPorts = [ 21 ]; - allowedTCPPortRanges = [ { from = 40000; to = 50000; } ]; - }; - }; - - users.users = [ - { - name = "ftp"; - uid = config.ids.uids.ftp; # 8 - group = "ftp"; - description = "Anonymous FTP user"; - home = "/homeless-shelter"; - extraGroups = [ "keys" ]; - } - ]; - - users.groups.ftp.gid = config.ids.gids.ftp; - - system.activationScripts.pure-ftpd = '' - install -m 0755 -o ftp -g ftp -d /var/lib/ftp - ''; - - secrets.keys = [{ - dest = "pure-ftpd-ldap"; - permissions = "0400"; - user = "ftp"; - group = "ftp"; - text = '' - LDAPServer ${myconfig.env.ftp.ldap.host} - LDAPPort 389 - LDAPUseTLS True - LDAPBaseDN ${myconfig.env.ftp.ldap.base} - LDAPBindDN ${myconfig.env.ftp.ldap.dn} - LDAPBindPW ${myconfig.env.ftp.ldap.password} - LDAPDefaultUID 500 - LDAPForceDefaultUID False - LDAPDefaultGID 100 - LDAPForceDefaultGID False - LDAPFilter ${myconfig.env.ftp.ldap.filter} - - LDAPAuthMethod BIND - - # Pas de possibilite de donner l'Uid/Gid ! - # Compile dans pure-ftpd directement avec immaeFtpUid / immaeFtpGid - LDAPHomeDir immaeFtpDirectory - ''; - }]; - - systemd.services.pure-ftpd = let - configFile = pkgs.writeText "pure-ftpd.conf" '' - PassivePortRange 40000 50000 - ChrootEveryone yes - CreateHomeDir yes - BrokenClientsCompatibility yes - MaxClientsNumber 50 - Daemonize yes - MaxClientsPerIP 8 - VerboseLog no - DisplayDotFiles yes - AnonymousOnly no - NoAnonymous no - SyslogFacility ftp - DontResolve yes - MaxIdleTime 15 - LDAPConfigFile /var/secrets/pure-ftpd-ldap - LimitRecursion 10000 8 - AnonymousCanCreateDirs no - MaxLoad 4 - AntiWarez yes - Umask 133:022 - # ftp - MinUID 8 - AllowUserFXP no - AllowAnonymousFXP no - ProhibitDotFilesWrite no - ProhibitDotFilesRead no - AutoRename no - AnonymousCantUpload no - MaxDiskUsage 99 - CustomerProof yes - TLS 1 - CertFile ${config.security.acme.directory}/ftp/full.pem - ''; - in { - description = "Pure-FTPd server"; - wantedBy = [ "multi-user.target" ]; - after = [ "network.target" ]; - - serviceConfig.ExecStart = "${pkgs.pure-ftpd}/bin/pure-ftpd ${configFile}"; - serviceConfig.Type = "forking"; - serviceConfig.PIDFile = "/run/pure-ftpd.pid"; - }; - }; - -} diff --git a/nixops/modules/gitolite/default.nix b/nixops/modules/gitolite/default.nix deleted file mode 100644 index f085b55..0000000 --- a/nixops/modules/gitolite/default.nix +++ /dev/null @@ -1,63 +0,0 @@ -{ lib, pkgs, config, myconfig, ... }: -let - cfg = config.services.myGitolite; -in { - options.services.myGitolite = { - enable = lib.mkEnableOption "my gitolite service"; - gitoliteDir = lib.mkOption { - type = lib.types.string; - default = "/var/lib/gitolite"; - }; - }; - - config = lib.mkIf cfg.enable { - networking.firewall.allowedTCPPorts = [ 9418 ]; - - services.gitDaemon = { - enable = true; - user = "gitolite"; - group = "gitolite"; - basePath = "${cfg.gitoliteDir}/repositories"; - }; - - system.activationScripts.gitolite = let - gitolite_ldap_groups = pkgs.mylibs.wrap { - name = "gitolite_ldap_groups.sh"; - file = ./gitolite_ldap_groups.sh; - vars = { - LDAP_PASS = myconfig.env.tools.gitolite.ldap.password; - }; - paths = [ pkgs.openldap pkgs.stdenv.shellPackage pkgs.gnugrep pkgs.coreutils ]; - }; - in { - deps = [ "users" ]; - text = '' - if [ -d ${cfg.gitoliteDir} ]; then - ln -sf ${gitolite_ldap_groups} ${cfg.gitoliteDir}/gitolite_ldap_groups.sh - chmod g+rx ${cfg.gitoliteDir} - fi - if [ -f ${cfg.gitoliteDir}/projects.list ]; then - chmod g+r ${cfg.gitoliteDir}/projects.list - fi - ''; - }; - - users.users.wwwrun.extraGroups = [ "gitolite" ]; - - users.users.gitolite.packages = let - python-packages = python-packages: with python-packages; [ - simplejson - urllib3 - sleekxmpp - ]; - in - [ - (pkgs.python3.withPackages python-packages) - ]; - # Installation: https://git.immae.eu/mantisbt/view.php?id=93 - services.gitolite = { - enable = true; - adminPubkey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDXqRbiHw7QoHADNIEuo4nUT9fSOIEBMdJZH0bkQAxXyJFyCM1IMz0pxsHV0wu9tdkkr36bPEUj2aV5bkYLBN6nxcV2Y49X8bjOSCPfx3n6Own1h+NeZVBj4ZByrFmqCbTxUJIZ2bZKcWOFncML39VmWdsVhNjg0X4NBBehqXRIKr2gt3E/ESAxTYJFm0BnU0baciw9cN0bsRGqvFgf5h2P48CIAfwhVcGmPQnnAwabnosYQzRWxR0OygH5Kd8mePh6FheIRIigfXsDO8f/jdxwut8buvNIf3m5EBr3tUbTsvM+eV3M5vKGt7sk8T64DVtepTSdOOWtp+47ktsnHOMh immae@immae.eu"; - }; - }; -} diff --git a/nixops/modules/gitolite/gitolite_ldap_groups.sh b/nixops/modules/gitolite/gitolite_ldap_groups.sh deleted file mode 100755 index 7db0da4..0000000 --- a/nixops/modules/gitolite/gitolite_ldap_groups.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env bash - -uid_param="$1" -ldap_host="ldap.immae.eu" -ldap_binddn="cn=gitolite,ou=services,dc=immae,dc=eu" -ldap_bindpw="$LDAP_PASS" -ldap_searchbase="dc=immae,dc=eu" -ldap_scope="subtree" - -ldap_options="-h ${ldap_host} -ZZ -x -D ${ldap_binddn} -w ${ldap_bindpw} -b ${ldap_searchbase} -s ${ldap_scope}" - -ldap_filter="(&(memberOf=cn=groups,cn=gitolite,ou=services,dc=immae,dc=eu)(|(member=uid=${uid_param},ou=users,dc=immae,dc=eu)(member=uid=${uid_param},ou=group_users,dc=immae,dc=eu)))" -ldap_result=$(ldapsearch ${ldap_options} -LLL "${ldap_filter}" cn | grep 'cn:' | cut -d' ' -f2) - -echo "$ldap_result" diff --git a/nixops/modules/mail.nix b/nixops/modules/mail.nix deleted file mode 100644 index 611c8b4..0000000 --- a/nixops/modules/mail.nix +++ /dev/null @@ -1,13 +0,0 @@ -{ lib, pkgs, config, myconfig, ... }: -{ - config.users.users.nullmailer.uid = config.ids.uids.nullmailer; - config.users.groups.nullmailer.gid = config.ids.gids.nullmailer; - - config.services.nullmailer = { - enable = true; - config = { - me = myconfig.env.mail.host; - remotes = "${myconfig.env.mail.relay} smtp"; - }; - }; -} diff --git a/nixops/modules/mpd.nix b/nixops/modules/mpd.nix deleted file mode 100644 index 9903bdf..0000000 --- a/nixops/modules/mpd.nix +++ /dev/null @@ -1,56 +0,0 @@ -{ lib, pkgs, config, myconfig, ... }: -{ - config = { - secrets.keys = [ - { - dest = "mpd"; - permissions = "0400"; - text = myconfig.env.mpd.password; - } - { - dest = "mpd-config"; - permissions = "0400"; - user = "mpd"; - group = "mpd"; - text = '' - password "${myconfig.env.mpd.password}@read,add,control,admin" - ''; - } - ]; - networking.firewall.allowedTCPPorts = [ 6600 ]; - users.users.mpd.extraGroups = [ "wwwrun" "keys" ]; - systemd.services.mpd.serviceConfig.RuntimeDirectory = "mpd"; - services.mpd = { - enable = true; - network.listenAddress = "any"; - musicDirectory = myconfig.env.mpd.folder; - extraConfig = '' - include "/var/secrets/mpd-config" - audio_output { - type "null" - name "No Output" - mixer_type "none" - } - audio_output { - type "httpd" - name "OGG" - encoder "vorbis" - bind_to_address "/run/mpd/ogg.sock" - quality "5.0" - format "44100:16:1" - } - audio_output { - type "httpd" - name "MP3" - encoder "lame" - bind_to_address "/run/mpd/mp3.sock" - quality "5.0" - format "44100:16:1" - } - - - ''; - }; - }; -} - diff --git a/nixops/modules/pub/default.nix b/nixops/modules/pub/default.nix deleted file mode 100644 index cdc68db..0000000 --- a/nixops/modules/pub/default.nix +++ /dev/null @@ -1,52 +0,0 @@ -{ lib, pkgs, config, myconfig, ... }: -{ - options = { - services.pub.enable = lib.mkOption { - type = lib.types.bool; - default = false; - description = '' - Whether to enable pub user. - ''; - }; - }; - - config = lib.mkIf config.services.pub.enable { - users.users.pub = let - restrict = pkgs.runCommand "restrict" { - file = ./restrict; - buildInputs = [ pkgs.makeWrapper ]; - } '' - mkdir -p $out/bin - cp $file $out/bin/restrict - chmod a+x $out/bin/restrict - patchShebangs $out/bin/restrict - wrapProgram $out/bin/restrict \ - --prefix PATH : ${lib.makeBinPath [ pkgs.bubblewrap pkgs.rrsync ]} \ - --set TMUX_RESTRICT ${./tmux.restrict.conf} - ''; - purple-hangouts = pkgs.purple-hangouts.overrideAttrs(old: { - installPhase = '' - install -Dm755 -t $out/lib/purple-2/ libhangouts.so - for size in 16 22 24 48; do - install -TDm644 hangouts$size.png $out/share/pixmaps/pidgin/protocols/$size/hangouts.png - done - ''; - }); - in { - createHome = true; - description = "Restricted shell user"; - home = "/var/lib/pub"; - uid = myconfig.env.users.pub.uid; - useDefaultShell = true; - packages = [ - restrict - pkgs.tmux - (pkgs.pidgin.override { plugins = [ - pkgs.purple-plugin-pack purple-hangouts - pkgs.purple-discord pkgs.purple-facebook - pkgs.telegram-purple - ]; }) - ]; - }; - }; -} diff --git a/nixops/modules/pub/restrict b/nixops/modules/pub/restrict deleted file mode 100644 index b2f3be3..0000000 --- a/nixops/modules/pub/restrict +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/env bash -user="$1" -rootuser="$HOME/$user/" -mkdir -p $rootuser - -orig="$SSH_ORIGINAL_COMMAND" -if [ -z "$orig" ]; then - orig="/bin/bash -l" -fi -if [ "${orig:0:7}" = "command" ]; then - orig="${orig:8}" -fi - -case "$orig" in -rsync*) - rrsync $HOME/$user/ - ;; -*) - nix_store_paths() { - nix-store -q -R \ - /run/current-system/sw \ - /etc/profiles/per-user/pub \ - /etc/ssl/certs/ca-bundle.crt \ - | while read i; do - printf '%s--ro-bind\0'$i'\0'$i'\0' '' - done - } - - set -euo pipefail - (exec -c bwrap --ro-bind /usr /usr \ - --args 10 \ - --dir /tmp \ - --dir /var \ - --symlink ../tmp var/tmp \ - --proc /proc \ - --dev /dev \ - --ro-bind /etc/resolv.conf /etc/resolv.conf \ - --ro-bind /etc/zoneinfo /etc/zoneinfo \ - --ro-bind /etc/ssl /etc/ssl \ - --ro-bind /etc/static/ssl/certs /etc/static/ssl/certs \ - --ro-bind /run/current-system/sw/lib/locale/locale-archive /etc/locale-archive \ - --ro-bind /run/current-system/sw/bin /bin \ - --ro-bind /etc/profiles/per-user/pub/bin /bin-pub \ - --bind /var/lib/pub/$user /var/lib/pub \ - --dir /var/lib/commons \ - --ro-bind $TMUX_RESTRICT /var/lib/commons/tmux.restrict.conf \ - --chdir /var/lib/pub \ - --unshare-all \ - --share-net \ - --dir /run/user/$(id -u) \ - --setenv TERM "$TERM" \ - --setenv LOCALE_ARCHIVE "/etc/locale-archive" \ - --setenv XDG_RUNTIME_DIR "/run/user/`id -u`" \ - --setenv PS1 "$user@pub $ " \ - --setenv PATH "/bin:/bin-pub" \ - --setenv HOME "/var/lib/pub" \ - --file 11 /etc/passwd \ - --file 12 /etc/group \ - -- $orig) \ - 10< <(nix_store_paths) \ - 11< <(getent passwd $UID 65534) \ - 12< <(getent group $(id -g) 65534) - ;; -esac diff --git a/nixops/modules/pub/tmux.restrict.conf b/nixops/modules/pub/tmux.restrict.conf deleted file mode 100644 index 5aefd1c..0000000 --- a/nixops/modules/pub/tmux.restrict.conf +++ /dev/null @@ -1,43 +0,0 @@ -# Pour les nostalgiques de screen -# comme les raccourcis ne sont pas les mêmes, j'évite -set -g prefix C-a -unbind-key C-b - -unbind-key -a -bind-key -n C-h list-keys -bind-key C-d detach -bind-key & confirm-before -p "kill-window #W? (y/n)" kill-window - -# même hack que sur screen lorsqu'on veut profiter du scroll du terminal -# (xterm ...) -set -g terminal-overrides 'xterm*:smcup@:rmcup@' - -#Pour les ctrl+arrow -set-option -g xterm-keys on - -# c'est un minimum (defaut 2000) -set-option -g history-limit 10000 - -# lorsque j'ai encore un tmux ailleurs seule -# sa fenetre active réduit la taille de ma fenetre locale -setw -g aggressive-resize on - -# Pour etre alerté sur un changement dans une autre fenêtre -setw -g monitor-activity on -#set -g visual-activity on -#set -g visual-bell on - -set -g base-index 1 - -# repercuter le contenu de la fenetre dans la barre de titre -# reference des string : man tmux (status-left) -set -g set-titles on -set -g set-titles-string '#H #W #T' # host window command - -#Dans les valeurs par defaut deja, avec le ssh-agent -set -g update-environment "DISPLAY SSH_ASKPASS SSH_AUTH_SOCK SSH_AGENT_PID SSH_CONNECTION WINDOWID XAUTHORITY PATH" - -set -g status off -set -g status-left '' -set -g status-right '' - diff --git a/nixops/modules/ssh/default.nix b/nixops/modules/ssh/default.nix deleted file mode 100644 index beedaff..0000000 --- a/nixops/modules/ssh/default.nix +++ /dev/null @@ -1,40 +0,0 @@ -{ lib, pkgs, config, myconfig, ... }: -{ - config = { - networking.firewall.allowedTCPPorts = [ 22 ]; - - services.openssh.extraConfig = '' - AuthorizedKeysCommand /etc/ssh/ldap_authorized_keys - AuthorizedKeysCommandUser nobody - ''; - - secrets.keys = [{ - dest = "ssh-ldap"; - user = "nobody"; - group = "nogroup"; - permissions = "0400"; - text = myconfig.env.sshd.ldap.password; - }]; - system.activationScripts.sshd = { - deps = [ "secrets" ]; - text = '' - install -Dm400 -o nobody -g nogroup -T /var/secrets/ssh-ldap /etc/ssh/ldap_password - ''; - }; - # ssh is strict about parent directory having correct rights, don't - # move it in the nix store. - environment.etc."ssh/ldap_authorized_keys" = let - ldap_authorized_keys = - pkgs.mylibs.wrap { - name = "ldap_authorized_keys"; - file = ./ldap_authorized_keys.sh; - paths = [ pkgs.which pkgs.gitolite pkgs.openldap pkgs.stdenv.shellPackage pkgs.gnugrep pkgs.gnused pkgs.coreutils ]; - }; - in { - enable = true; - mode = "0755"; - user = "root"; - source = ldap_authorized_keys; - }; - }; -} diff --git a/nixops/modules/ssh/ldap_authorized_keys.sh b/nixops/modules/ssh/ldap_authorized_keys.sh deleted file mode 100755 index d556452..0000000 --- a/nixops/modules/ssh/ldap_authorized_keys.sh +++ /dev/null @@ -1,152 +0,0 @@ -#!/usr/bin/env bash - -LDAPSEARCH=ldapsearch -KEY="immaeSshKey" -LDAP_BIND="cn=ssh,ou=services,dc=immae,dc=eu" -LDAP_PASS=$(cat /etc/ssh/ldap_password) -LDAP_HOST="ldap.immae.eu" -LDAP_MEMBER="cn=users,cn=ssh,ou=services,dc=immae,dc=eu" -LDAP_GITOLITE_MEMBER="cn=users,cn=gitolite,ou=services,dc=immae,dc=eu" -LDAP_PUB_RESTRICT_MEMBER="cn=restrict,cn=pub,ou=services,dc=immae,dc=eu" -LDAP_PUB_FORWARD_MEMBER="cn=forward,cn=pub,ou=services,dc=immae,dc=eu" -LDAP_BASE="dc=immae,dc=eu" -GITOLITE_SHELL=$(which gitolite-shell) -ECHO=$(which echo) - -suitable_for() { - type_for="$1" - key="$2" - - if [[ $key != *$'\n'* ]] && [[ $key == ssh-* ]]; then - echo "$key" - else - key_type=$(cut -d " " -f 1 <<< "$key") - - if grep -q "\b-$type_for\b" <<< "$key_type"; then - echo "" - elif grep -q "\b$type_for\b" <<< "$key_type"; then - echo $(sed -e "s/^[^ ]* //g" <<< "$key") - else - echo "" - fi - fi -} - -clean_key_line() { - type_for="$1" - line="$2" - - if [[ "$line" == $KEY::* ]]; then - # base64 keys should't happen, unless wrong copy-pasting - key="" - else - key=$(sed -e "s/^$KEY: *//" -e "s/ *$//" <<< "$line") - fi - - suitable_for "$type_for" "$key" -} - -ldap_search() { - $LDAPSEARCH -h $LDAP_HOST -ZZ -b $LDAP_BASE -D $LDAP_BIND -w "$LDAP_PASS" -x -o ldif-wrap=no -LLL "$@" -} - -ldap_keys() { - user=$1; - if [[ $user == gitolite ]]; then - ldap_search '(&(memberOf='$LDAP_GITOLITE_MEMBER')('$KEY'=*))' $KEY | \ - while read line ; - do - if [ ! -z "$line" ]; then - if [[ $line == dn* ]]; then - user=$(sed -n 's/.*uid=\([^,]*\).*/\1/p' <<< "$line") - if [ -n "$user" ]; then - if [[ $user == "immae" ]] || [[ $user == "denise" ]]; then - # Capitalize first letter (backward compatibility) - user=$(sed -r 's/^([a-z])/\U\1/' <<< "$user") - fi - else - # Service fake user - user=$(sed -n 's/.*cn=\([^,]*\).*/\1/p' <<< "$line") - fi - elif [[ $line == $KEY* ]]; then - key=$(clean_key_line git "$line") - if [ ! -z "$key" ]; then - if [[ $key != *$'\n'* ]] && [[ $key == ssh-* ]]; then - echo -n 'command="'$GITOLITE_SHELL' '$user'",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ' - echo $key - fi - fi - fi - fi - done - exit 0 - elif [[ $user == pub ]]; then - ldap_search '(&(memberOf='$LDAP_PUB_RESTRICT_MEMBER')('$KEY'=*))' $KEY | \ - while read line ; - do - if [ ! -z "$line" ]; then - if [[ $line == dn* ]]; then - echo "" - user=$(sed -n 's/.*uid=\([^,]*\).*/\1/p' <<< "$line") - echo "# $user" - elif [[ $line == $KEY* ]]; then - key=$(clean_key_line pub "$line") - key_forward=$(clean_key_line forward "$line") - if [ ! -z "$key" ]; then - if [[ $key != *$'\n'* ]] && [[ $key == ssh-* ]]; then - echo -n 'command="/etc/profiles/per-user/pub/bin/restrict '$user'" ' - echo $key - fi - elif [ ! -z "$key_forward" ]; then - if [[ $key_forward != *$'\n'* ]] && [[ $key_forward == ssh-* ]]; then - echo "# forward only" - echo -n 'no-pty,no-X11-forwarding,command="'$ECHO' forward only" ' - echo $key_forward - fi - fi - fi - fi - done - - echo "" - ldap_search '(&(memberOf='$LDAP_PUB_FORWARD_MEMBER')('$KEY'=*))' $KEY | \ - while read line ; - do - if [ ! -z "$line" ]; then - if [[ $line == dn* ]]; then - echo "" - user=$(sed -n 's/.*uid=\([^,]*\).*/\1/p' <<< "$line") - echo "# $user" - elif [[ $line == $KEY* ]]; then - key=$(clean_key_line forward "$line") - if [ ! -z "$key" ]; then - if [[ $key != *$'\n'* ]] && [[ $key == ssh-* ]]; then - echo -n 'no-pty,no-X11-forwarding,command="'$ECHO' forward only" ' - echo $key - fi - fi - fi - fi - done - exit 0 - else - ldap_search '(&(memberOf='$LDAP_MEMBER')('$KEY'=*)(uid='$user'))' $KEY | \ - while read line ; - do - if [ ! -z "$line" ]; then - if [[ $line == dn* ]]; then - user=$(sed -n 's/.*uid=\([^,]*\).*/\1/p' <<< "$line") - elif [[ $line == $KEY* ]]; then - key=$(clean_key_line ssh "$line") - if [ ! -z "$key" ]; then - if [[ $key != *$'\n'* ]] && [[ $key == ssh-* ]]; then - echo $key - fi - fi - fi - fi - done - fi -} - -ldap_keys $@ diff --git a/nixops/modules/task/default.nix b/nixops/modules/task/default.nix deleted file mode 100644 index 9aeaa3f..0000000 --- a/nixops/modules/task/default.nix +++ /dev/null @@ -1,327 +0,0 @@ -{ lib, pkgs, config, myconfig, ... }: -let - cfg = config.services.myTasks; - server_vardir = config.services.taskserver.dataDir; - fqdn = "task.immae.eu"; - user = config.services.taskserver.user; - env = myconfig.env.tools.task; - group = config.services.taskserver.group; - taskserver-user-certs = pkgs.runCommand "taskserver-user-certs" {} '' - mkdir -p $out/bin - cat > $out/bin/taskserver-user-certs <<"EOF" - #!/usr/bin/env bash - - user=$1 - - silent_certtool() { - if ! output="$("${pkgs.gnutls.bin}/bin/certtool" "$@" 2>&1)"; then - echo "GNUTLS certtool invocation failed with output:" >&2 - echo "$output" >&2 - fi - } - - silent_certtool -p \ - --bits 4096 \ - --outfile "${server_vardir}/userkeys/$user.key.pem" - ${pkgs.gnused}/bin/sed -i -n -e '/^-----BEGIN RSA PRIVATE KEY-----$/,$p' "${server_vardir}/userkeys/$user.key.pem" - - silent_certtool -c \ - --template "${pkgs.writeText "taskserver-ca.template" '' - tls_www_client - encryption_key - signing_key - expiration_days = 3650 - ''}" \ - --load-ca-certificate "${server_vardir}/keys/ca.cert" \ - --load-ca-privkey "${server_vardir}/keys/ca.key" \ - --load-privkey "${server_vardir}/userkeys/$user.key.pem" \ - --outfile "${server_vardir}/userkeys/$user.cert.pem" - EOF - chmod a+x $out/bin/taskserver-user-certs - patchShebangs $out/bin/taskserver-user-certs - ''; - taskwarrior-web = pkgs.webapps.taskwarrior-web; - socketsDir = "/run/taskwarrior-web"; - varDir = "/var/lib/taskwarrior-web"; - taskwebPages = let - uidPages = lib.attrsets.zipAttrs ( - lib.lists.flatten - (lib.attrsets.mapAttrsToList (k: c: map (v: { "${v}" = k; }) c.uid) env.taskwarrior-web) - ); - pages = lib.attrsets.mapAttrs (uid: items: - if lib.lists.length items == 1 then - '' - - - - - - - '' - else - '' - - - To-do list disponibles - - - - -
    - ${builtins.concatStringsSep "\n" (map (item: "
  • ${item}
  • ") items)} -
- - - '' - ) uidPages; - in - pkgs.runCommand "taskwerver-pages" {} '' - mkdir -p $out/ - ${builtins.concatStringsSep "\n" (lib.attrsets.mapAttrsToList (k: v: "cp ${pkgs.writeText k v} $out/${k}.html") pages)} - echo "Please login" > $out/index.html - ''; -in { - options.services.myTasks = { - enable = lib.mkEnableOption "my tasks service"; - }; - - config = lib.mkIf cfg.enable { - secrets.keys = [{ - dest = "webapps/tools-taskwarrior-web"; - user = "wwwrun"; - group = "wwwrun"; - permissions = "0400"; - text = '' - SetEnv TASKD_HOST "${fqdn}:${toString config.services.taskserver.listenPort}" - SetEnv TASKD_VARDIR "${server_vardir}" - SetEnv TASKD_LDAP_HOST "ldaps://${env.ldap.host}" - SetEnv TASKD_LDAP_DN "${env.ldap.dn}" - SetEnv TASKD_LDAP_PASSWORD "${env.ldap.password}" - SetEnv TASKD_LDAP_BASE "${env.ldap.base}" - SetEnv TASKD_LDAP_FILTER "${env.ldap.search}" - ''; - }]; - services.websites.tools.modules = [ "proxy_fcgi" "sed" ]; - services.websites.tools.vhostConfs.task = { - certName = "eldiron"; - addToCerts = true; - hosts = [ "task.immae.eu" ]; - root = "/run/current-system/webapps/_task"; - extraConfig = [ '' - - DirectoryIndex index.php - Use LDAPConnect - Require ldap-group cn=users,cn=taskwarrior,ou=services,dc=immae,dc=eu - - SetHandler "proxy:unix:/var/run/phpfpm/task.sock|fcgi://localhost" - - Include /var/secrets/webapps/tools-taskwarrior-web - - '' - '' - - ProxyPass "unix://${socketsDir}/%{folderName}.sock|http://localhost-%{folderName}/" - ProxyPassReverse "unix://${socketsDir}/%{folderName}.sock|http://localhost-%{folderName}/" - ProxyPassReverse http://${fqdn}/ - - SetOutputFilter Sed - OutputSed "s|/ajax|/taskweb/%{folderName}/ajax|g" - OutputSed "s|\([^x]\)/tasks|\1/taskweb/%{folderName}/tasks|g" - OutputSed "s|\([^x]\)/projects|\1/taskweb/%{folderName}/projects|g" - OutputSed "s|http://${fqdn}/|/taskweb/%{folderName}/|g" - OutputSed "s|/img/relax.jpg|/taskweb/%{folderName}/img/relax.jpg|g" - - '' - '' - Alias /taskweb ${taskwebPages} - - DirectoryIndex index.html - Require all granted - - - RewriteEngine on - RewriteRule ^/taskweb$ /taskweb/ [R=301,L] - RedirectMatch permanent ^/taskweb/([^/]+)$ /taskweb/$1/ - - RewriteCond %{LA-U:REMOTE_USER} !="" - RewriteCond ${taskwebPages}/%{LA-U:REMOTE_USER}.html -f - RewriteRule ^/taskweb/?$ ${taskwebPages}/%{LA-U:REMOTE_USER}.html [L] - - - Use LDAPConnect - Require ldap-group cn=users,cn=taskwarrior,ou=services,dc=immae,dc=eu - - '' - ] ++ (lib.attrsets.mapAttrsToList (k: v: '' - - ${builtins.concatStringsSep "\n" (map (uid: "Require ldap-attribute uid=${uid}") v.uid)} - - Use Taskwarrior ${k} - - '') env.taskwarrior-web); - }; - services.phpfpm.poolConfigs = { - tasks = '' - listen = /var/run/phpfpm/task.sock - user = ${user} - group = ${group} - listen.owner = wwwrun - listen.group = wwwrun - pm = dynamic - pm.max_children = 60 - pm.start_servers = 2 - pm.min_spare_servers = 1 - pm.max_spare_servers = 10 - - ; Needed to avoid clashes in browser cookies (same domain) - env[PATH] = "/etc/profiles/per-user/${user}/bin" - php_value[session.name] = TaskPHPSESSID - php_admin_value[open_basedir] = "${./www}:/tmp:${server_vardir}:/etc/profiles/per-user/${user}/bin/" - ''; - }; - - myServices.websites.webappDirs._task = ./www; - - security.acme.certs."task" = config.services.myCertificates.certConfig // { - inherit user group; - plugins = [ "fullchain.pem" "key.pem" "cert.pem" "account_key.json" ]; - domain = fqdn; - postRun = '' - systemctl restart taskserver.service - ''; - }; - - users.users.${user}.packages = [ taskserver-user-certs ]; - - system.activationScripts.taskserver = { - deps = [ "users" ]; - text = '' - install -m 0750 -o ${user} -g ${group} -d ${server_vardir} - install -m 0750 -o ${user} -g ${group} -d ${server_vardir}/userkeys - install -m 0750 -o ${user} -g ${group} -d ${server_vardir}/keys - - if [ ! -e "${server_vardir}/keys/ca.key" ]; then - silent_certtool() { - if ! output="$("${pkgs.gnutls.bin}/bin/certtool" "$@" 2>&1)"; then - echo "GNUTLS certtool invocation failed with output:" >&2 - echo "$output" >&2 - fi - } - - silent_certtool -p \ - --bits 4096 \ - --outfile "${server_vardir}/keys/ca.key" - - silent_certtool -s \ - --template "${pkgs.writeText "taskserver-ca.template" '' - cn = ${fqdn} - expiration_days = -1 - cert_signing_key - ca - ''}" \ - --load-privkey "${server_vardir}/keys/ca.key" \ - --outfile "${server_vardir}/keys/ca.cert" - - chown :${group} "${server_vardir}/keys/ca.key" - chmod g+r "${server_vardir}/keys/ca.key" - fi - ''; - }; - - services.taskserver = { - enable = true; - allowedClientIDs = [ "^task [2-9]" "^Mirakel [1-9]" ]; - inherit fqdn; - listenHost = "::"; - pki.manual.ca.cert = "${server_vardir}/keys/ca.cert"; - pki.manual.server.cert = "${config.security.acme.directory}/task/fullchain.pem"; - pki.manual.server.crl = "${config.security.acme.directory}/task/invalid.crl"; - pki.manual.server.key = "${config.security.acme.directory}/task/key.pem"; - requestLimit = 104857600; - }; - - system.activationScripts.taskwarrior-web = { - deps = [ "users" ]; - text = '' - if [ ! -f ${server_vardir}/userkeys/taskwarrior-web.cert.pem ]; then - ${taskserver-user-certs}/bin/taskserver-user-certs taskwarrior-web - chown taskd:taskd ${server_vardir}/userkeys/taskwarrior-web.cert.pem ${server_vardir}/userkeys/taskwarrior-web.key.pem - fi - ''; - }; - - systemd.services = (lib.attrsets.mapAttrs' (name: userConfig: - let - credentials = "${userConfig.org}/${name}/${userConfig.key}"; - dateFormat = userConfig.date; - taskrc = pkgs.writeText "taskrc" '' - data.location=${varDir}/${name} - taskd.certificate=${server_vardir}/userkeys/taskwarrior-web.cert.pem - taskd.key=${server_vardir}/userkeys/taskwarrior-web.key.pem - # IdenTrust DST Root CA X3 - # obtained here: https://letsencrypt.org/fr/certificates/ - taskd.ca=${pkgs.writeText "ca.cert" '' - -----BEGIN CERTIFICATE----- - MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/ - MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT - DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow - PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD - Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB - AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O - rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq - OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b - xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw - 7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD - aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV - HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG - SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69 - ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr - AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz - R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5 - JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo - Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ - -----END CERTIFICATE-----''} - taskd.server=${fqdn}:${toString config.services.taskserver.listenPort} - taskd.credentials=${credentials} - dateformat=${dateFormat} - ''; - in lib.attrsets.nameValuePair "taskwarrior-web-${name}" { - description = "Taskwarrior webapp for ${name}"; - wantedBy = [ "multi-user.target" ]; - after = [ "network.target" ]; - path = [ pkgs.taskwarrior ]; - - environment.TASKRC = taskrc; - environment.BUNDLE_PATH = "${taskwarrior-web.gems}/${taskwarrior-web.gems.ruby.gemPath}"; - environment.BUNDLE_GEMFILE = "${taskwarrior-web.gems.confFiles}/Gemfile"; - environment.LC_ALL = "fr_FR.UTF-8"; - - script = '' - exec ${taskwarrior-web.gems}/${taskwarrior-web.gems.ruby.gemPath}/bin/bundle exec thin start -R config.ru -S ${socketsDir}/${name}.sock - ''; - - serviceConfig = { - User = user; - PrivateTmp = true; - Restart = "always"; - TimeoutSec = 60; - Type = "simple"; - WorkingDirectory = taskwarrior-web; - StateDirectoryMode = 0750; - StateDirectory = assert lib.strings.hasPrefix "/var/lib/" varDir; - (lib.strings.removePrefix "/var/lib/" varDir + "/${name}"); - RuntimeDirectoryPreserve = "yes"; - RuntimeDirectory = assert lib.strings.hasPrefix "/run/" socketsDir; - lib.strings.removePrefix "/run/" socketsDir; - }; - - unitConfig.RequiresMountsFor = varDir; - }) env.taskwarrior-web) // { - taskserver-ca.postStart = '' - chown :${group} "${server_vardir}/keys/ca.key" - chmod g+r "${server_vardir}/keys/ca.key" - ''; - }; - - }; -} diff --git a/nixops/modules/task/www/index.php b/nixops/modules/task/www/index.php deleted file mode 100644 index deaf8af..0000000 --- a/nixops/modules/task/www/index.php +++ /dev/null @@ -1,157 +0,0 @@ - $value) { - if ($key !== "count") { - $entries[] = explode(":", $value); - } -} - -if (isset($_GET["file"])) { - $basecert = $vardir . "/userkeys/" . $ldap_user; - if (!file_exists($basecert . ".cert.pem")) { - exec("taskserver-user-certs $ldap_user"); - } - $certificate = file_get_contents($basecert . ".cert.pem"); - $cert_key = file_get_contents($basecert . ".key.pem"); - - // IdenTrust DST Root CA X3 - // obtained here: https://letsencrypt.org/fr/certificates/ - $server_cert = "-----BEGIN CERTIFICATE----- -MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/ -MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT -DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow -PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD -Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB -AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O -rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq -OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b -xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw -7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD -aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV -HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG -SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69 -ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr -AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz -R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5 -JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo -Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ ------END CERTIFICATE-----"; - - $file = $_GET["file"]; - switch($file) { - case "ca.cert.pem": - $content = $server_cert; - $name = "ca.cert.pem"; - $type = "application/x-x509-ca-cert"; - break; - case "cert.pem": - $content = $certificate; - $name = $ldap_user . ".cert.pem"; - $type = "application/x-x509-ca-cert"; - break; - case "key.pem": - $content = $cert_key; - $name = $ldap_user . ".key.pem"; - $type = "application/x-x509-ca-cert"; - break; - case "mirakel"; - foreach ($entries as $entry) { - list($org, $user, $key) = $entry; - if ($key == $_GET["key"]) { break; } - } - $name = $user . ".mirakel"; - $type = "text/plain"; - $content = "username: $user -org: $org -user key: $key -server: $host -client.cert: -$certificate -Client.key: -$cert_key -ca.cert: -$server_cert -"; - break; - default: - die("invalid file name"); - break; - } - - header("Content-Type: $type"); - header('Content-Disposition: attachment; filename="' . $name . '"'); - header('Content-Transfer-Encoding: binary'); - header('Accept-Ranges: bytes'); - header('Cache-Control: private'); - header('Pragma: private'); - echo $content; - exit; -} -?> - -
- Taskwarrior configuration -
- - -For command line interface, download the files, put them near your Taskwarrior -configuration files, and add that to your Taskwarrior configuration: -
-taskd.certificate=/path/to/.cert.pem
-taskd.key=/path/to/.key.pem
-taskd.server=
- 1) {
-  echo "# Chose one of them\n";
-  foreach($entries as $entry) {
-    list($org, $user, $key) = $entry;
-    echo "# taskd.credentials=$org/$user/$key\n";
-  }
-} else { ?>
-taskd.credentials=//
-
-taskd.ca=/path/to/ca.cert.pem
-
-For Mirakel, download and import the file: - -For Android Taskwarrior app, see instructions here. - - - -- cgit v1.2.3