Смена роли после подключения к базе данных
Можно ли изменить роль postgresql, которую использует пользователь при взаимодействии с postgres после первоначального подключения?
База данных будет использоваться в веб-приложении, и я хотел бы использовать правила уровня базы данных для таблиц и схем с пулами соединений. Из прочтения документации postgresql выясняется, что я могу поменяться ролями, если первоначально подключаюсь как пользователь с ролью суперпользователя, но я бы предпочел изначально подключиться как пользователь с минимальными разрешениями и переключаться по мере необходимости. Было бы хорошо указать пароль пользователя при переключении (на самом деле я бы предпочел его).
Что мне не хватает?
Обновление: я пробовал оба SET ROLE
а также SET SESSION AUTHORIZATION
однако, как предполагает @Milen, ни одна из команд не работает, если пользователь не является суперпользователем:
$ psql -U test
psql (8.4.4)
Type "help" for help.
test=> \du test
List of roles
Role name | Attributes | Member of
-----------+------------+----------------
test | | {connect_only}
test=> \du test2
List of roles
Role name | Attributes | Member of
-----------+------------+----------------
test2 | | {connect_only}
test=> set role test2;
ERROR: permission denied to set role "test2"
test=> \q
3 ответа
--create a user that you want to use the database as:
create role neil;
--create the user for the web server to connect as:
create role webgui noinherit login password 's3cr3t';
--let webgui set role to neil:
grant neil to webgui; --this looks backwards but is correct.
webgui
сейчас в neil
группа, так webgui
может позвонить set role neil
, Тем не мение, webgui
не наследовал neil
разрешения.
Позже, войдите как webgui:
psql -d some_database -U webgui
(enter s3cr3t as password)
set role neil;
webgui
не требуется superuser
разрешение на это.
Вы хотите set role
в начале сеанса базы данных и сбросьте его в конце сеанса. В веб-приложении это соответствует получению соединения из пула соединений с базой данных и его освобождению соответственно. Вот пример использования пула соединений Tomcat и Spring Security:
public class SetRoleJdbcInterceptor extends JdbcInterceptor {
@Override
public void reset(ConnectionPool connectionPool, PooledConnection pooledConnection) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if(authentication != null) {
try {
/*
use OWASP's ESAPI to encode the username to avoid SQL Injection. Can't use parameters with SET ROLE. Need to write PG codec.
Or use a whitelist-map approach
*/
String username = ESAPI.encoder().encodeForSQL(MY_CODEC, authentication.getName());
Statement statement = pooledConnection.getConnection().createStatement();
statement.execute("set role \"" + username + "\"");
statement.close();
} catch(SQLException exp){
throw new RuntimeException(exp);
}
}
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if("close".equals(method.getName())){
Statement statement = ((Connection)proxy).createStatement();
statement.execute("reset role");
statement.close();
}
return super.invoke(proxy, method, args);
}
}
Если кому-то это все еще нужно (как и мне).
Указанное имя_роли должно быть ролью, членом которой является текущий пользователь сеанса. https://www.postgresql.org/docs/10/sql-set-role.html
Нам нужно сделать текущего пользователя сессии членом роли:
create role myrole;
set role myrole;
grant myrole to myuser;
set role myrole;
производит:
Role ROLE created.
Error starting at line : 4 in command -
set role myrole
Error report -
ERROR: permission denied to set role "myrole"
Grant succeeded.
Role SET succeeded.