def alter_user(self, context, user, encrypt_password=None, *options): """Change the password and options of an existing users. :param user: User to be altered. :type user: PostgreSQLUser :param encrypt_password: Store passwords encrypted if True. Fallback to configured default behavior if None. :type encrypt_password: boolean :param options: Other user options. :type options: list """ LOG.info( _("{guest_id}: Altering user {user} {with_clause}.").format( guest_id=CONF.guest_id, user=user.name, with_clause=pgutil.UserQuery._build_with_clause( '<SANITIZED>', encrypt_password, *options), )) pgutil.psql( pgutil.UserQuery.alter_user(user.name, user.password, encrypt_password, *options), timeout=30, )
def create_user(self, context, users): """Create users and grant privileges for the specified databases. The users parameter is a list of dictionaries in the following form: {"_name": "", "_password": "", "_databases": [{"_name": ""}, ...]} """ for user in users: LOG.debug( "{guest_id}: Creating user {name} with password {password}.". format( guest_id=CONF.guest_id, name=user['_name'], password=user['_password'], )) LOG.info( _("{guest_id}: Creating user {name} with password {password}." ).format( guest_id=CONF.guest_id, name=user['_name'], password="******", )) pgutil.psql( pgutil.UserQuery.create( name=user['_name'], password=user['_password'], ), timeout=30, ) self.grant_access( context, user['_name'], None, [d['_name'] for d in user['_databases']], )
def create_database(self, context, databases): """Create the list of specified databases. The databases parameter is a list of dictionaries in the following form: {"_name": "", "_character_set": "", "_collate": ""} Encoding and collation values are validated in trove.guestagent.db.models. """ for database in databases: encoding = database.get('_character_set') collate = database.get('_collate') LOG.info( _("{guest_id}: Creating database {name}.").format( guest_id=CONF.guest_id, name=database['_name'], )) pgutil.psql( pgutil.DatabaseQuery.create( name=database['_name'], encoding=encoding, collation=collate, ), timeout=30, )
def create_database(self, context, databases): """Create the list of specified databases. The databases parameter is a list of dictionaries in the following form: {"_name": "", "_character_set": "", "_collate": ""} Encoding and collation values are validated in trove.guestagent.db.models. """ for database in databases: encoding = database.get('_character_set') collate = database.get('_collate') LOG.info( _("{guest_id}: Creating database {name}.").format( guest_id=CONF.guest_id, name=database['_name'], ) ) pgutil.psql( pgutil.DatabaseQuery.create( name=database['_name'], encoding=encoding, collation=collate, ), timeout=30, )
def change_passwords(self, context, users): """Change the passwords of one or more existing users. The users parameter is a list of dictionaries in the following form: {"name": "", "password": ""} """ for user in users: LOG.debug( "{guest_id}: Changing password for {user} to {password}.". format( guest_id=CONF.guest_id, user=user['name'], password=user['password'], )) LOG.info( _("{guest_id}: Changing password for {user} to {password}."). format( guest_id=CONF.guest_id, user=user['name'], password="******", )) pgutil.psql( pgutil.UserQuery.update_password( user=user['name'], password=user['password'], ), timeout=30, )
def enable_as_master(self, service, master_config, for_failover=False): # For a server to be a master in postgres, we need to enable # replication user in pg_hba and ensure that WAL logging is # the appropriate level (use the same settings as backups) self._get_or_create_replication_user() hba_entry = "host replication replicator 0.0.0.0/0 md5 \n" tmp_hba = '/tmp/pg_hba' operating_system.copy(self.pgsql_hba_config, tmp_hba, force=True, as_root=True) operating_system.chmod(tmp_hba, FileMode.SET_ALL_RWX(), as_root=True) with open(tmp_hba, 'a+') as hba_file: hba_file.write(hba_entry) operating_system.copy(tmp_hba, self.pgsql_hba_config, force=True, as_root=True) operating_system.chmod(self.pgsql_hba_config, FileMode.SET_USR_RWX(), as_root=True) operating_system.remove(tmp_hba, as_root=True) pgutil.psql("SELECT pg_reload_conf()")
def enable_root(self, context, root_password=None): """Create a superuser user or reset the superuser password. The default PostgreSQL administration account is 'postgres'. This account always exists and cannot be removed. Its attributes and access can however be altered. Clients can connect from the localhost or remotely via TCP/IP: Local clients (e.g. psql) can connect from a preset *system* account called 'postgres'. This system account has no password and is *locked* by default, so that it can be used by *local* users only. It should *never* be enabled (or its password set)!!! That would just open up a new attack vector on the system account. Remote clients should use a build-in *database* account of the same name. It's password can be changed using the "ALTER USER" statement. Access to this account is disabled by Trove exposed only once the superuser access is requested. Trove itself creates its own administrative account. {"_name": "postgres", "_password": "******"} """ user = models.PostgreSQLRootUser(password=root_password) query = pgutil.UserQuery.alter_user(user.name, user.password, None, *self.ADMIN_OPTIONS) pgutil.psql(query, timeout=30) return user.serialize()
def change_passwords(self, context, users): """Change the passwords of one or more existing users. The users parameter is a list of dictionaries in the following form: {"name": "", "password": ""} """ for user in users: LOG.debug( "{guest_id}: Changing password for {user} to {password}." .format( guest_id=CONF.guest_id, user=user['name'], password=user['password'], ) ) LOG.info( _("{guest_id}: Changing password for {user} to {password}.") .format( guest_id=CONF.guest_id, user=user['name'], password="******", ) ) pgutil.psql( pgutil.UserQuery.update_password( user=user['name'], password=user['password'], ), timeout=30, )
def _create_user(self, context, user, encrypt_password=None, *options): LOG.info( _("{guest_id}: Creating user {user} {with_clause}.") .format( guest_id=CONF.guest_id, user=user['_name'], with_clause=pgutil.UserQuery._build_with_clause( '<SANITIZED>', encrypt_password, *options ), ) ) pgutil.psql( pgutil.UserQuery.create( user['_name'], user['_password'], encrypt_password, *options ), timeout=30, ) self.grant_access( context, user['_name'], None, [d['_name'] for d in user['_databases']], )
def _create_replication_user(self, pwfile): """Create the replication user. Unfortunately, to be able to run pg_rewind, we need SUPERUSER, not just REPLICATION privilege """ pw = utils.generate_random_password() operating_system.write_file(pwfile, pw, as_root=True) operating_system.chown(pwfile, user=self.PGSQL_OWNER, group=self.PGSQL_OWNER, as_root=True) operating_system.chmod(pwfile, FileMode.OCTAL_MODE("0600"), as_root=True) # TODO(atomic77) Alter user is swallowing the replication # option for some reason -- enable this code when the # underlying issue is fixed # repl_user = models.PostgreSQLUser(name=REPL_USER, # password=REPL_PW) # self._create_user(context=None, user=repl_user) # self.alter_user(None, repl_user, 'REPLICATION', 'LOGIN') pgutil.psql("CREATE USER %s SUPERUSER ENCRYPTED " "password '%s';" % (REPL_USER, pw)) return pw
def alter_user(self, context, user, encrypt_password=None, *options): """Change the password and options of an existing users. :param user: User to be altered. :type user: PostgreSQLUser :param encrypt_password: Store passwords encrypted if True. Fallback to configured default behavior if None. :type encrypt_password: boolean :param options: Other user options. :type options: list """ LOG.info( _("{guest_id}: Altering user {user} {with_clause}.") .format( guest_id=CONF.guest_id, user=user.name, with_clause=pgutil.UserQuery._build_with_clause( '<SANITIZED>', encrypt_password, *options ), ) ) pgutil.psql( pgutil.UserQuery.alter_user( user.name, user.password, encrypt_password, *options), timeout=30, )
def enable_as_master(self, service, master_config, for_failover=False): """For a server to be a master in postgres, we need to enable the replication user in pg_hba and ensure that WAL logging is at the appropriate level (use the same settings as backups) """ LOG.debug("Enabling as master, with cfg: %s " % master_config) self._get_or_create_replication_user() hba_entry = "host replication replicator 0.0.0.0/0 md5 \n" # TODO(atomic77) Remove this hack after adding cfg manager for pg_hba tmp_hba = '/tmp/pg_hba' operating_system.copy(self.PGSQL_HBA_CONFIG, tmp_hba, force=True, as_root=True) operating_system.chmod(tmp_hba, FileMode.OCTAL_MODE("0777"), as_root=True) with open(tmp_hba, 'a+') as hba_file: hba_file.write(hba_entry) operating_system.copy(tmp_hba, self.PGSQL_HBA_CONFIG, force=True, as_root=True) operating_system.chmod(self.PGSQL_HBA_CONFIG, FileMode.OCTAL_MODE("0600"), as_root=True) operating_system.remove(tmp_hba, as_root=True) pgutil.psql("SELECT pg_reload_conf()")
def enable_root(self, context, root_password=None): """Create a superuser user or reset the superuser password. The default PostgreSQL administration account is 'postgres'. This account always exists and cannot be removed. Its attributes and access can however be altered. Clients can connect from the localhost or remotely via TCP/IP: Local clients (e.g. psql) can connect from a preset *system* account called 'postgres'. This system account has no password and is *locked* by default, so that it can be used by *local* users only. It should *never* be enabled (or its password set)!!! That would just open up a new attack vector on the system account. Remote clients should use a build-in *database* account of the same name. It's password can be changed using the "ALTER USER" statement. Access to this account is disabled by Trove exposed only once the superuser access is requested. Trove itself creates its own administrative account. {"_name": "postgres", "_password": "******"} """ user = models.PostgreSQLRootUser(password=root_password) query = pgutil.UserQuery.alter_user( user.name, user.password, None, *self.ADMIN_OPTIONS ) pgutil.psql(query, timeout=30) return user.serialize()
def _create_user(self, context, user, encrypt_password=None, *options): """Create a user and grant privileges for the specified databases. :param user: User to be created. :type user: PostgreSQLUser :param encrypt_password: Store passwords encrypted if True. Fallback to configured default behavior if None. :type encrypt_password: boolean :param options: Other user options. :type options: list """ LOG.info( _("{guest_id}: Creating user {user} {with_clause}.").format( guest_id=CONF.guest_id, user=user.name, with_clause=pgutil.UserQuery._build_with_clause( '<SANITIZED>', encrypt_password, *options), )) pgutil.psql( pgutil.UserQuery.create(user.name, user.password, encrypt_password, *options), timeout=30, ) self._grant_access( context, user.name, [PostgreSQLSchema.deserialize_schema(db) for db in user.databases])
def alter_user(self, context, user, encrypt_password=None, *options): """Change the password and options of an existing users. The user parameter is a dictionary of the following form: {"name": "", "password": ""} """ LOG.info( _("{guest_id}: Altering user {user} {with_clause}.") .format( guest_id=CONF.guest_id, user=user['_name'], with_clause=pgutil.UserQuery._build_with_clause( '<SANITIZED>', encrypt_password, *options ), ) ) pgutil.psql( pgutil.UserQuery.alter_user( user['_name'], user['_password'], encrypt_password, *options), timeout=30, )
def enable_root(self, context, root_password=None): """Create a root user or reset the root user password. The default superuser for PgSql is postgres, but that account is used for administration. Instead, this method will create a new user called root that also has superuser privileges. If no root_password is given then a random UUID will be used for the superuser password. Return value is a dictionary in the following form: {"_name": "root", "_password": ""} """ user = { "_name": "root", "_password": root_password or str(uuid.uuid4()), } LOG.debug( "{guest_id}: Creating root user with password {password}.".format( guest_id=CONF.guest_id, password=user['_password'], ) ) query = pgutil.UserQuery.create( name=user['_name'], password=user['_password'], ) if self.is_root_enabled(context): query = pgutil.UserQuery.update_password( name=user['_name'], password=user['_password'], ) pgutil.psql(query, timeout=30) return user
def _create_user(self, context, user, encrypt_password=None, *options): LOG.info( _("{guest_id}: Creating user {user} {with_clause}.") .format( guest_id=CONF.guest_id, user=user['_name'], with_clause=pgutil.UserQuery._build_with_clause( '<SANITIZED>', encrypt_password, *options ), ) ) pgutil.psql( pgutil.UserQuery.create( user['_name'], user['_password'], encrypt_password, *options ), timeout=30, ) self.grant_access( context, user['_name'], None, [d['_name'] for d in user['_databases']], )
def enable_root(self, context, root_password=None): """Create a root user or reset the root user password. The default superuser for PgSql is postgres, but that account is used for administration. Instead, this method will create a new user called root that also has superuser privileges. If no root_password is given then a random UUID will be used for the superuser password. Return value is a dictionary in the following form: {"_name": "root", "_password": ""} """ user = { "_name": "root", "_password": root_password or str(uuid.uuid4()), } LOG.debug( "{guest_id}: Creating root user with password {password}.".format( guest_id=CONF.guest_id, password=user['_password'], )) query = pgutil.UserQuery.create( name=user['_name'], password=user['_password'], ) if self.is_root_enabled(context): query = pgutil.UserQuery.update_password( name=user['_name'], password=user['_password'], ) pgutil.psql(query, timeout=30) return user
def enable_as_master(self, service, master_config): """For a server to be a master in postgres, we need to enable the replication user in pg_hba and ensure that WAL logging is at the appropriate level (use the same settings as backups) """ LOG.debug("Enabling as master, with cfg: %s " % master_config) self._get_or_create_replication_user() hba_entry = "host replication replicator 0.0.0.0/0 md5 \n" # TODO(atomic77) Remove this hack after adding cfg manager for pg_hba tmp_hba = '/tmp/pg_hba' operating_system.copy(self.pgsql_hba_config, tmp_hba, force=True, as_root=True) operating_system.chmod(tmp_hba, FileMode.OCTAL_MODE("0777"), as_root=True) with open(tmp_hba, 'a+') as hba_file: hba_file.write(hba_entry) operating_system.copy(tmp_hba, self.pgsql_hba_config, force=True, as_root=True) operating_system.chmod(self.pgsql_hba_config, FileMode.OCTAL_MODE("0600"), as_root=True) operating_system.remove(tmp_hba, as_root=True) pgutil.psql("SELECT pg_reload_conf()")
def alter_user(self, context, user, encrypt_password=None, *options): """Change the password and options of an existing users. The user parameter is a dictionary of the following form: {"name": "", "password": ""} """ LOG.info( _("{guest_id}: Altering user {user} {with_clause}.") .format( guest_id=CONF.guest_id, user=user['_name'], with_clause=pgutil.UserQuery._build_with_clause( '<SANITIZED>', encrypt_password, *options ), ) ) pgutil.psql( pgutil.UserQuery.alter_user( user['_name'], user['_password'], encrypt_password, *options), timeout=30, )
def update_attributes(self, context, username, hostname, user_attrs): """Change the attributes of one existing user. The username and hostname parameters are strings. The user_attrs parameter is a dictionary in the following form: {"password": "", "name": ""} Each key/value pair in user_attrs is optional. """ if user_attrs.get("password") is not None: self.change_passwords(context, ({"name": username, "password": user_attrs["password"]},)) if user_attrs.get("name") is not None: access = self.list_access(context, username, None) LOG.info( _("{guest_id}: Changing username for {old} to {new}.").format( guest_id=CONF.guest_id, old=username, new=user_attrs["name"] ) ) pgutil.psql(pgutil.psql.UserQuery.update_name(old=username, new=user_attrs["name"]), timeout=30) # Regrant all previous access after the name change. LOG.info( _("{guest_id}: Regranting permissions from {old} to {new}.").format( guest_id=CONF.guest_id, old=username, new=user_attrs["name"] ) ) self.grant_access( context, username=user_attrs["name"], hostname=None, databases=(db["_name"] for db in access) )
def apply_overrides(self, context, overrides): # Send a signal to the server, causing configuration files to be # reloaded by all server processes. # Active queries or connections to the database will not be # interrupted. # # NOTE: Do not use the 'SET' command as it only affects the current # session. pgutil.psql("SELECT pg_reload_conf()")
def delete_user(self, context, user): """Delete the specified user. The user parameter is a dictionary in the following form: {"_name": ""} """ LOG.info(_("{guest_id}: Dropping user {name}.").format(guest_id=CONF.guest_id, name=user["_name"])) pgutil.psql(pgutil.UserQuery.drop(name=user["_name"]), timeout=30)
def update_attributes(self, context, username, hostname, user_attrs): """Change the attributes of one existing user. The username and hostname parameters are strings. The user_attrs parameter is a dictionary in the following form: {"password": "", "name": ""} Each key/value pair in user_attrs is optional. """ with EndNotification(context): if user_attrs.get('password') is not None: self.change_passwords( context, ( { "name": username, "password": user_attrs['password'], }, ), ) if user_attrs.get('name') is not None: access = self.list_access(context, username, None) LOG.info( _("{guest_id}: Changing username for {old} to {new}." ).format( guest_id=CONF.guest_id, old=username, new=user_attrs['name'], ) ) pgutil.psql( pgutil.psql.UserQuery.update_name( old=username, new=user_attrs['name'], ), timeout=30, ) # Regrant all previous access after the name change. LOG.info( _("{guest_id}: Regranting permissions from {old} " "to {new}.") .format( guest_id=CONF.guest_id, old=username, new=user_attrs['name'], ) ) self.grant_access( context, username=user_attrs['name'], hostname=None, databases=(db['_name'] for db in access) )
def _get_actual_db_status(self): try: # Any query will initiate a new database connection. pgutil.psql("SELECT 1") return instance.ServiceStatuses.RUNNING except psycopg2.OperationalError: return instance.ServiceStatuses.SHUTDOWN except utils.Timeout: return instance.ServiceStatuses.BLOCKED except Exception: LOG.exception(_("Error getting Postgres status.")) return instance.ServiceStatuses.CRASHED return instance.ServiceStatuses.SHUTDOWN
def _drop_database(self, database): """Drop a given Postgres database. :param database: Database to be dropped. :type database: PostgreSQLSchema """ LOG.info( _("{guest_id}: Dropping database {name}.").format( guest_id=CONF.guest_id, name=database.name, )) pgutil.psql( pgutil.DatabaseQuery.drop(name=database.name), timeout=30, )
def _drop_user(self, user): """Drop a given Postgres user. :param user: User to be dropped. :type user: PostgreSQLUser """ LOG.info( _("{guest_id}: Dropping user {name}.").format( guest_id=CONF.guest_id, name=user.name, )) pgutil.psql( pgutil.UserQuery.drop(name=user.name), timeout=30, )
def delete_database(self, context, database): """Delete the specified database. The database parameter is a dictionary in the following form: {"_name": ""} """ LOG.info( _("{guest_id}: Dropping database {name}.").format( guest_id=CONF.guest_id, name=database['_name'], )) pgutil.psql( pgutil.DatabaseQuery.drop(name=database['_name']), timeout=30, )
def _drop_database(self, database): """Drop a given Postgres database. :param database: Database to be dropped. :type database: PostgreSQLSchema """ LOG.info( _("{guest_id}: Dropping database {name}.").format( guest_id=CONF.guest_id, name=database.name, ) ) pgutil.psql( pgutil.DatabaseQuery.drop(name=database.name), timeout=30, )
def delete_user(self, context, user): """Delete the specified user. The user parameter is a dictionary in the following form: {"_name": ""} """ LOG.info( _("{guest_id}: Dropping user {name}.").format( guest_id=CONF.guest_id, name=user['_name'], )) pgutil.psql( pgutil.UserQuery.drop(name=user['_name']), timeout=30, )
def _drop_user(self, user): """Drop a given Postgres user. :param user: User to be dropped. :type user: PostgreSQLUser """ LOG.info( _("{guest_id}: Dropping user {name}.").format( guest_id=CONF.guest_id, name=user.name, ) ) pgutil.psql( pgutil.UserQuery.drop(name=user.name), timeout=30, )
def _create_replication_user(self, pwfile): """Create the replication user. Unfortunately, to be able to run pg_rewind, we need SUPERUSER, not just REPLICATION privilege """ pw = utils.generate_random_password() operating_system.write_file(pwfile, pw, as_root=True) operating_system.chown(pwfile, user=self.PGSQL_OWNER, group=self.PGSQL_OWNER, as_root=True) operating_system.chmod(pwfile, FileMode.SET_USR_RWX(), as_root=True) pgutil.psql("CREATE USER %s SUPERUSER ENCRYPTED " "password '%s';" % (REPL_USER, pw)) return pw
def delete_database(self, context, database): """Delete the specified database. The database parameter is a dictionary in the following form: {"_name": ""} """ LOG.info( _("{guest_id}: Dropping database {name}.").format( guest_id=CONF.guest_id, name=database['_name'], ) ) pgutil.psql( pgutil.DatabaseQuery.drop(name=database['_name']), timeout=30, )
def _create_database(self, context, database): """Create a database. :param database: Database to be created. :type database: PostgreSQLSchema """ LOG.info( _("{guest_id}: Creating database {name}.").format( guest_id=CONF.guest_id, name=database.name, )) pgutil.psql( pgutil.DatabaseQuery.create( name=database.name, encoding=database.character_set, collation=database.collate, ), timeout=30, )
def create_user(self, context, users): """Create users and grant privileges for the specified databases. The users parameter is a list of dictionaries in the following form: {"_name": "", "_password": "", "_databases": [{"_name": ""}, ...]} """ for user in users: LOG.debug( "{guest_id}: Creating user {name} with password {password}.".format( guest_id=CONF.guest_id, name=user["_name"], password=user["_password"] ) ) LOG.info( _("{guest_id}: Creating user {name} with password {password}.").format( guest_id=CONF.guest_id, name=user["_name"], password="******" ) ) pgutil.psql(pgutil.UserQuery.create(name=user["_name"], password=user["_password"]), timeout=30) self.grant_access(context, user["_name"], None, [d["_name"] for d in user["_databases"]])
def _create_database(self, context, database): """Create a database. :param database: Database to be created. :type database: PostgreSQLSchema """ LOG.info( _("{guest_id}: Creating database {name}.").format( guest_id=CONF.guest_id, name=database.name, ) ) pgutil.psql( pgutil.DatabaseQuery.create( name=database.name, encoding=database.character_set, collation=database.collate, ), timeout=30, )
def revoke_access(self, context, username, hostname, database): """Revoke a user's permission to use a given database. The username and hostname parameters are strings. The database parameter is a string representing the name of the database. """ LOG.info( _("{guest_id}: Revoking user ({user}) access to database" "({database}).").format( guest_id=CONF.guest_id, user=username, database=database, )) pgutil.psql( pgutil.AccessQuery.revoke( user=username, database=database, ), timeout=30, )
def _drop_user(self, context, user): """Drop a given Postgres user. :param user: User to be dropped. :type user: PostgreSQLUser """ # Postgresql requires that you revoke grants before dropping the user dbs = self.list_access(context, user.name, None) for d in dbs: db = models.PostgreSQLSchema.deserialize_schema(d) self.revoke_access(context, user.name, None, db.name) LOG.info( _("{guest_id}: Dropping user {name}.").format( guest_id=CONF.guest_id, name=user.name, )) pgutil.psql( pgutil.UserQuery.drop(name=user.name), timeout=30, )
def revoke_access(self, context, username, hostname, database): """Revoke a user's permission to use a given database. The username and hostname parameters are strings. The database parameter is a string representing the name of the database. """ LOG.info( _("{guest_id}: Revoking user ({user}) access to database" "({database}).").format( guest_id=CONF.guest_id, user=username, database=database,) ) pgutil.psql( pgutil.AccessQuery.revoke( user=username, database=database, ), timeout=30, )
def _rename_user(self, context, user, new_username): """Rename a given Postgres user and transfer all access to the new name. :param user: User to be renamed. :type user: PostgreSQLUser """ LOG.info( _("{guest_id}: Changing username for {old} to {new}.").format( guest_id=CONF.guest_id, old=user.name, new=new_username, )) # PostgreSQL handles the permission transfer itself. pgutil.psql( pgutil.UserQuery.update_name( old=user.name, new=new_username, ), timeout=30, )
def grant_access(self, context, username, hostname, databases): """Give a user permission to use a given database. The username and hostname parameters are strings. The databases parameter is a list of strings representing the names of the databases to grant permission on. """ for database in databases: LOG.info( _("{guest_id}: Granting user ({user}) access to database " "({database}).").format( guest_id=CONF.guest_id, user=username, database=database, )) pgutil.psql( pgutil.AccessQuery.grant( user=username, database=database, ), timeout=30, )
def grant_access(self, context, username, hostname, databases): """Give a user permission to use a given database. The username and hostname parameters are strings. The databases parameter is a list of strings representing the names of the databases to grant permission on. """ for database in databases: LOG.info( _("{guest_id}: Granting user ({user}) access to database " "({database}).").format( guest_id=CONF.guest_id, user=username, database=database,) ) pgutil.psql( pgutil.AccessQuery.grant( user=username, database=database, ), timeout=30, )
def _rename_user(self, context, user, new_username): """Rename a given Postgres user and transfer all access to the new name. :param user: User to be renamed. :type user: PostgreSQLUser """ LOG.info( _("{guest_id}: Changing username for {old} to {new}.").format( guest_id=CONF.guest_id, old=user.name, new=new_username, ) ) # PostgreSQL handles the permission transfer itself. pgutil.psql( pgutil.UserQuery.update_name( old=user.name, new=new_username, ), timeout=30, )
def _create_replication_user(self, pwfile): """Create the replication user. Unfortunately, to be able to run pg_rewind, we need SUPERUSER, not just REPLICATION privilege """ pw = utils.generate_random_password() operating_system.write_file(pwfile, pw, as_root=True) operating_system.chown(pwfile, user=self.PGSQL_OWNER, group=self.PGSQL_OWNER, as_root=True) operating_system.chmod(pwfile, FileMode.OCTAL_MODE("0600"), as_root=True) # TODO(atomic77) Alter user is swallowing the replication # option for some reason -- enable this code when the # underlying issue is fixed # repl_user = models.PostgreSQLUser(name=REPL_USER, # password=REPL_PW) # self._create_user(context=None, user=repl_user) # self.alter_user(None, repl_user, 'REPLICATION', 'LOGIN') pgutil.psql("CREATE USER %s SUPERUSER ENCRYPTED " "password '%s';" % (REPL_USER, pw)) return pw
def _drop_user(self, context, user): """Drop a given Postgres user. :param user: User to be dropped. :type user: PostgreSQLUser """ # Postgresql requires that you revoke grants before dropping the user dbs = self.list_access(context, user.name, None) for d in dbs: db = models.PostgreSQLSchema.deserialize_schema(d) self.revoke_access(context, user.name, None, db.name) LOG.info( _("{guest_id}: Dropping user {name}.").format( guest_id=CONF.guest_id, name=user.name, ) ) pgutil.psql( pgutil.UserQuery.drop(name=user.name), timeout=30, )
def _create_user(self, context, user, encrypt_password=None, *options): """Create a user and grant privileges for the specified databases. :param user: User to be created. :type user: PostgreSQLUser :param encrypt_password: Store passwords encrypted if True. Fallback to configured default behavior if None. :type encrypt_password: boolean :param options: Other user options. :type options: list """ LOG.info( _("{guest_id}: Creating user {user} {with_clause}.") .format( guest_id=CONF.guest_id, user=user.name, with_clause=pgutil.UserQuery._build_with_clause( '<SANITIZED>', encrypt_password, *options ), ) ) pgutil.psql( pgutil.UserQuery.create( user.name, user.password, encrypt_password, *options ), timeout=30, ) self._grant_access( context, user.name, [PostgreSQLSchema.deserialize_schema(db) for db in user.databases])
def pg_checkpoint(self): """Wrapper for CHECKPOINT call""" pgutil.psql("CHECKPOINT")