• Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Search
  • Register
  • Login
Netgate Discussion Forum
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Search
  • Register
  • Login

Problem using webroot local folder - hash file not created

Scheduled Pinned Locked Moved ACME
acme
6 Posts 3 Posters 1.1k Views
Loading More Posts
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • B
    Bill Harris
    last edited by Aug 29, 2022, 1:49 AM

    I'm trying to set up the acme plugin with the webroot local folder method in conjunction with haproxy and the LUA script from [https://github.com/janeczku/haproxy-acme-validation-plugin/blob/master/acme-http01-webroot.lua](link url).

    Unfortunately, the acme plugin doesn't seem to be able to write the token file. I've checked the logs, both general and the acme log mentioned below, but nothing shows up. The directory in question exists as shown below. I've been scratching my head for a couple hours trying to solve this, with no luck. Any help would be appreciated

    ls -al /tmp/haproxy_chroot/haproxywebroot/.well-known/acme-challenge/
    total 8
    drwxrw-rw-  2 root  wheel  64 Aug 28 17:25 .
    drwxr-xr-x  3 root  wheel  64 Aug 28 15:52 ..
    -rw-rw-rw-  1 root  wheel  43 Aug 28 17:25 _s1qu-iKQquucEl99yMlOHgdssWW1LklUQe5cYnaDeM
    

    I created the file above just to verify the script can access it. It's a different challenge file.

    Here's the log from the acme client starting on the line it should have written the token file to:

    put token at: /tmp/haproxy_chroot/haproxywebroot/.well-known/acme-challenge/4DTeprjHhqNIE_K8EJncCuoBfaONNJ_Rt1Db_rN5PbM
    [Sun Aug 28 18:01:38 PDT 2022] Pending, The CA is processing your order, please just wait. (1/30)
    [Sun Aug 28 18:01:41 PDT 2022] Found domain http api file: /tmp/acme/[redacted].cx//httpapi/pfSenseacme.sh
    [Sun Aug 28 18:01:41 PDT 2022] [redacted].cx:Verify error:99.78.100.117: Invalid response from http://[redacted].cx/.well-known/acme-challenge/4DTeprjHhqNIE_K8EJncCuoBfaONNJ_Rt1Db_rN5PbM: 404
    [Sun Aug 28 18:01:41 PDT 2022] Please check log file for more details: /tmp/acme/[redacted].cx/acme_issuecert.log
    
    G 1 Reply Last reply Aug 29, 2022, 10:54 AM Reply Quote 0
    • G
      Gertjan @Bill Harris
      last edited by Gertjan Aug 29, 2022, 10:55 AM Aug 29, 2022, 10:54 AM

      @bill-harris

      Place a file like test.html with content "hello" in /tmp/haproxy_chroot/haproxywebroot/.well-known/acme-challenge/
      and in http://[redacted].cx/.well-known/acme-challenge/

      Now, from the outside ( !!! ) check :
      http://[redacted].cx/.well-known/acme-challenge/test.html
      http://[redacted].cx/test.html

      Can you open / see these files ?

      Also, when it says "4DTeprjHhqNIE_K8EJncCuoBfaONNJ_Rt1Db_rN5PbM" created,
      was the file visible in tmp/haproxy_chroot/haproxywebroot/.well-known/acme-challenge/
      use console or SFTP to check.
      Did it contain a token ?

      edit : why would you need a LUA script from an external source to make acme.sh work ?

      No "help me" PM's please. Use the forum, the community will thank you.
      Edit : and where are the logs ??

      B 2 Replies Last reply Aug 29, 2022, 9:03 PM Reply Quote 0
      • B
        Bill Harris @Gertjan
        last edited by Aug 29, 2022, 9:03 PM

        Now, from the outside ( !!! ) check :

        The file is served as expected from an outside connection (phone with wifi disabled)

        Also, when it says "4DTeprjHhqNIE_K8EJncCuoBfaONNJ_Rt1Db_rN5PbM" created,
        was the file visible in tmp/haproxy_chroot/haproxywebroot/.well-known/acme-challenge/

        The file does not exist after the script fails. It's possible the acme script cleans up the file before I could check? I haven't tracked down the script source to troubleshoot there... That's probably the best course of action if all else fails.

        find /  -name "*4DTeprjHhqNIE_K8EJncCuoBfaONNJ_Rt1Db_rN5PbM*"
        returns no results
        

        edit : why would you need a LUA script from an external source to make acme.sh work ?

        I'm using HAProxy with an LUA script backend to serve the request. I've looked it over and it's harmless. It simply verifies the existence of the challenge file that the acme script wrote and returns the contents.

        Is there a better way to serve the file from pfsense directly? I'm trying to avoid additional dependencies for certificate generation/renewal.

        B 1 Reply Last reply Aug 29, 2022, 10:01 PM Reply Quote 0
        • B
          Bill Harris @Bill Harris
          last edited by Aug 29, 2022, 10:01 PM

          @bill-harris said in Problem using webroot local folder - hash file not created:

          The file does not exist after the script fails. It's possible the acme script cleans up the file before I could check? I haven't tracked down the script source to troubleshoot there... That's probably the best course of action if all else fails.

          I tracked down the location of the acme script and it does indeed clean up the token file by the time it's done. After removing that bit of code, I was able to verify that it's properly writing the file in the expected location. My problem is that the LUA script is failing to open the file and thus can't read/serve it from HAProxy. I'll figure it out and post the solution whether it's a filesystem or LUA permission thing.

          1 Reply Last reply Reply Quote 0
          • B
            Bill Harris @Gertjan
            last edited by Aug 29, 2022, 10:39 PM

            @gertjan Looks like lua under haproxy is forbidden from doing file io because it blocks.. Time to figure out how to configure the local pfsense nginx process to serve the file.

            1 Reply Last reply Reply Quote 0
            • S
              Soyokaze
              last edited by Mar 6, 2023, 1:51 PM

              FYI just today that script gave me hassles until it... just started to work.

              Same script by Jan Broer as always, same config as always.

              pfsense: 2.6.0-RELEASE (amd64)
              acme: 0.7.3
              haproxy: 0.61_7
              

              Frontend configuration:

              ACL configuration

              ACL Name: url_acme_http01
              Expression: "Path starts with:"
              Value: /.well-known/acme-challenge/
              

              Actions

              Action: http-request lua service
              Condition acl names: METH_GET url_acme_http01
              lua-function: acme-http01
              

              Lua script in case I lose it again:

              -- ACME http-01 domain validation plugin for Haproxy 1.6+
              -- copyright (C) 2015 Jan Broer
              --
              -- usage:
              --
              -- 1) copy acme-webroot.lua in your haproxy config dir
              -- 
              -- 2) Invoke the plugin by adding in the 'global' section of haproxy.cfg:
              -- 
              --    lua-load /etc/haproxy/acme-webroot.lua
              -- 
              -- 3) insert these two lines in every http frontend that is
              --    serving domains for which you want to create certificates:
              -- 
              --    acl url_acme_http01 path_beg /.well-known/acme-challenge/
              --    http-request use-service lua.acme-http01 if METH_GET url_acme_http01
              --
              -- 4) reload haproxy
              --
              -- 5) create a certificate:
              --
              -- ./letsencrypt-auto certonly --text --webroot --webroot-path /var/tmp -d blah.example.com --renew-by-default --agree-tos --email my@email.com
              --
              
              acme = {}
              acme.version = "0.1.1"
              
              --
              -- Configuration
              --
              -- When HAProxy is *not* configured with the 'chroot' option you must set an absolute path here and pass 
              -- that as 'webroot-path' to the letsencrypt client
              
              acme.conf = {
              	["non_chroot_webroot"] = ""
              }
              
              --
              -- Startup
              --  
              acme.startup = function()
              	core.Info("[acme] http-01 plugin v" .. acme.version);
              end
              
              --
              -- ACME http-01 validation endpoint
              --
              acme.http01 = function(applet)
              	local response = ""
              	local reqPath = applet.path
              	local src = applet.sf:src()
              	local token = reqPath:match( ".+/(.*)$" )
              
              	if token then
              		token = sanitizeToken(token)
              	end
              
              	if (token == nil or token == '') then
              		response = "bad request\n"
              		applet:set_status(400)
              		core.Warning("[acme] malformed request (client-ip: " .. tostring(src) .. ")")
              	else
              		auth = getKeyAuth(token)
              		if (auth:len() >= 1) then
              			response = auth .. "\n"
              			applet:set_status(200)
              			core.Info("[acme] served http-01 token: " .. token .. " (client-ip: " .. tostring(src) .. ")")
              		else
              			response = "resource not found\n"
              			applet:set_status(404)
              			core.Warning("[acme] http-01 token not found: " .. token .. " (client-ip: " .. tostring(src) .. ")")
              		end
              	end
              
              	applet:add_header("Server", "haproxy/acme-http01-authenticator")
              	applet:add_header("Content-Length", string.len(response))
              	applet:add_header("Content-Type", "text/plain")
              	applet:start_response()
              	applet:send(response)
              end
              
              --
              -- strip chars that are not in the URL-safe Base64 alphabet
              -- see https://github.com/letsencrypt/acme-spec/blob/master/draft-barnes-acme.md
              --
              function sanitizeToken(token)
              	_strip="[^%a%d%+%-%_=]"
              	token = token:gsub(_strip,'')
              	return token
              end
              
              --
              -- get key auth from token file
              --
              function getKeyAuth(token)
                      local keyAuth = ""
                      local path = acme.conf.non_chroot_webroot .. "/.well-known/acme-challenge/" .. token
                      local f = io.open(path, "rb")
                      if f ~= nil then
                              keyAuth = f:read("*all")
                              f:close()
                      end
                      return keyAuth
              end
              
              core.register_init(acme.startup)
              core.register_service("acme-http01", "http", acme.http01)
              

              Need full pfSense in a cloud? PM for details!

              1 Reply Last reply Reply Quote 0
              • First post
                Last post
              Copyright 2025 Rubicon Communications LLC (Netgate). All rights reserved.
                [[user:consent.lead]]
                [[user:consent.not_received]]