Unverified Commit 3f66adff authored by Franz Pletz's avatar Franz Pletz Committed by GitHub
Browse files

nixos/acme: drop email requirement (#489983)

parents b658df36 e65f8ef1
Loading
Loading
Loading
Loading
+21 −10
Original line number Diff line number Diff line
@@ -15,9 +15,21 @@ let
  numCerts = lib.length (builtins.attrNames cfg.certs);
  _24hSecs = 60 * 60 * 24;

  # The placerholder email address used by lego in case none gets passed
  placeholderEmail = "noemail@example.com";

  # Used to make unique paths for each cert/account config set
  mkHash = with builtins; val: lib.substring 0 20 (hashString "sha256" val);
  mkAccountHash = acmeServer: data: mkHash "${toString acmeServer} ${data.keyType} ${data.email}";
  mkAccountHash =
    acmeServer: data:
    mkHash (
      lib.concatStringsSep " " [
        (toString acmeServer)
        data.keyType
        (if (data.email != null) then data.email else placeholderEmail)
      ]

    );
  accountDirRoot = "/var/lib/acme/.lego/accounts/";

  isIP =
@@ -273,6 +285,8 @@ let
        "--accept-tos" # Checking the option is covered by the assertions
        "--path"
        "."
      ]
      ++ lib.optionals (data.email != null) [
        "--email"
        data.email
      ]
@@ -580,7 +594,12 @@ let
          # Check if a new order is needed
          # We can only renew if the list of domains has not changed.
          # We also need an account key. Avoids #190493
          if cmp -s domainhash.txt certificates/domainhash.txt && [ -e '${certificateKey}' ] && [ -e 'certificates/${keyName}.crt' ] && [ -n "$(find accounts -name '${data.email}.key')" ]; then
          if cmp -s domainhash.txt certificates/domainhash.txt && [ -e '${certificateKey}' ] && \
            [ -e 'certificates/${keyName}.crt' ] && \
            [ -n "$(find accounts -name '${
              if (data.email != null) then data.email else placeholderEmail
            }.key')" ];
          then
            # Even if a cert is not expired, it may be revoked by the CA.
            # Try to renew, and silently fail if the cert is not expired.
            # Avoids #85794 and resolves #129838
@@ -1118,14 +1137,6 @@ in
          certs = lib.attrValues cfg.certs;
        in
        [
          {
            assertion = cfg.defaults.email != null || lib.all (certOpts: certOpts.email != null) certs;
            message = ''
              You must define `security.acme.certs.<name>.email` or
              `security.acme.defaults.email` to register with the CA. Note that using
              many different addresses for certs may trigger account rate limits.
            '';
          }
          {
            assertion = cfg.acceptTerms;
            message = ''
+21 −1
Original line number Diff line number Diff line
@@ -52,7 +52,14 @@ in
          };

          accountchange.configuration = {
            security.acme.certs."${config.networking.fqdn}".email = "admin@example.test";
            # Providing an email address is optional
            security.acme.certs."${config.networking.fqdn}".email = null;
          };

          emailplaceholder.configuration = {
            # but Lego will default to this email address, which should not
            # result in any change when configured
            security.acme.certs."${config.networking.fqdn}".email = "noemail@example.com";
          };

          keytype.configuration = {
@@ -157,6 +164,7 @@ in
      certName = nodes.builtin.networking.fqdn;
      caDomain = nodes.acme.test-support.acme.caDomain;
    in
    # python
    ''
      ${(import ./utils.nix).pythonUtils}

@@ -217,11 +225,23 @@ in
          hash_after = builtin.succeed(f"sha256sum /var/lib/acme/{cert}/cert.pem")
          # Has to do a full run to register account, which creates new certs.
          assert hash != hash_after, "Certificate was not renewed"
          hash = hash_after

          builtin.succeed("systemctl stop renew-triggered.target")
          switch_to(builtin, "emailplaceholder")
          builtin.wait_for_unit("renew-triggered.target")

          # Check that there are still two account directories
          builtin.succeed("test $(ls -1 /var/lib/acme/.lego/accounts | tee /dev/stderr | wc -l) -eq 2")
          hash_after = builtin.succeed(f"sha256sum /var/lib/acme/{cert}/cert.pem")
          assert hash == hash_after, "Implicit to explicit email placeholder renewed the certificate"

          # Remove the new account directory
          builtin.succeed(
              "cd /var/lib/acme/.lego/accounts"
              " && ls -1 --sort=time | tee /dev/stderr | head -1 | xargs rm -rf"
          )

          # old_hash will be used in the preservation tests later
          old_hash = hash_after