AWS RDS PostgreSQL Tablespace - postgresql

I created an AWS RDS postgres instance. When creating i was prompted to create user. There is no reason for creating tablespaces with location in AWS RDS? The reason is when creating a database i want the database to goto the tablespace i created. When i run the below command
CREATE USER test;
CREATE TABLESPACE test OWNER test LOCATION '/test_data';
CREATE DATABASE test WITH TEMPLATE = template0 ENCODING = 'UTF8' LC_COLLATE = 'C' LC_CTYPE = 'C' TABLESPACE = test;
ERROR: permission denied for tablespace test
I logged into postgres using test_admin user to run the above commands. The test_admin is the account i created during the RDS instance provisioning. Is that the only account that i should be using above to create all of the DB objects from that point?

Do you want the owner of the database to be test as well? If so, add that into your CREATE DATABASE.... Otherwise, you'll probably need to give the test_admin user permission on the test tablespace before trying to create it.

Tablespaces in postgres RDS are located in /rdsdbdata/db/base/tablespace/
and I think this question has been answered here
Create tablespace on PostgreSQL RDS

Related

Install PostgreSQL extension for non-superuser

My app's database has a dedicated user with full access like so;
CREATE DATABASE "mydb"
WITH OWNER = cloudsqlsuperuser
ENCODING = 'UTF8'
TABLESPACE = pg_default
LC_COLLATE = 'en_US.UTF8'
LC_CTYPE = 'en_US.UTF8'
CONNECTION LIMIT = -1;
GRANT CONNECT, TEMPORARY ON DATABASE "mydb" TO public;
GRANT ALL ON DATABASE "mydb" TO cloudsqlsuperuser;
GRANT ALL ON DATABASE "mydb" TO "mydb";
In the startup of my app I have the following query in place to make sure that UUID extension is available;
create extension if not exists "uuid-ossp";
This works great. However I recently tried adding an identical query to create "pgcrypto" extension like so;
create extension if not exists "pgcrypto";
This fails claiming I need super user privileges to create the extension. So I decided to manually create it as a superuser user. However even if I log as postgres user in Adminer and create the extension successfully, it does not become available to the queries in my app (mydb user).
I am not familiar with the namespace mechanisms used in PostgreSQL, so I want to know how can I create the extension so that it will become available from my app's code without giving app user superuser privileges?

Revoke CONNECT permission to new DB by default

this is happening on newly created Postgres 13 instance on GCP's Cloud SQL.
I would like to disallow users to CONNECT to newly created databases. So I am modifying template database:
REVOKE ALL ON DATABASE template1 FROM public;
Then, I create new Database:
CREATE DATABASE mydb TEMPLATE template1;
Then I am checking CONNECT permissions for existing user:
SELECT datname
FROM pg_database
WHERE has_database_privilege('someuser', datname, 'CONNECT')
datname
---------------
cloudsqladmin
postgres
template0
mydb
So as you can see someuser has CONNECT permission to mydb.
Why is this happening? How can I prevent users to connect to newly created databases?
The permissions on a database are not copied from the template database during CREATE DATABASE. Rather, all new databases have the same default permissions: CONNECT and TEMP for PUBLIC, and all permissions for the owner.
There is no way to change that default, short of modifying the PostgreSQL code.

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;

Create tablespace in postgresql and set is to it is the default for all newly created databases

I have created a tablespace named hdd_tablespace and I wan't all new databases to be automatically created there. Basically when I execute:
CREATE DATABASE FOO;
I want this database to be created in hdd_tablespace.
I have updated postgresql.conf with:
default_tablespace = 'hdd_tablespace'
However, new databases are still created in pg_default.
Actually it turned out I had also to update template1 database that is a template database.
I had to;
ALTER DATABASE template1 SET TABLESPACE hdd_tablespace;

Difference between ALTER ROLE WITH CREATEDB and GRANT CREATE ON TABLESPACE

Coming from MySQL and not knowing about ROLEs I absentmindedly tried this
GRANT CREATE ON TABLESPACE pg_default TO username;
It didn't have the desired effect. The command that I was looking for was:
ALTER ROLE username WITH CREATEDB;
But what's the difference precisely? Does giving someone the CREATEDB role implicitly give them CREATE ON TABLESPACE ...? Is there a table where I can see all this?
From the docs, GRANT CREATE ON TABLESPACE means (my emphasis):
For tablespaces, allows tables,
indexes, and temporary files to be
created within the tablespace, and
allows databases to be
created that have the
tablespace as their default
tablespace. (Note that revoking this
privilege will not alter the placement
of existing objects.)
They are completely different privileges. CREATEDB means the role can create database. If your role doesn't have that, it can't create databases, period.
Granting CREATE for a tablespace to a role means that the role will be able to use that tablespace as default tablespace for the database. So a role that has CREATEDB will be able to create a database; just not on that tablespace. Note that there's always a pg_default tablespace that will be used as default tablespace for databases that don't otherwise have a default tablespace.
Tablespaces are not the same as databases.
It looks like the first statement gives you the ability to create tablespaces. This are physical files (or spaces on your storage device) that hold the data/indexes/... of the database.
So effectively you granted two different rights with the commands.