If we make the proxy not do auth, we put a hard requirement on the service to do it, and, in some cases that may be something we can't control. Think of some of the metrics data sources that you could have that are proprietary and not integrated with TO at all; we currently "pull those through" the TO monolith, and this cleans that up IMO.
On Mon, May 8, 2017 at 8:42 AM Robert Butts <[email protected]> wrote: > > couldn't make nginx or http do what we need. > > I was suggesting a different architecture. Not making the proxy do auth, > only standard proxying. > > > We can still have the services check the auth as well after the proxy > auth > > +1 > > > On Mon, May 8, 2017 at 3:36 AM, Amir Yeshurun <[email protected]> wrote: > > > Hi, > > > > Let me elaborate some more on the purpose of the API GW. I will put up a > > wiki page following our discussions here. > > > > Main purpose is to allow innovation by creating new services that handle > TO > > functionality, not as a part of the monolithic Mojo app. > > The long term vision is to de-compose TO into multiple microservices, > > allowing new functionality easily added. > > Indeed, the goal it to eventually deprecate the current AAA model, and > > replace it with the new AAA model currently under work (user-roles, > > role-capabilities) > > > > I think that handling authorization in the API layer is a valid approach. > > Security wise, I don't see much difference between that, and having each > > module access the auth service, as long as the auth service is deployed > in > > the backend. > > Having another proxy (nginx?) fronting the world and forwarding all > > requests to the backend GW mitigates the risk for compromising the > > authorization service. > > However, as mentioned above, we can still have the services check the > auth > > as well after the proxy auth. > > > > It is a standalone process, completely optional at this point. One can > > choose to deploy it in order to allow integration with additional > > services. Deployment > > and management are still T.B.D, and feedback on this is most welcome. > > > > Regarding token validation and revocation: > > Tokens have expiration time. Expired tokens do not pass token validation. > > In production, expiration should be set to relatively short time, say 5 > > minute. > > This way revocation is automatic. Re-authentication is handled via > refresh > > tokens (not implemented yet). Hitting the DB upon every API call cause > > congestion on users DB. > > To avoid that, we chose to have all user information self-contained > inside > > the JWT. > > > > Thanks > > /amiry > > > > On Mon, May 8, 2017 at 5:42 AM Jan van Doorn <[email protected]> wrote: > > > > > It's the reverse proxy we've discussed for the "micro services" version > > for > > > a while now (as in > > > https://cwiki.apache.org/confluence/display/TC/Design+Overview+v3.0). > > > > > > On Sun, May 7, 2017 at 7:22 PM Eric Friedrich (efriedri) < > > > [email protected]> > > > wrote: > > > > > > > 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]> 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] > > > > > > > > > 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]> > > > 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]> > > > 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]> > > > > 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 > > > > >>>>> > > > > >>>> > > > > >>> > > > > >> > > > > > > > > > > > > > >
