Prevent users from seeing objects to which they have no access - postgresql

WHAT
I have users that share a database, but have their own schemas. Each user is only able to access objects on their schema - they have been explicitly revoked usage on the schemas that are not theirs.
I am not concerned about a user inappropriately accessing others' schema; however, I would very much like for them not to be able to see the contents or even the existence of the other schema to which they have no access.
WHY
I am aware that this is mostly "cosmetic", but the primary reason for this would be that my users do not have to shift through objects that they cannot access in certain tools (Tableau, DB IDEs, etc) - so I think it does add some practical value.
ATTEMPTS
I've been searching for a solution, but haven't found one that works. For instance, I revoked users' access on information_schema and pg_catalog (I know this is not recommended); however, it had no effect.
Is this at all possible?

It is not possible to limit access to pg_class, pg_attribute, or pg_proc. Therefore what you want can only be achieved by separating each user in their own databases rather than individual schemas.

Related

Is there an advantage of having a userId AND a username even if they're both strings?

I have come across different variations when it comes to user authentication and I have seen developers include a userId field AND a username field (both strings) in their database so I wondered if there is an advantage if you have both of these fields.
I would rather have only one field (username) to have a better overview and prevent possible mistakes but I'm not sure if there could be problems that come along with that variation.
I've already looked on the internet but only found a Quora answer which stated it would make sense to have a userId as an integer since "Integers are easier/faster/less expensive to sort, search, and compare than strings"
https://www.quora.com/Why-do-developers-add-user-id-and-username-fields-to-a-user-table-Isnt-the-username-enough
The solution in the linked answer applies to SQL databases and not to NoSQL databases. If you're using Firebase Authentication, I cannot see any reason why would you store the UID or the user names in the database. Why? Because you can always get those values from the current user object without the need of performing a database call. As a general rule, always store in the database only the data that you need in your application code and nothing more.
The UID never changes and is generally used to reference related data in other collections/tables over username (as users are usually allowed to change their names in most of the applications). You have not provided many details on your applications but these are handy for most of the actions such as:
Fetching usernames when sending emails (better to query from a database rather than fetching data from Firebase Auth)
If your application serves user generated content e.g. articles, you might want to show the author's name and storing the username in the database is quicker than running an additional query to Firebase. Also, a user can read their own data only using the client SDKs.
I am not sure about which database you use, but as long as you have proper indexes setup, the queries should be fast. It's pretty common to use UUIDs or MongoBD's ObjectIDs as user IDs.

Why would you ever GRANT special permissions on a SEQUENCE?

What would be a good use case for restricting permissions on a SEQUENCE in a database?
Usually, when I GRANT permissions on a TABLE, I also GRANT the same permissions on the SEQUENCES. It seems like a redundant step, so is there a good use case for when SEQUENCE permissions differ from TABLE permissions?
I can see 3 reasons.
Not all sequences are attached to a table, so it makes sense to allow access to them separately.
For instance, an application that sending messages to a server may need a unique identifier for all messages, in which case a DB sequence is a convenient way to generate ids that will be unique across all clients.
Unlike tables, regular users are very rarely granted all privileges on a sequence when they are on a table and they are different anyway (respectively SELECT USAGE UPDATE and SELECT INSERT UPDATE DELETE TRUNCATE REFERENCES TRIGGER). That would create a mess to grant all privileges on sequences. The right approach is to only grant USAGE on sequences.
You can probably imagine the risk of letting anyone reset a sequence to 1 when the said sequence is used to generate primary key values on a table.
In that sense, privilege on sequences really need to be managed separately.
The standard behavior for all objects in a database and more generally for everything related to security, is that you have to explicitly grant privileges on an object before anybody can use it.
The two bulletpoints above merely explain why privileges must be specific to sequences but here is a more general consideration about why privileges are never granted by default.

security settings for graph databases

Relational Databases are able to set permissions for users to insert, update, delete, etc by schema or table (e.g. I can allow bob CRUD access to table someschema.XYZ but only allow read access to someschema.FooBar and no access to schema ABC)
Graph databases do not have predefined schemas but have an arbitrary set of node types. Is it possible to set restrictions on a graph database for what a user can access like you do for relational databases or does this granularity not exist in graph databases due to it's nature?
I am specifically looking at Neo4j but if this exists in other examples, then I would like to know.
Neo4j allows you to implement your own SecurityRules. A SecurityRule acts similar to a servlet filter, every request is evaluated with the SecurityRule.
However you have to implement the logic on your own which gives great flexibility but might also cause a serious amount of work.

Decentralizing Database Structure

Although this question fancies PostgreSQL, it is still a general DB question.
I have always been curious about the term schema as it relates to databases. Recently, we switched over to using PostgreSQL, where that term has actual significance to the underlying database structure.
In PostgreSQL-land, the decentralized structure is as follows:
DB Server (`some-server.com:5432`)
>> Database (`fizz`)
>> Schema (`buzz`)
>> Table (`foo`)
Thus, the FQDN for table [foo] is fizz.buzz.foo.
I understand that a "database" is a logical grouping of tables. For instance, an organization might have a "domain" database where all POJOs/VOs are persisted, an "orders" database where all sales-related info is stored, and a "logging" databases where all log messages get sent for future analysis, etc.
The introduction of this "schema" construct in between the database and its tables has me very confused, and the PostgreSQL documentation is a little too heavy-handed (and lacking good examples) for a newbie such as myself to understand.
I'm wondering if anyone can give me a laymen's description of not only what this "schema" construct is within the realm of PostgreSQL (and how it relates databases to tables), but I'm wondering what it means to database structures in general.
Thanks in advance!
Think of schemas as namespaces. We can use them to logically group tables (such as a People schema). Additionally, we can assign security to that schema so we can allow certain folks to look at a Customer schema, but not an Employee schema. This allows us to have a granularity of control of security just above an object level but below the database level.
Security is probably the most important reason to use schemas, but I've seen them used for logical groupings as well. It just depends on what you need them for.
Late to the party, but ..
I use schemas to split tables in to groups that are used by different applications that share a few tables, for example.
users
application1
application2
Here, if we log in with app1, we see users + application1; if we log in to app2, we see users and application2. So our user data can be shared between both, without exposing app1 users to app2 data. It also means that a superuser can do queries across both sets of data.

How to get available space in tablespace for a user (Oracle)

I'm working on a web application where I need to warn the user that they're running out of space in the given db user's tablespace.
The application doesn't know the credentials of the db's system user, so I can't query views like dba_users, dba_free_space..etc.
My question is, is there a way in Oracle for a user to find out how much space there is left for them in their tablespace?
Thanks!
Forgive my ignorance on the subject, for I believed only views available on data storage were dba_free_space etc..
I realized that for the logged user, there are user_free_space.. views for them.
Modified version of the query mentioned here would be the answer my question.
Query is as follows: (Getting the space left on the DEFAULT_TABLESPACE of the logged user)
SELECT
ts.tablespace_name,
TO_CHAR(SUM(NVL(fs.bytes,0))/1024/1024, '99,999,990.99') AS MB_FREE
FROM
user_free_space fs,
user_tablespaces ts,
user_users us
WHERE
fs.tablespace_name(+) = ts.tablespace_name
AND ts.tablespace_name(+) = us.default_tablespace
GROUP BY
ts.tablespace_name;
It would return free space in MB
create a stored package as a user that has the necessary privileges. You may have to create a new user. Grant EXECUTE on the package to any user that needs it. The packages needs to have all the procedures and functions needed to access the DBA views but should be coded carefully to avoid accessing "too much" information. You may want to write a second package in the account of a non-privileged user to encapsulate the logic.
This is potentially very complex, as it's quite possible for the user to:
Receive an "out of space" error even though the tablespaces that they have privileges on, including their default tablespace, have plenty of space. This could happen when they insert into a table that is owned by a different user which is on a tablespace that your user has no quota on. In this case, your user probably does not have access to the views required to determine whether there is free space or not,
Be able to continue inserting data even though there is no free space on the tablespaces on which they have a quota -- they might not even have a quota on their default tablespaces.
So unless you have a rather simple case you really have to be very aware of the way that the user interacts with the database on a far deeper level, and look at free space from a more database-holistic viewpoint.