Closed DocCyblade closed 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
Yeah, I wonder if there is a way to regenerate the password after the fact, right now it's set during the init phase.
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
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
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';
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
Confirmed that for whatever reason manually setting the password like above it only works once, after login the screen goes away
@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.
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
.
@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...
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.
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).
@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:
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:
Now on login, you get the nice screen here:
So it should be pretty simple, drop the two rows and run mayan-edms.py createautoadmin
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
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.
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.
So, after a long twisting issue path, the simple thing to do:
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
Complete
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