Looks like this topic quieted. I am attempting to summarize the points made into the wiki so it is easier to digest. If my summary is off, or people have more points to make please email on this thread.
A few thoughts: 1. I found a pretty detailed paper on configuring Nginx as an API gateway for microservices but its beyond my technical scope to say if it is relevant. To EF’s point, something like this may be easier than reinventing the wheel. https://www.nginx.com/blog/building-microservices-using-an-api-gateway/ 2. I like the idea of a two-tiered system with mandated auth at the gateway and optional additional auth at the services. I also like the idea that some services or endpoints like data reads for portal charts could be done with less auth overhead than say modifying or building services which should be tightly controlled. 3. I think an attack scenario planning should be built in to the system design at least for likely scenarios. The planning around “fail open” vs. “fail closed” seems pertinent as well as ideas for how we maintain control and the ability to fix affected services in these types of scenarios. Ryan Durfey M | 303-524-5099 CDN Support (24x7): 866-405-2993 or [email protected]<mailto:[email protected]> From: "Eric Friedrich (efriedri)" <[email protected]> Reply-To: "[email protected]" <[email protected]> Date: Sunday, May 7, 2017 at 9:21 PM To: "[email protected]" <[email protected]> Subject: Re: API GW route configuration From a higher level- what is purpose of the API Gateway? It seems like there may have been some previous discussions about API Gateway. Are there any notes or description that I can catch up on? How will it be deployed? (Is it a standalone service or something that runs inside the experimental Traffic Ops)? Is this new component required or optional? —Eric On May 7, 2017, at 8:28 PM, Jan van Doorn <[email protected]<mailto:[email protected]>> wrote: I looked into this a year or so ago, and I couldn't make nginx or http do what we need. We can still have the services check the auth as well after the proxy auth, and make things better than today, where we have the same problem that if the TO mojo app is compromised, everything is compromised. If we always route to TO, we don't untangle the mess of being dependent on the monolithic TO for everything. Many services today, and more in the future really just need a check to see if the user is authorized, and nothing more. On Sun, May 7, 2017 at 11:55 AM Robert Butts <[email protected]<mailto:[email protected]>> wrote: What are the advantages of these config files, over an existing reverse proxy, like Nginx or httpd? It's just as much work as configuring and deploying an existing product, but more code we have to write and maintain. I'm having trouble seeing the advantage. -1 on auth rules as a part of the proxy. Making a proxy care about auth violates the Single Responsibility Principle, and further, is a security risk. It creates unnecessary attack surface. If your proxy app or server is compromised, the entire framework is now compromised. An attacker could simply rewrite the proxy config to make all routes no-auth. The simple alternative is for the proxy to always route to TO, and TO checks the token against the auth service (which may also be proxied), and redirects unauthorized requests to a login endpoint (which may also be proxied). The TO service (and any other service that requires auth) MUST hit the database (or the auth service, which itself hits the database) to verify valid tokens' users still have the permissions they did when the token was created. Otherwise, it's impossible to revoke tokens, e.g. if an employee quits, or an attacker gains a token, or a user changes their password. On Sun, May 7, 2017 at 4:35 AM, Amir Yeshurun <[email protected]<mailto:[email protected]>> wrote: Seems that attachments are stripped on this list. Examples pasted below *rules.json* [ { "host": "localhost", "path": "/login", "forward": "localhost:9004", "scheme": "https", "auth": false }, { "host": "localhost", "path": "/api/1.2/innovation/", "forward": "localhost:8004", "scheme": "http", "auth": true, "routes-file": "innovation.json" }, { "host": "localhost", "path": "/api/1.2/", "forward": "localhost:3000", "scheme": "http", "auth": true, "routes-file": "traffic-ops-routes.json" }, { "host": "localhost", "path": "/internal/api/1.2/", "forward": "localhost:3000", "scheme": "http", "auth": true, "routes-file": "internal-routes.json" } ] *traffic-ops-routes.json (partial)* . . . { "match": "/cdns/health", "auth": { "GET": ["cdn-health-read"] }}, { "match": "/cdns/capacity", "auth": { "GET": ["cdn-health-read"] }}, { "match": "/cdns/usage/overview", "auth": { "GET": ["cdn-stats-read"] }}, { "match": "/cdns/name/dnsseckeys/generate", "auth": { "GET": ["cdn-security-keys-read"] }}, { "match": "/cdns/name/[^\/]+/?", "auth": { "GET": ["cdn-read"] }}, { "match": "/cdns/name/[^\/]+/sslkeys", "auth": { "GET": ["cdn-security-keys-read"] }}, { "match": "/cdns/name/[^\/]+/dnsseckeys", "auth": { "GET": ["cdn-security-keys-read"] }}, { "match": "/cdns/name/[^\/]+/dnsseckeys/delete", "auth": { "GET": ["cdn-security-keys-write"] }}, { "match": "/cdns/[^\/]+/queue_update", "auth": { "POST": ["queue-updates-write"] }}, { "match": "/cdns/[^\/]+/snapshot", "auth": { "PUT": ["cdn-config-snapshot-write"] }}, { "match": "/cdns/[^\/]+/health", "auth": { "GET": ["cdn-health-read"] }}, { "match": "/cdns/[^\/]+/?", "auth": { "GET": ["cdn-read"], "PUT": ["cdn-write"], "PATCH": ["cdn-write"], "DELETE": ["cdn-write"] }}, { "match": "/cdns", "auth": { "GET": ["cdn-read"], "POST": ["cdn-write"] }}, . . . On Sun, May 7, 2017 at 12:39 PM Amir Yeshurun <[email protected]<mailto:[email protected]>> wrote: Attached please find examples for forwarding rules file (rules.json) and the authorization rules file (traffic-ops-routes.json) On Sun, May 7, 2017 at 10:39 AM Amir Yeshurun <[email protected]<mailto:[email protected]>> wrote: Hi all, I am about to submit a PR with a first operational version of the API GW, to the "experimental" code base. The API GW forwarding logic is as follow: 1. Find host to forward the request: Prefix match on the request path against a list of forwarding rules. The matched forwarding rule defines the target's host, and the target's *authorization rules*. 2. Authorization: Regex match on the request path against a list of *authorization rules*. The matched rule defines the required capabilities to perform the HTTP method on the route. These capabilities are compared against the user's capabilities in the user's JWT At this moment, the 2 sets of rules are hard-coded in json files. The files are provided with the API GW distribution and contain definitions for TC 2.0 API routes. I have tested parts of the API, however, there might be mistakes in some of the routes. Please be warned. Considering manageability and high availability, I am aware that using local files for storing the set of authorization rules is inferior to centralized configuration. We are considering different approaches for centralized configuration, having the following points in mind - Microservice world: API GW will front multiple services, not only Mojo. It can also front other TC components like Traffic Stats and Traffic Monitor. Each service defines its own routes and capabilities. Here comes the question of what is the "source of truth" for the route definitions. - Handling private routes. API GW may front non-TC services. - User changes to the AAA scheme. The ability for admin user to makes changes in the required capabilities of a route, maybe even define new capability names, was raised in the past as a use case that should be supported. - Easy development and deployment of new services. - Using TO DB for expediency. I would appreciate any feedback and views on your approach to manage route definitions. Thanks /amiry
