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

control delete permission separately from write permission #478

Open
rptaylor opened this issue Feb 3, 2023 · 4 comments
Open

control delete permission separately from write permission #478

rptaylor opened this issue Feb 3, 2023 · 4 comments
Labels
docs Related to the documentation

Comments

@rptaylor
Copy link

rptaylor commented Feb 3, 2023

What is the idea ?

ARA_WRITE_LOGIN_REQUIRED
"Determines if authentication is required before being authorized to post data"

ARA_READ_LOGIN_REQUIRED
"Determines if authentication is required before being authorized to query all API endpoints"

If interpreted literally, it sounds like ARA_WRITE_LOGIN_REQUIRED might only allow POST operations.
But the CLI and API support delete operations for plays, tasks, etc. which I am guessing would be considered a write operation and would be controlled by ARA_WRITE_LOGIN_REQUIRED.
Considering that this is based on Django REST framework permissions, it would be useful to have documented exactly which operations are controlled by these settings.

What I really want is to allow unauthenticated append (POST) operations, but require authentication for all read (GET, HEAD) and delete (DELETE) operations. The use case is having a large fleet of servers and not wanting to configure write credentials on them, and in particular to allow the plays to run quickly without being slowed down by Django authentication when writing output to the server.
Our consideration on security is that it's not terribly bad if a malicious actor can write fake data to ARA without authentication, but we can not allow reading, deletion, or modification of existing data without authentication.

It's hard to tell from the docs but hopefully Ara is already append-only, i.e. records written to the database should be immutable, so PUT and PATCH are never allowed by the API?

Anyway if I interpreted the docs correctly, would it be possible to have something like ARA_DELETE_LOGIN_REQUIRED, so that unauthenticated (append-only) writes are possible, but deletion requires authentication?

@rptaylor
Copy link
Author

rptaylor commented Feb 3, 2023

I found more documentation here that clarifies "you can enable authentication against the API for read (ex: GET) and write (ex: DELETE, POST, PATCH) requests."

Those three types of operations (delete a record, write a new record, change an existing record) could have very different security considerations from each other. Would it make sense to make new settings, something like ARA_DELETE_LOGIN_REQUIRED, ARA_CREATE_LOGIN_REQUIRED, ARA_CHANGE_LOGIN_REQUIRED to control each of them separately? To preserve compatibility, the value of each one could default to ARA_WRITE_LOGIN_REQUIRED.

It looks like the code for that is here but I'm not sure how the Django REST framework works.

@dmsimard
Copy link
Contributor

dmsimard commented Feb 8, 2023

Hey @rptaylor and thanks for the issue.

I understand the use case and it's a valid one.

The ARA_WRITE_LOGIN_REQUIRED and ARA_READ_LOGIN_REQUIRED settings control the behavior of the built-in Django authentication backend. You've found the entirety of that code already: it is designed to be simple with just a few lines of code.

Generally speaking, there are no plans to implement more granular permissions or full-blown RBAC in ara at this time.

However, what users with similar use cases have done in the past -- and it is actually what the documentation recommends -- is to use a reverse proxy (such as nginx or apache) in front of the server to handle authentication and authorization instead of django.

Handling authentication in django has non-negligible performance drawbacks and using a reverse proxy gives you the flexibility of handling different endpoints (or HTTP methods) according to your needs.

I don't have an example on hand right now but in both apache and nginx, you can have different authentication methods (or none at all) depending on whether it is a GET, a POST/PUT/PATCH or a DELETE.
In fact there is an issue about supporting a "read-only" configuration via nginx in ara-collection which would leverage this mechanism: ansible-community/ara-collection#50

It's hard to tell from the docs but hopefully Ara is already append-only, i.e. records written to the database should be immutable, so PUT and PATCH are never allowed by the API?

The database is not immutable. The web reporting interface does not implement edition or deletion (on purpose) but the CLI provides commands to delete and prune playbooks. There are no implementations that allow users to edit things that I know of but the API allows for editing.

For example, the callback first does a POST to create a playbook in the database when the playbook begins and then once the playbook ends it sends a PATCH to update the end date and duration of the playbook.

There's nothing that uses PUT right now, at least to my knowledge.

I hope this helps!
If you end up writing an apache or nginx configuration that works for you, we can consider adding it to the docs.

@dmsimard dmsimard added the docs Related to the documentation label Feb 8, 2023
@rptaylor
Copy link
Author

Handling authentication in django has non-negligible performance drawbacks and using a reverse proxy gives you the flexibility of handling different endpoints (or HTTP methods) according to your needs.

Yes, but I was hoping to improve performance by allowing writes to be performed without requiring a login, bypassing the slowness of Django authn.

I am running Ara on k8s , it would be nice if it had built in functionality for this. If I have to make my own authenticating proxy I would maybe try implementing it with Traefik ingress rules and middlewares but that could be complex.

Anyway a question @dmsimard , I noticed the admin interface allows you to add user permissions such as "API | file | Can add file" etc, but these don't seem to do anything? Do all users have all capabilities regardless of what permissions are set there?

Thanks!

@dmsimard
Copy link
Contributor

Sorry for not replying until now, @rptaylor.

I am not all that familiar with the django admin interface. It is possible that these knobs might work but that would be news to me. In other words: there is no intentional support for granular RBAC but it could be possible that it comes "for free" like many things in django.

If it works we can add it to the docs.

Otherwise, to my knowledge, either you have access to everything or you don't. The loose concept of "read only" comes from leaving ARA_READ_LOGIN_REQUIRED to false while ARA_WRITE_LOGIN_REQUIRED is true.

You can also implement a similar concept with a reverse proxy in front by filtering on POST/PATCH/DELETE like I mentioned in my previous comment.

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

No branches or pull requests

2 participants