Closed Bug 1365662 Opened 6 years ago Closed 6 years ago

Restrict access to OrangeFactor to users with LDAP credentials


(Tree Management Graveyard :: OrangeFactor, enhancement, P1)



(Not tracked)



(Reporter: emorley, Assigned: emorley)




(3 files)

To reduce exposure to the issues in bug 1356410, it has been proposed that we put OrangeFactor behind auth and limit access to staff/NDA contributors (bug 1356410 comment 27).

Of note, the OrangeFactor API is consumed by the Bugzilla OrangeFactor extension, however:

(In reply to Ed Morley [:emorley] from bug 1356410 comment #29)
> * The "link to orangefactor" functionality (which I think is the most useful
> part) will still work
> (
> 20c1dbebae25818af68e68b77b8e33b76720c3c4/extensions/OrangeFactor/template/en/
> default/hook/bug_modal/edit-details_rhs.html.tmpl#L22)
> * The "display graph / count" functionality:
>  - fails gracefully
> (
> 20c1dbebae25818af68e68b77b8e33b76720c3c4/extensions/OrangeFactor/web/js/
> orange_factor.js#L84-L86)
>  - will presumably still work so long as users have authenticated via the
> OrangeFactor site first
> * the usage is very low (off by default, has to be enabled in Bugzilla
> prefs) - I'm guessing single digit users who actually use it
> such IMO it needn't block.

In addition I'd forgotten about the submissions Treeherder makes to Elasticsearch via Hawk-authenticated POSTs to:

...though given that's behind Hawk auth (and we can add additional payload validation there), I believe it would be fine to exclude that endpoint from SSO auth.

As far as implementation:

(In reply to Eric Ziegenhorn :ericz from bug 1356410 comment #33)
> Kang, orangefactor is served with nginx on brasstacks1.dmz.scl3 and webops
> has not implemented SSO with nginx yet -- do you have a preferred SAML
> authenticator for nginx and could you help us estimate the level of effort
> here as compared to say mod_mellon with Okta?

(In reply to Guillaume Destuynder [:kang] (NEEDINFO to ensure replies) from bug 1356410 comment #34)
> @:ericz has a demo of the nginx access
> proxy for SSO which is the recommended solution. It uses OIDC and cares for
> session management, etc. on your behalf. The nginx side setup is documented
> with guide and config examples at
> Credentials can be requested via
> (theres a
> link to request them in there together with some docs)
> Feel free to ping me directly if you run into any issue or have questions
> though!
Another complication:

There are scripts that run on brasstacks that connect to the API that we'll need to route around the SSO (presumably by using multiple nginx location blocks).

What I've dug up about brasstacks so far:

RHEL 6.9
Python 2.6.6

The nginx configs in /etc/nginx/* were a bit of a mess with backup versions of files around etc, so I gzipped the folder and left a backup at /root/nginx-backup.tar.gz, then pruned unused content for clarity.

/etc/nginx/nginx.conf seems to be entirely the stock config, and includes /etc/nginx/conf.d/*.conf

The only config there is /etc/nginx/conf.d/orangefactor.conf (I'll attach shortly), which includes /etc/nginx/default_locations/orangefactor.conf.

The locations file does a `fastcgi_pass`.

The backend service is run by /etc/init.d/orangefactor (monitored/managed by monit), which uses /usr/bin/spawn-fcgi to run woo_server.fcgi with the OrangeFactor venv Python:
Attachment #8868693 - Attachment description: Existing /etc/nginx/orangefactor.conf → Existing /etc/nginx/conf.d/orangefactor.conf
We need to switch from stock nginx to openresty (nginx variant with lua support), and openresty's configs live in a different location etc, so the existing configs will need migrating before we get to setting the SSO parts up.

As such, the plan is:
1) Request client credentials using process at
2) Install openresty, luarocks and lua-resty-openidc
3) Create new configs under /usr/local/openresty/... based on the existing nginx ones (also find a generic location for SSL keys rather than their existing nginx-specific home, move the static html directory somewhere more sensible etc)
4) Test by modifying the configs to listen on different ports, starting openresty and making requests to localhost
5) If working, stop openresty, switch ports back to expected values, stop nginx and start openresty
6) Ensure openresty run at boot and nginx not
7) Add a new server block that listens on a different port, that I can use to test adding the lua-resty-openidc specific parts and ensuring we can localhost and the Hawk-protected /api/saveclassification page
8) When SSO client credentials received, add them to the config file
9) If all looks good, apply the SSO config to the main port 443 server block
10) Notify about site now requiring SSO
> 1) Request client credentials using process at


> 2) Install openresty, luarocks and lua-resty-openidc

[root@brasstacks1.dmz.scl3 ~]# yum-config-manager --add-repo esty.repo
repo saved to /etc/yum.repos.d/OpenResty.repo

[root@brasstacks1.dmz.scl3 ~]# yum install epel-release
Package epel-release-6-8.noarch already installed and latest version

[root@brasstacks1.dmz.scl3 ~]# yum install openresty
  openresty.x86_64 0:

Dependency Installed:
  openresty-openssl.x86_64 0:1.0.2k-1.el6             openresty-pcre.x86_64 0:8.40-1.el6
  openresty-zlib.x86_64 0:1.2.11-1.el6

[root@brasstacks1.dmz.scl3 ~]# openresty -V
nginx version: openresty/
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-18) (GCC)
built with OpenSSL 1.0.2k  26 Jan 2017
TLS SNI support enabled
configure arguments: --prefix=/usr/local/openresty/nginx <SNIP>

[root@brasstacks1.dmz.scl3 ~]# yum install luarocks
  luarocks.noarch 0:2.1.2-1.el6

[root@brasstacks1.dmz.scl3 ~]# yum install luarocks openssl-devel lua-devel
  lua-devel.x86_64 0:5.1.4-4.1.el6

[root@brasstacks1.dmz.scl3 ~]# luarocks install lua-resty-openidc
lua-resty-openidc 1.3.1-1 is now built and installed in /usr (license: Apache 2.0)

[root@brasstacks1.dmz.scl3 ~]# luarocks path
export LUA_PATH='/usr/share/lua/5.1/?.lua;/usr/share/lua/5.1/?/init.lua;/root/.luarocks/share/lua/5.1/?.lua;/root/.luarocks/share/lua/5.1/?/init.lua;./?.lua;/usr/lib64/lua/5.1/?.lua;/usr/lib64/lua/5.1/?/init.lua'
export LUA_CPATH='/usr/lib/lua/5.1/?.so;/root/.luarocks/lib/lua/5.1/?.so;./?.so;/usr/lib64/lua/5.1/?.so;/usr/lib64/lua/5.1/'
Steps 1-7 from comment 4 are now complete. 

In addition, I have:
* Fixed the issues with the port 80 server block, that were preventing it from being used by cron scripts locally (required so they can skip SSO later).
* Added and tested the SSO exemptions for localhost and /api/saveclassification
* Updated woo_cron.conf so the cron jobs use localhost:80 not, so they can skip SSO.
* Made openidc_layer.lua load globally (so I can check the LUA libs are loading fine), but return early unless accessing or the callback/login URLs.
* Updated the TLS configuration with the latest changes from the Mozilla config generator [1]. Notably:
  - HTTP2 is now enabled and working [2].
  - OCSP stapling is now enabled and working [3].
* Reworked the OrangeFactor static assets location block, so it serves them from the source html directory rather than having to sync them across after each deploy to the stock nginx html directory.
* Raised the nginx error_log level from error to warn to make the logs more useful.
* Cleared out a number of leftovers from autolog/mozmill-dashboard/other services that used to run on the box, to make it easier to see what's left.

Left to do (revised plan from that in comment 4):
8) Wait for Auth0 credentials
9) Once received, update openidc_config.lua and `sudo service openresty reload`.
10) Test SSO works using and tweak as needed.
11) If working, remove conditionals in openidc_layer.lua that return early for anything but the test pages, and `sudo service openresty reload`.
12) Check the exemptions correctly don't hit SSO, using:
  - `curl -I http://localhost/orangefactor/api/count` (from brasstacks)
  - `curl -IX POST` (expected to HTTP 401)
13) Check SSO works for:
14) Check Treeherder submissions not reporting errors on New Relic.
15) Announce that SSO auth now required for OrangeFactor.
16) Move or rename old nginx configuration directory since it should in theory not be used by anything.
17) Check the next round of cron jobs after SSO enabling ran ok.
18) Attach the config files (minus openidc_config.lua secrets) to this bug or else commit them to the orangefactor repo.
19) After X amount of time, remove the old nginx config directory and uninstall nginx (to avoid confusion when people looking at the box in the future).

I'm also going to be collating docs rough edges and filing issues to help improve:

See Also: → 1367107
(In reply to Ed Morley [:emorley] from comment #5)
> > 1) Request client credentials using process at
> >
> Opened:

Justin, I don't suppose you know when you might be able to look at this Auth0 credential request ticket? :-)
Flags: needinfo?(jdow)
Depends on: 1368739
The SSO credentials were issued Friday evening (26th) - I've now updated the config on brasstacks to use them.

The test page worked well for me and also for non-staff contributor LDAP, so I've now enabled SSO site-wide, using steps 9-16 from comment 6, and emailed the mailing lists:!topic/
Flags: needinfo?(jdow)
OrangeFactor has never set its own Cache-Control headers on static assets including the index page, so I've had to add one to ensure that when the SSO expires the browser still gets the redirect on the index page, rather than just seeing it only on the API XHRs.
Depends on: 1369481
Further tweaks:
* yesterday I reduced caching from 60s to zero (since it broke the callback):
* I've adapted the BMO OrangeFactor integration to work with the SSO in bug 1368739.
* Bug 1369481 has fixed an omission in the SSO example configs that meant the session cookie was 1 hour and so the refresh process didn't work, with returning visitors being treated as new users.
* I've performed the old nginx install cleanup/remaining steps from comment 6.

I've issues against the example SSO configs for some potential improvements:

With that, I think we're done :-)
Closed: 6 years ago
Resolution: --- → FIXED
For anyone wanting to access OrangeFactor's API in an automated manner, I'd recommend either:
* Using to fetch the browser SSO cookie for (NB: the automation will need to use the same User Agent as the browser for the session to work)
* Pulling data from ActiveData ( ; the `orange_factor` index) or Treeherder's API instead (!/project/project_bug_job_map_list ; though at present the API cannot retrieve by bug, just by job_id).
Group: mozilla-employee-confidential
Product: Tree Management → Tree Management Graveyard
You need to log in before you can comment on or make changes to this bug.