Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Alternative white lisiting method because configuration.allowlist_regexp is error prone #71

Open
TildeWill opened this issue Apr 9, 2019 · 6 comments

Comments

@TildeWill
Copy link

The pain of #61 highlights that this regex is cumbersome to maintain. In referrals, we have an entry that looks like this:

  configuration.allowlist_regexp = %r{\A/(referrals\/api\/contacts|referrals\/api\/referrals|assets|client|referrals\/api\/docs|referrals\/proof_of_life|referrals\/resque|referrals\/teaspoon)}

It turns out that there was an overly permissive entry in there which essentially white listed all of the referrals API - not desirable and tests are being back filled.

I'd like to add something that's a bit easier to read/maintain. I spent some time trying to replace the middleware by creating a Rails custom constraint. Constraints have a handle on the request, but not on the response and so I ran into trouble when trying to replicate these lines:

env[@configuration.env_var_to_hold_api_client_primary_key] = client.id
env[@configuration.env_var_to_hold_api_client] = client

Is there a) still a need for these lines, and b) a way to move them out of the middleware? Or maybe some third way to make it more obvious in routes.rb what does/does not require the api_key? A less desirable option would be to add a before_filter in the controllers but I'm guessing that choice was avoided on purpose?

@davetron5000
Copy link
Contributor

The thinking was that a micro service would not have a ton of non-authed routes. The app you are referring too is a full stack app that exposes a microservice, which is a pattern we recommend against and that we should avoid. I think this is why your allow list is so complicated.

The simplest way I can think of to clean it up would be to accept an array of regexps:

configuration.allow_list = [
  "/referrals/foo",
  "/resque-web",
  # etc.
]

and then wrap those with %r{\a{#val}\Z} or something.

I'm not understanding how this plays into the need to store the api client in the environment that. Those should be totally separate concerns from what is allowed/denied.

@TildeWill
Copy link
Author

I think this is why your allow list is so complicated.

Correct. The team is taking steps to move to the recommended architecture in this specific case.

The simplest way I can think of to clean it up would be to accept an array of regexps:

configuration.allow_list = [
  "/referrals/foo",
  "/resque-web",
  # etc.
]

and then wrap those with %r{\a{#val}\Z} or something.

That would be a big improvement in readability within the Stitches initializer within an app and would address some of the pain. But the discoverability of the allow_list is still pretty poor when you're rolling in to an application and trying to understand why some endpoints give you a 401 and others don't. I want to move API auth to a place that is closer to where someone might look, such as in routes.rb or in the controller.

@davetron5000
Copy link
Contributor

Yeah, the allow list was added kinda hastily as we realized we needed a way to easily opt out some routes from auth—I would agree it's a "thing about routing" and thus kinda belongs in the routes file (thus your point that it's more discoverable). The main "feature" I would want to keep is "auth by default", i.e if you add a route in config/routes.rb in "the normal Rails Way" it should require auth. I think a routing constraint could do this?

@TildeWill
Copy link
Author

I think a routing constraint could do this?

Correct.

What it can't do is set the client on the response as is currently happening here:

env[@configuration.env_var_to_hold_api_client_primary_key] = client.id
env[@configuration.env_var_to_hold_api_client] = client

@davetron5000
Copy link
Contributor

It might not need to, but to leave the api_key middleware in would require two lookups to the api client per request. I guess the proposed routing constraint could simply check for the existence of the key in the header and handle the allow list and we keep the middleware the same? I dunno, we'll have to think this through.

@TildeWill
Copy link
Author

I'll put a PR together to give us something concrete to point to

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants