Man-in-the-middle yourself:
Debugging Production Web Apps
Ben Ripkens
Slide 2
Slide 2 text
Ben Ripkens
Lead Web Engineer – Instana
Slide 3
Slide 3 text
No content
Slide 4
Slide 4 text
Debugging Production Web Apps
Getting Informed About Problems
of the JavaScript which is
executed in our users’ browsers
Slide 5
Slide 5 text
No content
Slide 6
Slide 6 text
No content
Slide 7
Slide 7 text
TrackJS is on the right track
not affiliated
but lacks crucial
source map features
Slide 8
Slide 8 text
undefined is not an object
(evaluating 'r.get(\"data\").get(\"keyspaces\").sort)
at render (index.js:1:32487)
Error occurred at 2016-01-15T08:31:04.874Z
So, which source map was deployed at
that time on that machine?
Slide 9
Slide 9 text
No content
Slide 10
Slide 10 text
At Instana we apply source
maps automatically
at the moment the
error is reported
and send reports
to Slack
Slide 11
Slide 11 text
level: "error"
logger: "in-component.Jail"
serverTime: "2016-01-15T12:32:12.835Z"
user:
id: "569665348c5bea000d52e153"
email: "[email protected]"
version:
revision: "7b7fa6ceb1960bdd5a139855e71f856dd75c90c6"
date: "2016-01-15T08:31:04.874Z"
url: “https://demo.instana.io/#/dashboard?pluginId=cassandraNode…”
userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_1) AppleWebKit…”
platform: "MacIntel"
error:
message: "undefined is not an object (evaluating 'r.get(\"data\").get(\"keyspaces
\").sort')"
readableStack:
- "at sort (webpack:///in-forge/cassandraNode/Dashboard/Content.es6:41:60)"
- "at render (webpack:///~/react/lib/ReactCompositeComponent.js:767:0)"
- "at _renderValidatedComponentWithoutOwnerOrContext (webpack:///~/react/lib/
ReactCompositeComponent.js:793:0)"
- "at _renderValidatedComponent (webpack:///~/react/lib/ReactCompositeComponent.js:
227:0)"
- "at rootID (webpack:///~/react/lib/ReactReconciler.js:38:0)"
- "much more stuff…"
Slide 12
Slide 12 text
Objective:
Fix issues before they are noticed by users
Slide 13
Slide 13 text
Debugging Production Web Apps
Debugging and Fixing Code
Slide 14
Slide 14 text
remote
debugging
workflow
try to get source
maps to work
endlessly navigate because
code looks different
realise that we cannot
add code to verify
assumptions
try to fix code locally
fail because we didn’t have
access to production data
Slide 15
Slide 15 text
local
development
workflow
Inspect Result
Write Code
Think
Slide 16
Slide 16 text
How can we align the
remote debugging workflow
with the
local development workflow ?
Slide 17
Slide 17 text
1. Use the same application version,
2. in the same configuration,
3. with the same data,
4. in the same browser,
5. on the same platform,
6. in the same environment.
Debugging Workflow Requirements
Slide 18
Slide 18 text
1. Use the same application version,
2. in the same configuration,
3. with the same data,
4. in the same browser,
5. on the same platform.
Debugging Workflow Requirements
Slide 19
Slide 19 text
1. Use the same application version,
2. in the same configuration,
3. with the same data.
Debugging Workflow Requirements
Slide 20
Slide 20 text
$ curl https://demo.instana.io/build.json
{
"revision": "354b1c175759d4572b…",
"version": "1.0.0-prerelease"
}
$ git checkout 354b1c175759d4572b…
Use the version reported with the stack trace
– or –
1. Use the same application version
Slide 21
Slide 21 text
Highly application specific – examples:
2. Use the same configuration
1. Environment variables
2. compilation modes
3. feature flags
Slide 22
Slide 22 text
Browser Local Dev Server
Static Files
XHR
WebSocket
3. Use the same data
Slide 23
Slide 23 text
Browser
Local Dev Server
WebSocket
XHR
Webpack
Static Files
3. Use the same data (contd.)
Slide 24
Slide 24 text
Browser
Local Dev Server
Proxy
Static Files
Webpack
WebSocket / XHR
3. Use the same data (contd.)
Man-In-the-Middle
Slide 25
Slide 25 text
Browser
Component A
(Local)
Component B
(Production)
Component C
(Production)
3. Use the same data (contd.)
Slide 26
Slide 26 text
Demo
See examples in github.com/bripkens/proxrox
Slide 27
Slide 27 text
Looks complicated, but is actually easy to setup!
$ npm install -g proxrox
$ brew install nginx
$ proxrox start .proxrox.yaml
Slide 28
Slide 28 text
port: 4000 # Port to bind to.
root: target/ # Directory with static files.
tls: true # Local HTTPS with self-signed cert.
http2: true # Use HTTP 2 where possible.
proxy:
# Webpack dev server (local).
/: http://127.0.0.1:3000
# Authentication system (production environment).
/auth: https://instana.io
# Error reporting endpoint (demo environment).
/uiTracker/: http://demo.instana.io/,
websocketProxy:
# Data provider (demo environment).
/api/data: http://demo.instana.io/api/data
Slide 29
Slide 29 text
1. Use the same application version,
git checkout!
2. in the same configuration,
Requires some work!
3. with the same data.
Use proxies!
Conclusion
Slide 30
Slide 30 text
Debugging Production Web Apps
Why We Need Proxies
Slide 31
Slide 31 text
HTTP Strict Transport Security
Enforces HTTPS and optionally pins certificates
{
"name": "accounts.google.com",
"include_subdomains": true,
"mode": "force-https",
"pins": "google"
}
Pinned certificates are almost
impossible to work around
Pinning Users
Dropbox
Facebook
Google
SpiderOak
Tor
Twitter
Yahoo