Where does trac store the users and passwords in a default installation? - trac

I have a long list of users to delete. I logged in the trac.db but I don't find anything similar to a user/password table. where does trac store the users and passwords in a default installation?

For future reference: probably the easiest way (since Trac 0.12) would be to use
$ trac-admin <path-to-trac-env> session list
$ trac-admin <path-to-trac-env> session delete username1 username2 ...

First and foremost: There is no clearly shaped concept of neither account nor user in Trac until now. What is referred to as 'username' is basically the authenticated session ID, or an arbitrary string mapped to an 'anonymous' session.
Look at the definitive reference on Trac's db schema:
The session table holds all valid session IDs. Note that the key is 'sid' + 'authenticated' flag (0 = unauthenticated, 1 = authenticated). Users in anonymous sessions are allowed to choose another, more memorable session ID via session preferences, if they like.
It depends on the Trac db back-end, if the primary key for session is enforced as foreign key in session_attribute too. This is the other relevant table, that holds additional attributes like first name+surname or email address for a given session. Again 'sid' + 'authenticated' flag combined are the primary key there.
Anonymous sessions get purged after some time of inactivity (watch out for POSIX seconds/microseconds timestamps in 'last_visit' of session table) by Trac automatically, while entries for authenticated sessions stay there forever. You're most likely looking for them (SELECT sid,last_visit FROM session WHERE authenticated=1).
You'll not find a password hash in the Trac db. Only Trac plugins like AccountManager's SessionStore will store their password hash (should never-ever be a password in cleartext) in the db (table 'session_attribute' in that case). Depending on your authentication setup the user credentials are managed independently, i.e. in a file in Apache htpasswd/htdigest format, that is used by the web-server Trac is running on, or tracd for the stand-alone Trac setup.

Related

How to restrict a user to a single signed in session

I'm working on a website where a user is only allowed to have a single signed-in session. If a user attempts to authenticate to the website from more than one location the prior session is logged out.
The session information for a given user will be stored in Redis.
My current implementation uses two Redis databases. The first database stores session ID as the key and username as the value. The second database stores the username as the key and some other information including session ID as the value.
When a user logs in, the second Redis database is queried to find an existing session ID. If found, the old session is deleted, this would essentially force the user's old session to log out. After the old session is removed, we create another session in the first database and update the value of the session ID in the second database using the username as the key.
Here is a demonstration of this behavior using the "redis-cli":
redis-cli
select 2
get username
The website gets the session ID of the previous session and then generates a new session ID...
redis-cli
select 1
del old_session_id
set new_session_id username
select 2
set username new_session_id
This works, but I want to optimize it. In this solution, the website would query Redis twice because we have to get the old session id and delete it.
My question is: Can we combine the two queries?
My challenge is how to read the command get username result and automatically run del old_session_id against the Redis database.
Can anybody help me?
According to the SET documentation, you can add the GET option to write a key and get its old value. I would use this on database 2 first. If it returns an old session id, you can use RENAME to change the key name. If it doesn't return an old session id, you can just use another SET.
You should be able to get your setup to work with something like this:
redis-cli
select 2
set username new_session_id get
If that command returns a value, run this:
redis-cli
select 1
rename old_session_id new_session_id
If it does not return a value, run this:
redis-cli
select 1
set new_session_id username

MaxDB - User does not access tables

I have created a new user in a MaxDb database. I assign a role that has access to all the tables in roleprivileges but the user can not see these tables.
The user can access the tables if I assign permissions directly to the tables in tableprivileges.
The role has access, other users have this role assigned and they see all the tables.
What can be failing?
Today I've heard of MaxDB for the first time (what an ignoramus, eh?). I'm not sure why you tagged your question with the "Oracle" tag; Google says that MaxDB <> Oracle.
Anyway: it sounds like common problems in Oracle's PL/SQL, where privileges - acquired via roles - won't work, but have to be granted directly to the user.
Saying that "other users have this role assigned and they see all the tables", are you sure that they don't have direct privileges granted as well?
Assuming this deals indeed with MaxDB, and not with Oracle:
In contrast to privileges, roles need to be activated for a user session. Assigning is not enough. It is done by command SET ROLE <role>.
A role may also be activated as default for every new session, with command:
ALTER USER <user> DEFAULT ROLE <role>.
You can also activate all roles assigned to the user, like this:
ALTER USER <user> DEFAULT ROLE ALL.

Read-only access for Heroku Postgres Databases

I have a Heroku Postgres database for my application. I can easily access the psql shell using the provided DATABASE_URL from Heroku
psql $(heroku config:get DATABASE_URL -a my_app)
psql (9.6.1)
SSL connection (protocol: TLSv1.2, cipher: ECDSE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.
d5i032ahpfiv07=>
And by default, this user seems to have full access to update and drop tables
d5i032ahpfiv07=> SELECT
table_name,
string_agg(privilege_type, ', ') as privileges
FROM information_schema.role_table_grants
WHERE table_schema = 'public'
AND grantee = current_user
GROUP BY 1
;
table_name | privileges
-----------------------------------+---------------------------------------------------------------
articles | INSERT, TRIGGER, REFERENCES, TRUNCATE, DELETE, UPDATE, SELECT
comment_flags | TRIGGER, INSERT, SELECT, UPDATE, DELETE, TRUNCATE, REFERENCES
comment_likes | TRUNCATE, REFERENCES, TRIGGER, INSERT, SELECT, UPDATE, DELETE
comments | INSERT, SELECT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER
communities | TRIGGER, REFERENCES, TRUNCATE, DELETE, UPDATE, SELECT, INSERT
.....
I'd love to set up "Read Only" users in the database so that people can view this data without fear of running "DROP TABLE" or some other destructive command.
How can I go about setting up a read-only user on Heroku Postgres?
Thank you!
Create a Heroku Postgres Follower Database
A database follower is a read-only copy of the leader database that
stays up-to-date with the leader database data. As writes and other
data modifications are committed in the leader database, the changes
are streamed, in real-time, to the follower databases.
Then simply run your analytics, dataclips, and other read-only applications against the follower. This is a very standard configuration that safeguards your main DB, and has added performance benefits: you can hammer it with queries (which are often intensive and have different cache profiles) without affecting your user-facing application.
Adam's suggestion to create a follower database is usually the right solution for this, but it's possible to create a read-only role (or any other permissions you want), for any Heroku Postgres database, even one that isn't a follower.
Heroku has detailed documentation for this at Heroku Postgres Credentials, but briefly:
Create Heroku credential
heroku pg:credentials:create <addon_name> --name new_credential -a <app_name>
<addon_name> is the name of your Postgres addon, which you can find by running heroku pg:info -a <app_name> and checking the "Add-on" line in the output.
The new credential is named new_credential in the above command, but you can use whatever name you want.
Set permissions
Creating the new_credential credential also creates a new_credential role (see Postgres roles documentation) in your Postgres database. You can set the permissions for new_credential like any other role, using psql. By default, the role has no permissions. The Heroku docs give this example, to run in psql:
GRANT USAGE ON SCHEMA PUBLIC TO new_credential;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO new_credential;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT SELECT ON TABLES TO new_credential;
The above sets the new_credential role to have read-only privileges. See the Postgres documentation on privileges for more details.
Attach the credential
Before you can use the credential, you need to attach it to your app:
heroku addons:attach <addon_name> --credential new_credential -a <app_name>
When you run the addons:attach command, the output will include a new config var named HEROKU_POSTGRESQL_<COLOUR>_URL, where <COLOUR> is some colour. This config var holds a Postgres connection URL you can use to connect to the database using the new_credential role.
Using the credential
In an app, connect to the database using the new config var created in the last step instead of the default DATABASE_URL (which still contains the default, read-write credentials).
You can also use the new role in psql:
heroku pg:psql <addon_name> --credential new_credential -a <app_name>
Or, if you want to use psql directly as in your example, you can use the new colour URL:
psql $(heroku config:get HEROKU_POSTGRESQL_<COLOUR>_URL -a <app_name>)
When you connect to Postgres using the new role, any attempts to create, update, or drop data will be rejected by Postgres due to the role's permissions.
It has kind of already been said, but this is a simple solution for those who don't want to get real technical.
https://data.heroku.com/dataclips
You can just create dataclips here for each or any individual Heroku app that you have. You run whatever queries you like, and then you can share it via URL, CSV, JSON, Google Sheet, or you can even add individual people or teams to have access to them.
It's nice cause you have the Heroku web UI to use (rather than through CLI), and it doesn't necessarily give someone complete access to the DB, just what you want them to see; which is suitable for some people's specific needs/scenarios.

GRANT EXECUTE for "sp_delete_database_backuphistory" for group of users

I have a group login which has the Server Role "dbcreator". Users of this login has been granted execute on "sp_delete_database_backuphistory" so that they can delete each others databases. The problem now is that it is possible for these users to delete databases created by other logins. Is there a solution for this? Can permission´s be set, so that these users ONLY can delete databases created with this login?
You can't do this directly, but you can wrap the system sp_delete_database_backuphistory into your own usp_delete_database_backuphistory
that can call sp_delete_database_backuphistory or return immediately depending on a result of the check you want to perform.
I cannot ask you in a comment what do you mean saying 'databases created by other users', first of all only login (not user) can create a database but this information (db creator) you cannot extract from any system metadata, all you can get is the current database owner and this can differ from database creator.
I mean, when you create a database you can explicitly assign other login to own the database, or you can do this later for certain purposes

Update user password in Mysql 5.7

I wrote an installation script to change the root password with this SQL command:
UPDATE user SET password='*C563415623144561...' WHERE user='root';
This doesn't work on Mysql 5.7:
http://dev.mysql.com/doc/relnotes/mysql/5.7/en/news-5-7-6.html#mysqld-5-7-6-account-management
My question is: how to change this command with another one compatible with 5.6 and 5.7 version of Mysql? I would like to update the password with a hashed string and not with a clear password.
This is no more password field in the user table as of mysql 5.7. It's now called authentication_string. You can change or set the password like this:
set password for 'jeff'#'localhost' = PASSWORD('mypass'); // this automatically hashes the password
If you you want to use your query , just change password to authentication_string,and it will work.
UPDATE user SET authentication_string='*C563415623144561...' WHERE user='root#localhost';
Hope this help.
I've used this command to reset to empty password in Mysql 5.7.22
ALTER USER 'root'#'localhost' IDENTIFIED WITH mysql_native_password BY '';
Given that 'SET PASSWORD FOR = PASSWORD('')' is deprecated as on mysql 5.7. If not done correctly you could even end up with below error in syslog.
The plugin 'auth_socket' used to authenticate user 'root'#'localhost' is not loaded. Nobody can currently login using this account.
I suggest to use below command.
ALTER USER 'root'#'localhost' IDENTIFIED WITH mysql_native_password BY 'mypass';
https://www.percona.com/blog/2016/03/16/change-user-password-in-mysql-5-7-with-plugin-auth_socket/
On Ubuntu 19.10 with mysqld version 8.0.19, none of the above worked for me. The instructions given here https://linuxconfig.org/how-to-reset-root-mysql-mariadb-password-on-ubuntu-20-04-focal-fossa-linux worked. It's for MariaDB, but it's the same if don't use MariaDB. The two key points are : the function password() is removed in mysqld 8.0+ and, for some reason, the unix socket for mysqld is not created with the --skip-grant-tables options. So, you must use these modified instructions:
$ sudo systemctl stop mysql
$ sudo mkdir -p /var/run/mysqld
$ sudo chown mysql:mysql /var/run/mysqld
$ sudo /usr/sbin/mysqld --skip-grant-tables --skip-networking &
Check that the daemon mysqld is running:
$ ps aux | grep mysqld
If it is running, then start mysql and change the password
$ mysql -u root
> FLUSH PRIVILEGES;
> USE mysql;
> ALTER USER 'root'#'localhost' IDENTIFIED BY 'N3w_p#ssw0rD.';
> quit
Important: before you (re)start mysqld, you need to kill the current process. Just stopping it the normal way does not work.
$ sudo pkill mysqld
$ sudo systemctl start mysql
Then you can test:
$ mysql -u root --password='N3w_p#ssw0rD.'
First of all look your specified mysql version security policies.
show variables like '%validate_password%';
you can change this policy if you like with
set variable_name=new_value;
Changing appropriate user password.
MySQL 5.7.5 and earlier version:
SET PASSWORD FOR 'user_name' = PASSWORD('new_password');
MySQL 5.7.6 and later version:
alter user 'user_name' identified by 'new_password';
For Server version: 5.7.25 - MySQL Community Server (GPL). Use below query as password is no more valid and replaced by authentication_string
UPDATE user SET authentication_string = PASSWORD('yourpassword'), password_last_changed = NULL
WHERE user.Host = 'localhost' AND user.User = 'username';
I'm no MySQL authority, but based on MySQL's current 5.7 documentation, the suggestions in the currently accepted and most upvoted answer strike me as inadvisable. (This is likely due to the passage of time -- the question and #mdamia's answer were both posted in 2015.)
The MySQL 5.7.6 (2015-03-09, Milestone 16) release notes linked by #Tobia's question say "ALTER USER is now the preferred statement for assigning passwords."
The question did ask if a single command could be used for both MySQL 5.6 and 5.7, but given that the ALTER USER syntax implemented by MySQL >= 5.7.6 offers a security enhancement, I would use the newer syntax when it is available. If I still had to operate a MySQL < 5.7.6 installation, I would limit my use of older and deprecated/discouraged password-updating syntax to those circumstances.
The ALTER USER statements suggested by #Carlos Alberto GarcĂ­a Guardia and #Venkat Kotra in their answers thus seem to me like the right syntax to use for MySQL >= 5.7.6. Two examples (adapted from their answers and the ALTER USER documentation for MySQL 5.7): :
ALTER USER '<username>'#'localhost'
IDENTIFIED BY '<new_cleartext_password>';
ALTER USER '<username>'#'localhost'
IDENTIFIED WITH <auth_plugin>
BY '<new_cleartext_password>';
The second example above contains an optional WITH clause to specify an authentication plugin. The plugin specified gets written to the "plugin" field of the mysql.user table. For background on the history and future of MySQL authentication plugins, I found these MySQL Server Team blog posts helpful:
"Protecting MySQL Passwords With the sha256_password Plugin"
"New Default Authentication Plugin: caching_sha2_password"
In answer to #Tobia's question how to pass the new password to MySQL in hashed format rather than cleartext, the MySQL ALTER USER documentation indicates that this is done by using AS in place of BY in the ALTER USER statement:
ALTER USER '<username>'#'localhost'
IDENTIFIED WITH <auth_plugin>
AS '<new_hashed_password_value>';
When using AS instead of BY, the ALTER USER documentation says, the password string "is assumed to be already in the format the authentication plugin requires, and is stored as is in the mysql.user table." If a plugin requires a hashed value, "the value must be hashed in a format appropriate for the plugin. Otherwise, the value is not usable by the plugin and correct authentication of client connections will not occur." Id.
The currently accepted answer suggests using either a SET PASSWORD ... PASSWORD() statement or an UPDATE statement (the former for passing the new password in cleartext and the latter for passing it in hashed format):
SET PASSWORD
FOR '<username>'#'localhost' =
PASSWORD('<mypass_in_cleartext>');
or
UPDATE mysql.user
SET authentication_string='<mypass_as_hash>'
WHERE User='<username>';
These statements are deprecated and/or discouraged in relation to the currently preferred ALTER USER statement.
SET PASSWORD ... = PASSWORD(<cleartext>) "is deprecated as of MySQL 5.7.6 and will be removed in a future MySQL release", according to the SET PASSWORD documentation.
The SET PASSWORD ... = 'auth_string' syntax (i.e., leaving out the PASSWORD(str) encryption function) "is not deprecated, but ALTER USER is the preferred statement for account alterations, including assigning passwords." Id. See also Removal and Deprecation in MySQL 5.7:
We have deprecated the SET PASSWORD syntax and the PASSWORD() function. The existing ALTER USER statement is modified to cover the deprecated functionality. The PASSWORD() function was originally introduced as a way to manually update the mysql.user table. This is generally a bad idea and we want to leave the task of managing user authentication properties exclusively to using the ALTER USER statement which automatically determines which authentication plugin should be used and then adjusts the password algorithm accordingly.
As described by the manual, it also appears that UPDATE is less secure than ALTER PASSWORD with respect to logging. The manual indicates that UPDATE statements are written to logs as is, becoming visible to anyone with read access to the logs.[1] In contrast, the manual indicates, when MySQL writes ALTER USER ... IDENTIFIED BY ... statements (and also SET PASSWORD statements) to logs, it rewrites the contained passwords so they do "not appear literally".[1]
At least in most circumstances. The documentation for SET PASSWORD and ALTER USER warns that these statements too can be logged with visible passwords "under some circumstances",[2] although presumably not in all circumstances as apparently is the case with UPDATE.
1: See MySQL 5.7 manual on password logging ("In particular, INSERT or UPDATE statements for the mysql.user system table that refer to literal passwords are logged as is, so you should avoid such statements. (Direct modification of grant tables is discouraged, anyway.)")
2: See MySQL 5.7 SET PASSWORD documentation and MySQL 5.7 ALTER USER documentation
Disclaimer: I'm just sharing my interpretation upon reading the MySQL manual today. I haven't tested MySQL's behavior with respect to what password-altering statements it logs where in what format.
This is the only way to me in: mysql Ver 14.14 Distrib 5.7.30
UPDATE user SET authentication_string = PASSWORD('YourPassword'), password_last_changed = NULL
WHERE user.Host = 'localhost' AND user.User = 'YourUsername';