Difference between revisions of "AppSuite:Debugging production servers"

(Squid: Added SquidMan link)
(Described the new proxy feature of grunt dev)
Line 2: Line 2:
 
<div class="title">Debugging production servers</div>
 
<div class="title">Debugging production servers</div>
  
A how-to for debugging your local UI plugin in combination with production and staging servers, which use redirects, HTTPS, and other things which break with a simple <tt>grunt dev</tt> command.
+
A how-to for debugging your local UI plugin in combination with production and staging servers, which use redirects, HTTPS, and other things which break with the auto-generated Grunt configuration.
  
 
== Introduction ==
 
== Introduction ==
Line 8: Line 8:
 
Not everybody has access to a dedicated test server. Sometimes, a plugin requires a backend system which is hard to access outside of existing infrastructure. And sometimes, a bug appears only on a production server. There are many reasons why a server which is used by <tt>grunt dev</tt> can not be reconfigured and has to be used as-is.
 
Not everybody has access to a dedicated test server. Sometimes, a plugin requires a backend system which is hard to access outside of existing infrastructure. And sometimes, a bug appears only on a production server. There are many reasons why a server which is used by <tt>grunt dev</tt> can not be reconfigured and has to be used as-is.
  
The most frequent reason, why debugging with a remote server fails, are redirects to an external login page. After the login, the browser is usually redirected to the original domain, and all the cookies used for authentication are also set for that domain, not http://localhost:8337, where Grunt listens.
+
The most frequent reason, why debugging with a remote server fails, is a redirect to an external login page. After the login, the browser is usually redirected to the original domain, and all the cookies used for authentication are also set for that domain, not http://localhost:8337, where Grunt listens.
  
The solution is to use a proxy server, which redirects all requests to the server's domain to Grunt. Until <tt>grunt dev</tt> can be used as an HTTP proxy directly, a dedicated proxy is required. This proxy needs to support custom hosts files. Any kind of rewriting or forwarding usually ends up in the wrong domain being used, and therefore still breaking cookies and redirects. The global <tt>/etc/hosts</tt> can't be used because Grunt still needs to access the original server, and use the original domain name for that to properly set the <tt>Host</tt> header.
+
The solution is to use grunt as an HTTP proxy server, which intercepts all requests to the server's domain.
  
The usual way to use a custom hosts file is to set it in the <tt>HOSTALIASES</tt> environment variable. Unfortunately, for security reasons, this variable is explicitly cleared when executing setuid processes. And this is exactly what proxy servers tend to do. A proxy server with explicit configuration support for custom hosts files is Squid. So that's what we will use for debugging.
+
In this article, <tt>''example.com''</tt> is user for the server domain, which you should replace by the real domain of the OX server.
  
== HOWTO ==
+
== Configuring Grunt ==
  
All commands are specified for Debian. Commands which need to be run as root start with <tt>#</tt>, commands which can be run as a normal user start with <tt>$</tt>.
+
Following is an example <tt>grunt/local.conf.json</tt> file:
  
The examples use <tt>''user''</tt> as user name, and all temporary files are stored in <tt>/home/''user''/proxy</tt>. You should use your own directory, and can pick any other directory. For the server domain, we'll use <tt>''example.com''</tt>, which should of course be replaced by the real domain of the OX server.
+
{
 +
    "proxy": true,
 +
    "appserver": {
 +
        "protocol": "https",
 +
        "livereload": false,
 +
        "server": "https://''example.com''/''custom-path''/",
 +
        "path": "/''custom-path''/",
 +
        "rejectUnauthorized": false,
 +
        "verbose": [],
 +
        "prefixes": [
 +
            "build/",
 +
            "../../web/ui/build"
 +
        ],
 +
        "manifests": [
 +
            "build/manifests/",
 +
            "../../web/ui/build/manifests"
 +
        ]
 +
    },
 +
    "debug": true,
 +
    "coreDir": "../../web/ui/build"
 +
}
  
=== Squid ===
+
The relevant settings are:
  
Install Squid.
+
;<tt>"proxy": true</tt>
 +
: instructs Grunt to start an HTTP proxy on port 8080. Note that the value is outside the <tt>"appserver"</tt> section.
 +
;<tt>"protocol": "https"</tt>
 +
: to use HTTPS on port 8337.
 +
;<tt>"livereload": false</tt>
 +
: because LiveReload can't be proxied.
 +
;<tt>"path": "/''custom-path''/"</tt>
 +
: must correspond to the path in the <tt>"server"</tt> entry and can be omitted if it's <tt>"/appsuite/"</tt>.
 +
;<tt>"rejectUnauthorized": false</tt>
 +
: is helpful with certificate problems, especially for integration tests of the login mechanism on a POC system with self-signed certificates.
 +
;<tt>"index": "/"</tt>
 +
: If the main path uses an HTTP redirect for a custom login page, then the initial request should not be intercepted by Grunt. Adding this entry in the <tt>"appserver"</tt> section disables the interception. This has two side-effects:
 +
:# The main HTML file is always served by the original server, and therefore
 +
:# The timestamps used for cache-busting are not updated by Grunt.
 +
:Unfortunately, this means clearing the cache will be required more often. If that becomes too much overhead, you can log in, then remove the option and restart Grunt.
  
# apt-get install squid3
+
After the configuration is complete, Grunt is started like always with
  
Copy your <tt>/etc/hosts</tt> file to another location.
+
grunt dev
  
$ cp /etc/hosts /home/''user''/proxy/hosts
+
== Launching the browser ==
  
Add a line which redirects the target domain to localhost.
+
Now that the proxy is running, you just need to use it when debugging your code in the browser. Most browsers have their own proxy settings, which override system-wide settings. They also respect environment variables like <tt>http_proxy</tt>.
  
  $ echo '127.0.0.1 ''example.com''<nowiki/>' >> /home/''user''/proxy/hosts
+
  http_proxy=http://localhost:8080 firefox
 
 
Now this file can be added to Squid's configuration file.
 
 
 
# echo 'hosts_file /home/''user''/proxy/hosts' >> /etc/squid3/squid.conf
 
# service squid3 reload
 
 
 
For Macs, there's [http://squidman.net/squidman/ SquidMan]. It has a preferences item where you can edit the configuration file.
 
 
 
=== Grunt ===
 
 
 
Assuming you already have a working <tt>local.conf.json</tt>, add the following entries to the <tt>"appserver"</tt> section:
 
 
 
"protocol": "https",
 
"port": 443,
 
"server": "https://''example.com''/''custom-path''/",
 
"rejectUnauthorized": false,
 
"path": "/''custom-path''",
 
 
 
The entry <tt>"path"</tt> is optional, if the default <tt>/appsuite</tt> is used.
 
 
 
If the main path uses an HTTP redirect for a custom login page, then the initial request can't be intercepted by Grunt. The following entry disables it:
 
 
 
"index": "/",
 
 
 
This has two side-effects:
 
# The mail HTML file is always served by the original server, and therefore
 
# The timestamps used for cache-busting are not updated by Grunt.
 
 
 
This means clearing the cache will be required more often. If that becomes too much overhead, you can log in, then remove the option and restart Grunt.
 
 
 
=== Running <tt>grunt dev</tt>===
 
 
 
Since Grunt needs to bind to port 443, it requires additional privileges. There are several options. Running Grunt as root is the quickest, but also least secure way. Better alternatives are <tt>authbind</tt> and <tt>setcap</tt>.
 
 
 
Don't forget to stop your local web server (e.g. Apache),
 
 
 
# service apache2 stop
 
 
 
or at least disable SSL.
 
 
 
# a2dismod ssl
 
# service apache2 restart
 
 
 
==== <tt>authbind</tt> ====
 
 
 
<tt>authbind</tt> is a program which uses a setuid helper to bind to lower ports. It is usually not installed by default.
 
 
 
# apt-get install authbind
 
 
 
The configuration is performed by creating files in <tt>/etc/authbind</tt> and giving execute permissions to the appropriate users.
 
 
 
# touch /etc/authbind/443
 
# chown ''user'' /etc/authbind/443
 
# chmod 544 /etc/authbind
 
 
 
Now, Grunt can be started using the wrapper.
 
 
 
$ authbind --deep grunt dev
 
 
 
==== <tt>setcap</tt> ====
 
 
 
This option can be used if your file system supports capabilities. It is less secure since it grants the permission to bind to all low ports to any Node program. But if supported, it at least does not require additional tools.
 
 
 
# setcap "cap_net_bind_service=+ep" "$(readlink -f "$(which node)")"
 
 
 
On OS X, <tt>greadlink</tt> needs to be used instead of <tt>readlink</tt>. If you don't have it, just find out where the actual <tt>node</tt> binary is installed and use it directly as the second parameter to <tt>setcap</tt>.
 
 
 
Grunt can then be run as usual.
 
 
 
$ grunt dev
 
 
 
=== Launching the browser ===
 
 
 
Now that everything is running, you only need to use the proxy when debugging your code in the browser. Most browsers have their own proxy settings, which override system-wide settings. They also respect environment variables like <tt>http_proxy</tt>.
 
 
 
$ http_proxy=http://localhost:3128 firefox
 
  
 
Chrome does not have its own settings (it starts the global settings dialog) and it ignores http_proxy. Instead, you have to use a command line parameter:
 
Chrome does not have its own settings (it starts the global settings dialog) and it ignores http_proxy. Instead, you have to use a command line parameter:
  
  $ chromium --proxy-server=http://localhost:3128
+
  chromium --proxy-server=http://localhost:8080

Revision as of 09:30, 22 September 2015

API status: In Development

Debugging production servers

A how-to for debugging your local UI plugin in combination with production and staging servers, which use redirects, HTTPS, and other things which break with the auto-generated Grunt configuration.

Introduction

Not everybody has access to a dedicated test server. Sometimes, a plugin requires a backend system which is hard to access outside of existing infrastructure. And sometimes, a bug appears only on a production server. There are many reasons why a server which is used by grunt dev can not be reconfigured and has to be used as-is.

The most frequent reason, why debugging with a remote server fails, is a redirect to an external login page. After the login, the browser is usually redirected to the original domain, and all the cookies used for authentication are also set for that domain, not http://localhost:8337, where Grunt listens.

The solution is to use grunt as an HTTP proxy server, which intercepts all requests to the server's domain.

In this article, example.com is user for the server domain, which you should replace by the real domain of the OX server.

Configuring Grunt

Following is an example grunt/local.conf.json file:

{
    "proxy": true,
    "appserver": {
        "protocol": "https",
        "livereload": false,
        "server": "https://example.com/custom-path/",
        "path": "/custom-path/",
        "rejectUnauthorized": false,
        "verbose": [],
        "prefixes": [
            "build/",
            "../../web/ui/build"
        ],
        "manifests": [
            "build/manifests/",
            "../../web/ui/build/manifests"
        ]
    },
    "debug": true,
    "coreDir": "../../web/ui/build"
}

The relevant settings are:

"proxy": true
instructs Grunt to start an HTTP proxy on port 8080. Note that the value is outside the "appserver" section.
"protocol": "https"
to use HTTPS on port 8337.
"livereload": false
because LiveReload can't be proxied.
"path": "/custom-path/"
must correspond to the path in the "server" entry and can be omitted if it's "/appsuite/".
"rejectUnauthorized": false
is helpful with certificate problems, especially for integration tests of the login mechanism on a POC system with self-signed certificates.
"index": "/"
If the main path uses an HTTP redirect for a custom login page, then the initial request should not be intercepted by Grunt. Adding this entry in the "appserver" section disables the interception. This has two side-effects:
  1. The main HTML file is always served by the original server, and therefore
  2. The timestamps used for cache-busting are not updated by Grunt.
Unfortunately, this means clearing the cache will be required more often. If that becomes too much overhead, you can log in, then remove the option and restart Grunt.

After the configuration is complete, Grunt is started like always with

grunt dev

Launching the browser

Now that the proxy is running, you just need to use it when debugging your code in the browser. Most browsers have their own proxy settings, which override system-wide settings. They also respect environment variables like http_proxy.

http_proxy=http://localhost:8080 firefox

Chrome does not have its own settings (it starts the global settings dialog) and it ignores http_proxy. Instead, you have to use a command line parameter:

chromium --proxy-server=http://localhost:8080