Restricted database user for Django - python

I'm running Django with Postgres database. On top of application-level security checks, I'm considering adding database-level restrictions. E.g. the application code should only be able to INSERT into log tables, and not UPDATE or DELETE from them.
I would manually create database user with appropriate grants for this. I would also need a more powerful user for running database migrations.
My question is, do people practice things like this? Any advice, best practices on using restricted database users with Django?
Edit: To clarify, there's no technical problem, I'm just interested to hear other people's experiences and takeaways. One Django-specific thing is, I'll need at least two DB users: for normal operation and for running migrations. Where do I store credentials for the more privileged user? Maybe make manage.py migrate prompt for password?
As for the reasoning, suppose my app has a SQL injection vulnerability. With privileged user, the attacker can do things like drop all tables. With a more limited user there's slightly less damage potential and afterwards there's some evidence in insert-only log tables.

The way I would try to solve this problem is:
Setup two database connection for the same database but different users:
'default' for unprivileged db user.
'master' for user with full access to the db.
Configure routers to your liking: https://docs.djangoproject.com/en/dev/topics/db/multi-db/
Perform migrations: ./manage.py migrate --database=master
Now that being said, if you have a vulnerability, like a SQL injection, even with a user that can read, it is already a disaster. If you have db backup setup, you shouldn't worry about lost/corrupted data, you should be worrying about data leakage!
On the other hand, there might be other use cases for the proposed problem.

For storing the credentials to the privileged user for management commands, when running manage.py you can use the --settings flag, which you would point to another settings file that has the other database credentials.
Example migrate command using the new settings file:
python manage.py migrate --settings=myapp.privileged_settings

Yes, this is practiced sometimes, but not commonly. The best way to do it is to grant specific privileges on user, not in django. Making such restrictions means that we should not trust application, because it might change some files / data in db in the way that we do not expect it to do so.
So, to sum up: create another user able to create / modify data and user another one with restrictions to use normally.
It's also quite common in companies to create one user to insert data and another one for employees / scripts to access it.

Related

mongodb - app-users vs db-users login?

I am working on an app with a locally stored mongodb instance and I am strugling with the design of how app-users should be stored in order to implement in-app login.
In one hand, Mongodb provides a solid access control and authentication for db users, with the ability to define roles, actions and privileges. So I feel tempted to leverage this to implement my app-users storage.
On the other hand, considering it uses a system collection, I get the feeling, and from at least this thread I am getting it right, that this user management provided by mongodb should be used to manage db-user accounts only (that would be software that access the database), not app-user accounts (people who use the software that access the database).
So I am thinking my storage schema should look something like this:
system.
users #for db-users (apps and services)
other system cols
...
myappdb.
users #for app-users (actual people using the app)
other app cols
...
So, in order to log into my app, I need a first set of credentials (db-user) so the app can log into my db so I can retrieve app-user credentials in order to log this person into my app when they type their own credentials.
Question 1: does this make sense?
Question 2: if yes, how do I hide my db-user credentials then? because I get the feeling this should not be hardcoded and I am not finding a way to make the connection to the database without it being so.
Question 3: if not, what would be an appropriate way to deal with this? links and articles are welcome.

Using web2py for a user frontend crud

I was asked to port a Access database to MySQL and
provide a simple web frontend for the users.
The DB consists of 8-10 tables and stores data about
clients consulting (client, consultant,topic, hours, ...).
I need to provide a webinterface for our consultants to use,
where they insert all this information during a session into a predefined mask/form.
My initial thought was to port the Access-DB to MySQL, which I have done
and then use the web2py framework to build a user interface with login,
inserting data, browse/scroll through the cases and pulling reports.
web2py with usermanagment and a few samples views & controllers and
MySQL-DB is running. I added the DB to the DAL in web2py,
but now I noticed, that with web2py it is mandatory to define every table
again in web2py for it being able to communicate with the SQL-Server.
While struggeling to succesfully run the extract_mysql_models.py script
to export the structure of the already existing SQL DB for use in web2py
concerns about web2py are accumulating.
This double/redundant way of talking to my DB strikes me as odd and
web2py does not support python3.
Is web2py the correct way to fulfill my task or is there better way?
Thank you very much for listening/helping out.
This double/redundant way of talking to my DB strikes me as odd and web2py does not support python3.
Any abstraction you want to use to communicate with your database (whether it be the web2py DAL, the Django ORM, SQLAlchemy, etc.) will have to have some knowledge of the database schema in order to construct queries.
Even if you programmatically generated all the SQL statements yourself without use of an ORM/DAL, your code would still have to have some knowledge of the database structure (i.e., somewhere you have to specify names of tables and fields, etc.).
For existing databases, we aim to automate this process via introspection of the database schema, which is the purpose of the extract_mysql_models.py script. If that script isn't working, you should report an issue on Github and/or open a thread on the web2py Google Group.
Also, note that when creating a new database, web2py helps you avoid redundant specification of the schema by handling migrations (including table creation) for you -- so you specify the schema only in web2py, and the DAL will automatically create the tables in the database (of course, this is optional).

Writing a Django backend program that runs indefinitely -- what to keep in mind?

I am trying to write a Django app that queries a remote database for some data, performs some calculations on a portion of this data and stores the results (in the local database using Django models). It also filters another portion and stores the result separately. My front end then queries my Django database for these processed data and displays them to the user.
My questions are:
How do I write an agent program that continuously runs in the backend, downloads data from the remote database, does calculations/ filtering and stores the result in the local Django database ? Particularly, what are the most important things to keep in mind when writing a program that runs indefinitely?
Is using cron for this purpose a good idea ?
The data retrieved from the remote database belong to multiple users and each user's data must be kept/ stored separately in my local database as well. How do I achieve that? using row-level/ class-instance level permissions maybe? Remember that the backend agent does the storage, update and delete. Front end only reads data (through http requests).
And finally, I allow creation of new users. If a new user has valid credentials for the remote database the user should be allowed to use my app. In which case, my backend will download this particular user's data from the remote database, performs calculations/ filtering and presents the results to the user. How can I handle the dynamic creation of objects/ database tables for the new users? and how can I differentiate between users' data when retrieving them ?
Would very much appreciate answers from experienced programmers with knowledge of Django. Thank you.
For
1) The standard get-go solution for timed and background task is Celery which has Django integration. There are others, like Huey https://github.com/coleifer/huey
2) The usual solution is that each row contains user_id column for which this data belongs to. This maps to User model using Django ORM's ForeignKey field. Do your users to need to query the database directly or do they have direct database accounts? If not then this solution should be enough. It sounds like it your front end has 1 database connection and all permission logic is handled by the front end, not the database itself.
3) See 2

Postgres: is set_config(). current_setting() a private/robust stack for application variables?

In my application I have triggers that need access to things like user id. I am storing that information with
set_config('PRIVATE.'|'user_id', '221', false)
then, while I am doing operations that modify the database, triggers may do:
user_id = current_setting('PRIVATE.user_id');
it seems to work great. My database actions are mostly from python, psycopg2, once I get a connection I'll do the set_config() as my first operation, then go about my database business. Is this practice a good one or could data leak from one session to another? I was doing this sort of thing with the SD and GD variables in plpython, but that language proved too heavy for what I was trying to do so I had to shift to plpgsql.
While it's not really what they're designed for, you can use GUCs as session variables.
They can also be transaction scoped, with SET LOCAL or the set_config equivalent.
So long as you don't allow the user to run arbitrary SQL they're a reasonable choice, and session-local GUCs aren't shared with other sessions. They're not designed for secure session-local storage but they're handy places to stash things like an application's "current user" if you're not using SET ROLE or SET SESSION AUTHORIZATION for that.
Do be aware that the user can define them via environment variables if you let them run a libpq based client, e.g.
$ PGOPTIONS="-c myapp.user_id=fred" psql -c "SHOW myapp.user_id;"
myapp.user_id
---------------
fred
(1 row)
Also, on older PostgreSQL versions you had to declare the namespace in postgresql.conf before you could use it.

How to separate read db server and write db server on django 0.97?

I am using Django 0.97 version with postgresql 9.0. I have configured hot streaming replication on a master db server and a slave db server. My application has heavy bot-driven writes on the DB and reads only from the users. So, it makes it very optimized if I make the read-access slave db for the users' and write-access master db for the bot write access. Unfortunately only Django 1.2 has multiple database support and its a huge effort to upgrade in my application. I got some leads through the following link : http://www.eflorenzano.com/blog/post/easy-multi-database-support-django/ However, this also requires me to change all instances of db access in my application. Is there any simpler way to assign separate db servers for read access and write access by fiddling with the the django core db module?
Your best bet is to upgrade to 1.2 as it will be significantly less work than hacking together features that already exist. If you stick with 0.97 for much longer your life will only be more difficult down the road.
I'm guessing you may have some misconceptions on how using multiple DBs works in Django 1.2. You do not have to "change all instances of db access in [your] application" if you use the Database Routers feature of Django.
With a router, you can specify which database to use for reads and writes. All of your existing django models should work and begin sending requests to the proper database. It's pretty simple to set up a router, just check the docs. All that is required is to create the router class, put it somewhere, then add a line in your settings.
It works really nicely and is not as much work as you may expect. You may have other issues with upgrading that you aren't telling us, but as far as models go you shouldn't have many problems.

Categories