Appengine - Deployment of hidden folder

ⅰ亾dé卋堺 提交于 2019-12-05 15:47:25

For anyone else coming here like me after trying to serve the challenge for letsencrypt in a static manner in Google App Engine and failing, the following did it for me: (one might be able to actually do it statically, but I didn't try it as I didn't want to spend more time trying out stuff and Ian apparently tried that and could not make it work [maybe the copy command done internally on Google App Engine ignores the directories that start with a dot] )

Taken from http://igorartamonov.com/2015/12/lets-encrypt-ssl-google-appengine/ credits go to Igor Artamonov.

Just build a servlet like:

public class LetsencryptServlet extends HttpServlet {

    public static final Map<String, String> challenges = new HashMap<String, String>();

    static {
        challenges.put("RzrvZ9gd7EH3i_TsJM-B0vdEMslD4oo_lwsagGskp6c",
                "RzrvZ9gd7EH3i_TsJM-B0vdEMslD4oo_lwsagGskp6c.ONrZa3UelibSWEX270nTUiRZKPFXw096nENWbMGw0-E");
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        if (!req.getRequestURI().startsWith("/.well-known/acme-challenge/")) {
            resp.sendError(404);
            return;
        }
        String id = req.getRequestURI().substring("/.well-known/acme-challenge/".length());
        if (!challenges.containsKey(id)) {
            resp.sendError(404);
            return;
        }
        resp.setContentType("text/plain");
        resp.getOutputStream().print(challenges.get(id));
    }
}

And add to web.xml somethine like:

<servlet>
    <servlet-name>letsencrypt</servlet-name>
    <servlet-class>...LetsencryptServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>letsencrypt</servlet-name>
    <url-pattern>/.well-known/acme-challenge/*</url-pattern>
</servlet-mapping>

Of course, be sure that the servlet class has the full classpath for your created Servlet.

That blog post also deals with the other steps necessary to generate and install the certificate.

Ian: Are you sure that you were deploying the servlet well? check the logs, make sure that you are testing the right version.. maybe you had a compilation issue..

Cheers

I ran into this problem trying to serve an assetlinks.json file. It would indeed appear that folders starting with a . are not accessible within the static context in App Engine. A more generic version of João Antunes workaround is as follows.

First, create the folder without the . at the start and place any required files inside it.

We then need to create a servlet that will respond with the correct data when a request to the hidden folder is received.

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;

/**
 * Created by Will Calderwood on 17/05/2017.
 * <p>
 * It would appear to not be possible to upload hidden folders to app engine. So when files need
 * to be served from a hidden folder the URL can be bounced through this servlet
 */
public class StaticFileServer extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // We'll remove the dots from the path
        String uri = req.getRequestURI().replace("/.", "/");

        // Do anything else that needs doing here
        if (uri.toLowerCase().contains(".json")) {
            resp.setContentType("application/json");
        }

        // Read and return the resource from the non-hidden folder
        try (InputStream in = getServletContext().getResourceAsStream(uri)) {
            if (in == null){
                resp.sendError(404);
                return;
            }
            byte[] buffer = new byte[8192];
            int count;
            while ((count = in.read(buffer)) > 0) {
                resp.getOutputStream().write(buffer, 0, count);
            }
        }
    }
}

Then add the following to your web.xml file to point the hidden folder at our servlet

<servlet>
    <servlet-name>StaticFileServer</servlet-name>
    <servlet-class>main.com.you.StaticFileServer</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>StaticFileServer</servlet-name>
    <url-pattern>/.well-known/*</url-pattern>
</servlet-mapping>

I did find a better way, the issue is that the code is stored in a hidden directory, so we just need to map the correct url to a visible directory.

handlers: - url: /.well-known static_dir: _well-known

Static files are not uploaded to the application servers and thus are not accessible by app code. From appengine-web.xml Reference, in the <static-files> section:

< static-files >

Optional. The < static-files > element specifies patterns that match file paths to include and exclude from the list of static files, overriding or amending the default behavior. Static file are served from dedicated servers and caches that are separate from the application servers and are useful for serving static content such as images, CSS stylesheets or JavaScript files.

To have files accessible by app code they need to be specified in the <resource-files> section (same doc as above):

< resource-files >

Optional. The files that listed in the < resource-files > element are accessible by the application code using the filesystem. These files are stored on the application servers with the app as opposed to how static files are stored and served.

I tried everything, but could not manage to upload that hidden folder. I then defined a servlet mapping for that path an the servlet writes out the verification string expected bei the SSL issuer:

<servlet-mapping>
    <servlet-name>SSLVerificationServlet</servlet-name>
    <url-pattern>/.well-known/acme-challenge/roQH_vUmRQsuKH8lZGedft9O6TK-UoZWzv_kY8MukH4F8</url-pattern>
</servlet-mapping> 

An ugly, but straightforward workaround is to use JSP support to map the page. One example:

Create your json file in package/src/main/webapp/_well-known/assetlinks.json.jsp

<%@ page contentType="application/json;charset=UTF-8" language="java"%>
[JSON CONTENT]

Map the "servlet" to the desired path in web.xml:

<servlet>
    <servlet-name>Asset Links</servlet-name>
    <jsp-file>/_well-known/assetlinks.json.jsp</jsp-file>
</servlet>
<servlet-mapping>
    <servlet-name>Asset Links</servlet-name>
    <url-pattern>/.well-known/assetlinks.json</url-pattern>
</servlet-mapping>

Done!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!