Why can only a superuser CREATE EXTENSION hstore, but not on Heroku? - postgresql

When I attempt to enable hstore on my database:
=> CREATE EXTENSION IF NOT EXISTS hstore;
ERROR: permission denied to create extension "hstore"
HINT: Must be superuser to create this extension.
My user is not a superuser, but is the owner of the database.
According to the CREATE EXTENSION docs:
Loading an extension requires the same privileges that would be required to create its component objects. For most extensions this means superuser or database owner privileges are needed. The user who runs CREATE EXTENSION becomes the owner of the extension for purposes of later privilege checks, as well as the owner of any objects created by the extension's script.
What is hstore doing that requires superuser privileges? Is it affecting parts of the cluster outside the database I'm adding it to?
Further confundity:
The DB user Heroku Postgres provides is not a superuser:
Heroku Postgres users are granted all non-superuser permissions on their database. These include SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER, CREATE, CONNECT, TEMPORARY, EXECUTE, and USAGE.
However, that user is able to CREATE EXTENSION hstore:
To create any supported extension, open a session with heroku pg:psql and run the appropriate command:
$ heroku pg:psql
Pager usage is off.
psql (9.2.4)
SSL connection (cipher: DHE-RSA-AES256-SHA, bits: 256)
Type "help" for help.
ad27m1eao6kqb1=> CREATE EXTENSION hstore;
CREATE EXTENSION
ad27m1eao6kqb1=>
(For context, I'm attempting to set up a Dokku deployment, so the comparison to Heroku is especially important.)

The hstore extension creates functions that call code from an external dynamic object, which requires superuser privilege. That's why creating the hstore extension requires superuser privilege.
As for Heroku, it is my understanding that they are running with a special extension whitelisting module, which allows users to create certain extensions even though they are not superusers. I believe it is based on this code: https://github.com/dimitri/pgextwlist. You can try to install that code yourself if you want the same functionality in your databases.

ALTER USER myuser WITH SUPERUSER;
If you run this command from a superuser, this solves your CREATE EXTENSION issue. You may check your available users with \du to find a superuser.

This is not related to heroku.
This is how I solved this issue in ubuntu 18.04.
Provide postgres super user access.
sudo su postgres
Then I run:
psql -U postgres your_database_name -c 'create extension hstore;'
Now I can alter table your_database_name and add hstore type columns in it.
Connect to your database
psql -d your_database_name -U your_user_role
And
alter table your_table_name add your_column_name HSTORE;
Though there might be saveral different ways to do it, but I solve it in this way.
Hope this will help novice users like me.

Related

Can't create postgis extension on Google Cloud SQL

I've got a Postgres database and user I've created on Google Cloud SQL.
I'm trying to install the postgis extension for that user:
myuser=> CREATE EXTENSION postgis;
ERROR: permission denied to create extension "postgis"
HINT: Must be superuser to create this extension.
as you can see, it won't allow me to create the extension for this user, so I attempted to make this user a superuser from the postgres role:
postgres=> ALTER USER myuser WITH SUPERUSER;
ERROR: must be superuser to alter superusers
and I get the following error. This is because Google Cloud SQL does not allow the SUPERUSER role for any postgres accounts according to: https://cloud.google.com/sql/docs/postgres/users.
So I'm in this weird state of purgatory that I need to add this extension, but can't.
Any tips on how to proceed?
It looks like creating a new user through the API (or the console) will give it the proper permissions, at least according to the prompt when trying to add additional users through the console:

Fail to connect PostgreSQL DB from my Linux User

I am new to technologies , please do not judge my question too strong :).
I installed in My Ubuntu 18.04 PostgreSQL 10.7. To be able to enter my DB I need to enter the following commands from my terminal. sudo -u postgres psql.
Is there any shortened way where I can connect it from my Ubuntu User account. For example. if I input psql it will open database environment where I can type PostgreSQL commands.
Thank you.
Just execute this command in your terminal :
alias psql='sudo -u postgres psql'
So the next time, you input psql and execute, you will be in database environment.
I see two options:
1) Create alias for this command sudo -u postgres psql .
2) Go to psql and create new superuser and database for it:
CREATE ROLE username SUPERUSER;
ALTER ROLE username WITH LOGIN;
CREATE DATABASE username;
You shouldn't be using the superuser account for your normal database work. That is as if you were using root for everything in Linux.
You need to create a regular user with the privileges to create or modify tables in your database. This can be done by granting the user all privileges on the database (which is not the same as making that user a superuser) or make that user the owner of that database.
As documented in the manual psql tries to connect to a database with the name of the current Linux user and with a database user with the name of the current Linux user. So if you want to keep things simple create a user with your regular Linux user's name and an database that is owned by that user:
create user rob password 'somepassword';
create database rob owner = rob;
Assuming your Linux user is rob, then all you need to do is:
psql
and you are connected to a database where you can create and manage tables.
Depending on how you installed Postgres, you might need to adjust pg_hba.conf to allow rob to log in directly.
Again: please do NOT use the superuser account for your normal work.

Using Postgres PGCrypto encryption requires superuser to run view queries

Using: Postgres 9, CentOS 7,
Postgres Data directory not in default location but used RSync to make sure permissions were correct. And yes appropriate .config files were changed.
When I try to query a view containing an encrypted item as a NON superuser (Testuser), I get this error:
ERROR: must be superuser to read files CONTEXT: PL/pgSQL function
decrypt_data(bytea) line 13 at assignment
If I run that same query using POSTGRES superuser, the query completes fine.
This seems to be a file system read permission error when trying to read the Key files. Everything I see using encryption seem to not mention how to run without being superuser.
I have already run the following grants for Testuser:
GRANT ALL PRIVILEGES ON DATABASE xxx_db to Testuser;
GRANT SELECT ON ALL TABLES IN SCHEMA xxxxx TO Testuser;
GRANT ALL ON ALL TABLES IN SCHEMA xxxxx TO Testuser;
The test user can create tables, views, basically anything within that db.. just not read encryption keys.
The permissions on the keys are 775 right now, I even tried 777 without luck.
Any Ideas?
pgcrypto is a PostgreSQL extension described here:
https://www.postgresql.org/docs/current/static/pgcrypto.html
but it doesn't provide a decrypt_data(bytea) function.
This function seems to be custom code that happens to open a server-side file, with pg_read_file() or a similar method.
These methods are restricted to superusers to avoid normal users to read on the server's filesystem, no matter what are the Unix rights of the particular file they want to read.
You can verify this in the source of decrypt_data(bytea), which can be obtained with:
select pg_get_functiondef('decrypt_data(bytea)'::regprocedure);
or \df+ decrypt_data(bytea) from within psql.
I found the issue. I need to grant the user with function permissions.
GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA xxxxx TO yyyyyyyyy;

Database named "postgres"

I've just set up Postgres for use by different users on my network. Every user has his own username/password/database, but when I connect to Pg I can also see a 'postgres' database (and even create tables etc). I tried to REVOKE access to that database from public but then it won't let me connect. What exactly is the postgres database and why is it needed? Can I disable it so that users only see the database(s) I've created for them?
The postgres database is created by default when you run initdb.
Quote from the manual:
Creating a database cluster consists of creating the directories in which the database data will live (...) creating the template1 and postgres databases. When you later create a new database, everything in the template1 database is copied. (...) The postgres database is a default database meant for use by users, utilities and third party applications.
There is nothing special about it, and if you don't need it, you can drop it:
drop database postgres;
You need to do that as a superuser of course. The only downside of this is that when you run psql as the postgres operating system user, you need to explicitly provide a database name to connect to
If you drop the postgres database you'll find a few things to be confusing. Most tools default to using it as the default database to connect to, for one thing. Also, anything run under the postgres user will by default expect to connect to the postgres database.
Rather than dropping it, REVOKE the default connect right to it.
REVOKE connect ON DATABASE postgres FROM public;
The superuser (usually postgres), and any users you explicitly grant rights to access the database can still use it as a convenience DB to connect to. But others can't.
To grant connect rights to a user, simply:
GRANT connect ON DATABASE postgres TO myuser;

Postgresql: Create a new user with no privileges?

I'm just learning PostgreSQL. Every time I create users, they seem to have the full privileges to do anything in any database:
$ sudo useradd fool # create the user "fool" in the system
# And in postgresql, as restrictively as possible
$ sudo -u postgres createuser fool --no-superuser --no-createdb --no-createrole --no-inherit
$ sudo -u fool psql postgres # but it can still connect to the "postgres" db
postgres=> drop table ids; # and delete tables
DROP TABLE
I tried creating the user through the create user PostgreSQL command rather than the command-line tool but it had exactly the same effect.
How can I create a user that only has privileges to access its own database? Or do I have to specifically revoke all permissions after creating the user? 'Cos that kinda sucks from a security perspective - it's easy to accidentally forget (or just not know it's necessary) to revoke permissions for new users.
All roles are "members" of the pseudo-role PUBLIC. And by default PUBLIC has many privileges. My practice is to revoke all privileges from PUBLIC where I need and grant various combinations to specific roles. A recent addition helps with that - ALTER DEFAULT PRIVILEGES. Another, not so flexible but easier, method is the CONNECT privilege.