DocCyblade / tkl-mayan-edms

Turnkey Linux - Mayan EDMS
https://www.turnkeylinux.org/mayan-edms
Other
4 stars 12 forks source link

Testing: Admin password the same #60

Closed DocCyblade closed 7 years ago

DocCyblade commented 7 years ago

It looks like during build time of the ISO the admin password gets generated. We may want to wait to actually build the database during first boot. This would change a good part of the build script and move it the first boot inithooks

JedMeister commented 7 years ago

As a general rule, as much as possible should be done at build time. Other appliances that do a similar thing set a generic password at build time, then use an inithook to reset the password on firstboot. E.g. Mattermost: https://github.com/turnkeylinux-apps/mattermost/blob/master/overlay/usr/lib/inithooks/bin/mattermost.py

DocCyblade commented 7 years ago

Yeah, I wonder if there is a way to regenerate the password after the fact, right now it's set during the init phase.

DocCyblade commented 7 years ago

Did a quick look under the SQL hood, it seems it's using some form of passlib.hash further looking I found in the table autoadmin_autoadminsingleton there it stores the plan text password along with the hash, removing this entry removes the message.

I did some googling and some try an error and figured out this

I tried to manual on a python prompt do the following:

>>> from passlib.hash import django_pbkdf2_sha256 as djpass 
>>> hash = djpass.encrypt("TurnKey123")
>>> hash
'pbkdf2_sha256$10000$16lXxBtiICct$1FueJNgs6qcXUFhtB/5Mo79YWqFNRdv72ktokzdGnpw='

I then manually updated the user in the table auth_user and it worked!

So what we should do is create a new random password, hash it, and then update the database on a first boot init hook!

More reading here about Django password hashing

More reading about python pass lib and django here

DocCyblade commented 7 years ago

More reading I found that passlib has a password generator (probably what Mayan uses)

>>> from passlib.hash import django_pbkdf2_sha256 as djpass 
>>> from passlib import utils as passutils
>>> newpass = passutils.generate_password(size=10)
>>> newpass
'QKeuxNxe7Z'
>>> newhash = djpass.encrypt(newpass)
>>> newhash
'pbkdf2_sha256$10000$2uigEQzQIPhb$dqwJB4xDNBJWmxg+CnlnaozkPF8E48MhEYPCxUOJE/c='
>>> djpass.verify(newpass, newhash)
True
>>> djpass.verify('bad password', newhash)
False
DocCyblade commented 7 years ago

sql commands

Update message:

UPDATE "autoadmin_autoadminsingleton" SET
"password" = 'QKeuxNxe7Z',
"password_hash" = 'pbkdf2_sha256$10000$2uigEQzQIPhb$dqwJB4xDNBJWmxg+CnlnaozkPF8E48MhEYPCxUOJE/c=',
WHERE "id" = '1';

Update the user

UPDATE "auth_user" SET
"password" = 'pbkdf2_sha256$10000$2uigEQzQIPhb$dqwJB4xDNBJWmxg+CnlnaozkPF8E48MhEYPCxUOJE/c=',
WHERE "username" = 'admin';
DocCyblade commented 7 years ago

Noticed that when you change it like this, it does show only once on the login screen, after you login it is removed. I don't think that is the default behavior. I will have to check

DocCyblade commented 7 years ago

Confirmed that for whatever reason manually setting the password like above it only works once, after login the screen goes away

DocCyblade commented 7 years ago

@rosarior - Wanted you to bring you in to see your perspective. So normally with TurnKey linux we do the build of the OS and install and for any type of passwords or such we set them with a random cookie. Then during first boot init hook scripts we ask the user for passwords and update them.

Mayan is a little different in that the secret key in the local.py config file is generated on initalsetup, so is the admin user. We would like to try and update it during first boot but as you will see from my above posts it seems I can update the admin user password and the admin singleton table but after first login it NULLs out the admin singleton table entry.

If I can persuade @JedMeister to save the database setup and final config to first boot init hook it would solve this issue, but it does not follow the patterns TKL has been following.

Or, if you can tell me why the admin message disappears after one login, or suggest a better way of generating a new password that would be great.

ghost commented 7 years ago

Django itself doesn't provide a way to create super user or change the password of users in non-interactive ways. I created django-autoadmin to create automatic admin with sensible default passwords. You might be able to use Django's createsuperadmin and changepassword commands using something like expect.

JedMeister commented 7 years ago

@DocCyblade - Roberto's advice might point you in the right direction? As you know my python is pretty poor and my knowledge of Django is pretty basic too so I have nothing of value to add sorry.

I'm not against using SQL files per se, just not great big ones which are quite opaque and will require future maintenance.

If you can whittle it down to the specific SQL required just to update the little bit(s) you need that's ok. Perhaps you could try doing a few full SQL dumps (at different points) and run diffs on them to see what else is changing and where? Just throwing ideas around...

DocCyblade commented 7 years ago

I did find a command we can run that will create the admin account but we will need to remove it with SQL command first.

JedMeister commented 7 years ago

Does that mean that the original Admin user becomes orphaned? Or does the new admin user auto inherit the previous admin users stuff? If the former, what are the deeper implications of that on an existing system that includes docs and data?

Regardless I might ask Alon if he has any ideas. He's fairly well versed in Django (the Hub is a Django app).

DocCyblade commented 7 years ago

@JedMeister - So the issue is that during the conf stage of the build the command: mayan-edms.py initialsetup is run. His comment tipped me off to look at the code here on gitlab..

So I tried to see if I could run this command, and it looks like I can:

screen shot 2016-11-17 at 5 26 27 am

If you try and run it with the admin user already created it won't work, remove the admin user and the preference record, you can re-run the command:

screen shot 2016-11-17 at 5 26 45 am

Now on login, you get the nice screen here:

screen shot 2016-11-17 at 5 23 36 am

So it should be pretty simple, drop the two rows and run mayan-edms.py createautoadmin

DocCyblade commented 7 years ago

To be even more precise:

mysql << EOF

DELETE FROM "autoadmin_autoadminsingleton"
WHERE ("id" = '1');

DELETE FROM "common_userlocaleprofile"
WHERE ("user_id" = '1');

DELETE FROM "auth_user"
WHERE ("username" = 'admin');

EOF

cd /usr/share/mayan-edms/
source bin/activate
mayan-edms.py createautoadmin
JedMeister commented 7 years ago

If you try and run it with the admin user already created it won't work

It's a pity that we can't just use changepassword to change the password...

Where/when does that "first time login" screen display? IMO if it displays prior to login then that's not ideal. But if it displays after login then is it actually that relevant for us? The user has set their password in the inithooks (so the password reset warning is irrelevant) and they needed to login with their admin user account already?! The only bit that appears that useful is the email, but IMO we can just document that somewhere.

DocCyblade commented 7 years ago

TBH I did not try changepassword. If we do, we would still need to update the auto admin singleton. That is the part that puts up the login splash screen, but you just gave me another thought to just python ask for new password and set it.

I'll head down that road, not sure why I did not think of that before.

DocCyblade commented 7 years ago

So, after a long twisting issue path, the simple thing to do:

  1. On first boot, ask for new admin password and email (python script)
  2. Update the database (bash script or python)

Easy said than done. Need to look at existing change password python scripts as a starting point. Since we change the database password anyway on first boot, we would know the password to the root user of MySQL, we could in one bash script called from python: email address of admin, encrypted password. Script will generate new password for database user, use that password to connect to database and update the email and encrypted password.

Look at:

Init Hook shell script: https://github.com/DocCyblade/tkl-odoo/blob/master/overlay/usr/lib/inithooks/firstboot.d/40-odoo-adminpassword

Helper python script: https://github.com/DocCyblade/tkl-odoo/blob/master/overlay/usr/lib/inithooks/bin/odoo.py

DocCyblade commented 7 years ago

Complete