Dump/restore users (with passwords) via API
We are trying to dump/restore users using API calls and it seems that API allows us to dump password hashes (a good thing), but then API does not allow to insert users back using saved password hashes - only cleartext passwords. Aside from create_user is there any other way to create users/change their password?
-- Sr System and DevOps Engineer SoM IRT
On Mon, Sep 17, 2018, at 12:15 PM, Dmitry Makovey wrote:
We are trying to dump/restore users using API calls and it seems that API allows us to dump password hashes (a good thing), but then API does not allow to insert users back using saved password hashes - only cleartext passwords.
I'd say that is intentional. You don't want people to be setting up hashes as passwords.
Aside from create_user is there any other way to create users/change their password?
Not that I know of, not using the API atleast. You could potentially use the low level API that inserts records in the database or use SQL to dump and restore that data.
What do you use the Core's user/password for? Currently, the user passwords are basically just a carry-over from Mailman2 and there shouldn't be any use for it. I have been considering removing that completely have Postorius do all the authentication/authorization.
Email based authentication should rely on more reliable identities like email signatures, intead of having to send cleartext passwords over email.
-- thanks, Abhilash Raj (maxking)
On 09/17/2018 12:39 PM, Abhilash Raj wrote:
On Mon, Sep 17, 2018, at 12:15 PM, Dmitry Makovey wrote:
We are trying to dump/restore users using API calls and it seems that API allows us to dump password hashes (a good thing), but then API does not allow to insert users back using saved password hashes
- only cleartext passwords.
I'd say that is intentional. You don't want people to be setting up hashes as passwords.
Aside from create_user is there any other way to create users/change their password?
Not that I know of, not using the API atleast. You could potentially use the low level API that inserts records in the database or use SQL to dump and restore that data.
What do you use the Core's user/password for? Currently, the user passwords are basically just a carry-over from Mailman2 and there shouldn't be any use for it. I have been considering removing that completely have Postorius do all the authentication/authorization.
Email based authentication should rely on more reliable identities like email signatures, intead of having to send cleartext passwords over email.
I think I am asking about the username/password auth for postorious and how to dump/restore it. At present we have no tools for dump/restoring users so that's what we're trying to build.
-- Sr System and DevOps Engineer SoM IRT
On Tue, Sep 18, 2018, at 9:19 AM, Dmitry Makovey wrote:
On 09/17/2018 12:39 PM, Abhilash Raj wrote:
On Mon, Sep 17, 2018, at 12:15 PM, Dmitry Makovey wrote:
We are trying to dump/restore users using API calls and it seems that API allows us to dump password hashes (a good thing), but then API does not allow to insert users back using saved password hashes
- only cleartext passwords.
I'd say that is intentional. You don't want people to be setting up hashes as passwords.
Aside from create_user is there any other way to create users/change their password?
Not that I know of, not using the API atleast. You could potentially use the low level API that inserts records in the database or use SQL to dump and restore that data.
What do you use the Core's user/password for? Currently, the user passwords are basically just a carry-over from Mailman2 and there shouldn't be any use for it. I have been considering removing that completely have Postorius do all the authentication/authorization.
Email based authentication should rely on more reliable identities like email signatures, intead of having to send cleartext passwords over email.
I think I am asking about the username/password auth for postorious and how to dump/restore it. At present we have no tools for dump/restoring users so that's what we're trying to build.
Ah, why not take a database dump? There are a few specific tables that you can dump to get everything?
We don't have a way to do that because we do not actually do not handle auth ourselves, but instead delegate it to allauth library. You may have to dig into internals of that to be able to fetch/restore users/passwords.
-- thanks, Abhilash Raj (maxking)
On 09/18/2018 09:22 AM, Abhilash Raj wrote:
I think I am asking about the username/password auth for postorious and how to dump/restore it. At present we have no tools for dump/restoring users so that's what we're trying to build.
Ah, why not take a database dump? There are a few specific tables that you can dump to get everything?
We don't have a way to do that because we do not actually do not handle auth ourselves, but instead delegate it to allauth library. You may have to dig into internals of that to be able to fetch/restore users/passwords.
Thanks for picking up the thread, Abhilash.
Since we're trying to get solution that would allow us to dump/restore members/users of specific mailing list etc. we need a bit more "precise" method of extracting user info. We also suspect our DB could be corrupt (we have multiple address entries per member, of which 1 would have proper address and the rest are with empty fields, what's more the ones referenced from other tables are mainly those with empty fields) thus would like to dump "clean" objects and refresh DB rather than copy corruption from DB to DB.
-- Sr System and DevOps Engineer SoM IRT
On 9/18/18 6:30 PM, Dmitry Makovey wrote:
On 09/18/2018 09:22 AM, Abhilash Raj wrote:
I think I am asking about the username/password auth for postorious and how to dump/restore it. At present we have no tools for dump/restoring users so that's what we're trying to build. Ah, why not take a database dump? There are a few specific tables that you can dump to get everything?
We don't have a way to do that because we do not actually do not handle auth ourselves, but instead delegate it to allauth library. You may have to dig into internals of that to be able to fetch/restore users/passwords. Thanks for picking up the thread, Abhilash.
Since we're trying to get solution that would allow us to dump/restore members/users of specific mailing list etc. we need a bit more "precise" method of extracting user info. We also suspect our DB could be corrupt (we have multiple address entries per member, of which 1 would have proper address and the rest are with empty fields, what's more the ones referenced from other tables are mainly those with empty fields) thus would like to dump "clean" objects and refresh DB rather than copy corruption from DB to DB.
You are in Django territory, so I would suggest using django to get the job done.
You can write your own python scripts that do that for you, you could even use the django management commands
https://docs.djangoproject.com/en/2.1/howto/custom-management-commands/
You should be able to retrieve users
from django.contrib.auth.models import User
users = User.objects.all()
user = users[0]
user.password = 'passwordHash'
user.save()
That should set the password properly.
If you need further help, the django docs are quite good, but if you need anything I'm happy to help
cheers,
Simon
On Tue, Sep 18, 2018, at 9:30 AM, Dmitry Makovey wrote:
On 09/18/2018 09:22 AM, Abhilash Raj wrote:
I think I am asking about the username/password auth for postorious and how to dump/restore it. At present we have no tools for dump/restoring users so that's what we're trying to build.
Ah, why not take a database dump? There are a few specific tables that you can dump to get everything?
We don't have a way to do that because we do not actually do not handle auth ourselves, but instead delegate it to allauth library. You may have to dig into internals of that to be able to fetch/restore users/passwords.
Thanks for picking up the thread, Abhilash.
Since we're trying to get solution that would allow us to dump/restore members/users of specific mailing list etc. we need a bit more "precise" method of extracting user info. We also suspect our DB could be corrupt (we have multiple address entries per member, of which 1 would have proper address and the rest are with empty fields, what's more the ones referenced from other tables are mainly those with empty fields) thus would like to dump "clean" objects and refresh DB rather than copy corruption from DB to DB.
I was looking at the allauth docs and wasn't able to find any public API (http or python) to export/import users.
So, I'd say the best way would be use a combination of Mailman's API and Django API in a python script to filter the members/users you want to export and import.
You can ask here for help if you need any with writing the script, but there are good docs for Django's API and for mailmanclient too.
-- Sr System and DevOps Engineer SoM IRT
Mailman-users mailing list -- mailman-users@mailman3.org To unsubscribe send an email to mailman-users-leave@mailman3.org https://lists.mailman3.org/mailman3/lists/mailman-users.mailman3.org/ Email had 1 attachment:
- signature.asc 1k (application/pgp-signature)
-- thanks, Abhilash Raj (maxking)
On 09/18/2018 10:15 AM, Abhilash Raj wrote:
I was looking at the allauth docs and wasn't able to find any public API (http or python) to export/import users.
So, I'd say the best way would be use a combination of Mailman's API and Django API in a python script to filter the members/users you want to export and import.
You can ask here for help if you need any with writing the script, but there are good docs for Django's API and for mailmanclient too.
thanks Abhilash and Simon,
we'll keep on exploring along the lines you've mentioned and post back here if we bump into something.
-- Sr System and DevOps Engineer SoM IRT
Hello: Just an update and review on a previous thread and some progress.
I'm trying to write a Python script to do the following:
- Dump all the members from a email list within mailman instance A. This includes the display name, email, password hash, and all the preferences. The output is a json file.
- Then we read this json file and create the user, membership to the email list, and the preferences into mailman instance B.
The problem is that we are trying to insert the members with the password hash and NOT a new plain text password.
A simple json dump example:
{ "password":"$6$rounds=656000$QhEAT7XCQ9tyUmJV$cj2xv3GKd8UXdSSasMZdqe0NjUL4T751nBEkdubog55jzIY1iZ5AQ4aRVeJIi1jnS1CKHHJn6nVnW.Hz91Xvk.",
"list_fqdn": "helpme@confused.com", "display_name": "Bob Nobody", "email": "nobody@nowhere.com", "preferences": { "receive_list_copy": false, "hide_address": false, "preferred_language": "en", "delivery_mode": "regular", "receive_own_postings": true, "acknowledge_posts": false, "delivery_status": "enabled" } }
The code for this within the mailman client API is pretty straight forward. However, the method for create_member will not work for our situation because the argument requires the password to be in plain text to be encrypted later. The rest of the tasks (subscribing, preferences) can be done with the mailman client with this single exception.
Now my question is irf someone can send a single piece of code example or where to look to accomplish this.
I see two options:
Using the mainman core. I believe the modified code would be something like this:
user_manager = getUtility(IUserManager) #with transaction(): new_user = user_manager.create_user( 'nobody@where.com', 'Bob Nobody') new_user.password = config.password_context.encrypt('abc123') #replace with hash new_user.password = '$6$rounds=656000$tS8sTX'
So the password is set with the hash instead of the encryption method.
Original code: new_user.password = config.password_context.encrypt('abc123')
The other possible method is through django. However, I'm not really sure where to being on this on as I've been looking over the django-mailman3 and this is the only example I can find in test_delete_account.py:
def setUp(self): self.mm_user = Mock() self.mm_user.user_id = "dummy" self.mailman_client.get_user.side_effect = lambda e: self.mm_user self.user = User.objects.create_user( 'testuser', 'test@example.com', 'testPass', first_name="firstname", last_name="lastname", )
self.client.login(username='testuser', password='testPass')
Again, it appears that the password is encrypted somewhere else before encrypted.
Any help on this is greatly appreciated.
Thanks
Conrad
Please note that for authentication the frontend keeps it's own database. So the used usernames/passwords are not available in core and need to be restored from the frontend's database. So to migrate a mailman3 instance you need to migrate the data stored in core _and_ the data stored in the frontend/django.
It looks like you are doing fine with the core stuff. I would recommend using django's builtin methods to do the rest.
You are looking for dumpdata/loaddata.
https://docs.djangoproject.com/en/2.1/ref/django-admin/#dumpdata
Note the warning about the permissions and content-type tables.
https://docs.djangoproject.com/en/2.1/ref/django-admin/#cmdoption-dumpdata-n...
If you haven't changed anything in these tables (You probably haven't) You can safely ignore these tables using the --exclude option during dumping.
A manual method to restore Users can be found inline in this reply.
On 9/26/18 12:20 AM, Conrad Holmberg wrote:
Hello: Just an update and review on a previous thread and some progress.
I'm trying to write a Python script to do the following:
- Dump all the members from a email list within mailman instance A. This includes the display name, email, password hash, and all the preferences. The output is a json file.
- Then we read this json file and create the user, membership to the email list, and the preferences into mailman instance B.
The problem is that we are trying to insert the members with the password hash and NOT a new plain text password.
A simple json dump example:
{ "password":"$6$rounds=656000$QhEAT7XCQ9tyUmJV$cj2xv3GKd8UXdSSasMZdqe0NjUL4T751nBEkdubog55jzIY1iZ5AQ4aRVeJIi1jnS1CKHHJn6nVnW.Hz91Xvk.",
"list_fqdn": "helpme@confused.com", "display_name": "Bob Nobody", "email": "nobody@nowhere.com", "preferences": { "receive_list_copy": false, "hide_address": false, "preferred_language": "en", "delivery_mode": "regular", "receive_own_postings": true, "acknowledge_posts": false, "delivery_status": "enabled" } }
The code for this within the mailman client API is pretty straight forward. However, the method for create_member will not work for our situation because the argument requires the password to be in plain text to be encrypted later. The rest of the tasks (subscribing, preferences) can be done with the mailman client with this single exception.
Now my question is irf someone can send a single piece of code example or where to look to accomplish this.
I see two options:
Using the mainman core. I believe the modified code would be something like this:
user_manager = getUtility(IUserManager) #with transaction(): new_user = user_manager.create_user( 'nobody@where.com', 'Bob Nobody') new_user.password = config.password_context.encrypt('abc123') #replace with hash new_user.password = '$6$rounds=656000$tS8sTX'
So the password is set with the hash instead of the encryption method.
Original code: new_user.password = config.password_context.encrypt('abc123') As mentioned in a previous thread, the password that is stored in core, isn't being used anywhere. So saving/restoring it is of no use.
The other possible method is through django. However, I'm not really sure where to being on this on as I've been looking over the django-mailman3 and this is the only example I can find in test_delete_account.py:
That is the correct password to save/restore.
the create_user method takes a plaintext password and hashes it. So you would need to do something like this:
user = User()
user.username = 'username'
user.email = 'email@example.com'
user.password = 'password-hash'
user.save()
Setting the password like this bypasses the hashing, which is what you want.
def setUp(self): self.mm_user = Mock() self.mm_user.user_id = "dummy" self.mailman_client.get_user.side_effect = lambda e: self.mm_user self.user = User.objects.create_user( 'testuser', 'test@example.com', 'testPass', first_name="firstname", last_name="lastname", )
self.client.login(username='testuser', password='testPass')
Again, it appears that the password is encrypted somewhere else before encrypted.
Any help on this is greatly appreciated.
Thanks
Conrad
Mailman-users mailing list -- mailman-users@mailman3.org To unsubscribe send an email to mailman-users-leave@mailman3.org https://lists.mailman3.org/mailman3/lists/mailman-users.mailman3.org/
participants (4)
-
Abhilash Raj
-
Conrad Holmberg
-
Dmitry Makovey
-
Simon Hanna