Opened 21 months ago

Last modified 3 weeks ago

#27801 assigned New feature

Make createsuperuser inspect environment variables for username and password

Reported by: Markus Holtermann Owned by: James Pic
Component: contrib.auth Version: master
Severity: Normal Keywords:
Cc: James Pic Triage Stage: Accepted
Has patch: yes Needs documentation: yes
Needs tests: yes Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

The createsuperuser management command is not quite suitable for scripting, even with the --no-input flag, as it doesn't set a password. The management command should inspect some environment variables (e.g. DJANGO_SUPERUSER_{USERNAME_FIELD.upper()} and DJANGO_SUPERUSER_PASSWORD) to pick up the username, password and possibly all other required fields.

Change History (9)

comment:1 Changed 21 months ago by lsmag

Owner: changed from nobody to lsmag
Status: newassigned

comment:2 Changed 21 months ago by Tim Graham

I'm not certain if using createsuperuser in non-interactive mode with environment variables is simpler than writing a standalone script to handle this use case. Did you give any thought to this?

comment:3 in reply to:  2 Changed 21 months ago by Markus Holtermann

Replying to Tim Graham:

I'm not certain if using createsuperuser in non-interactive mode with environment variables is simpler than writing a standalone script to handle this use case. Did you give any thought to this?

Yes, I gave it some thought. The logic in createsuperuser for ensuring all required fields are present, selecting the right database, etc is already there. With more and more automated deployments for Django projects I think having this feature built-in is essential.

I think I'd have createsuperuser fallback to the environment variables if they are present unless fields are overridden by command line arguments:

user_data = {}
for field in required_fields:
    if field in options:
        user_data[field] = options[field]
    elif 'DJANGO_SUPERUSER_' + field.upper() in os.environ:
        user_data[field] = os.environ['DJANGO_SUPERUSER_' + field.upper()]
    elif options['interactive']:
        user_data[field] = ask_for_field_value(field)
    else:
        raise CommandError('Missing value for %s' % field)

That's a rough draft!

comment:4 Changed 21 months ago by Tim Graham

I guess it could help to define the scope of the use case. Would this be meant for creating one initial superuser. Should it ease creating many superusers?

That might help clarify the need to have all fields pulled from environment variables rather than just the password. This seems to add some complication and I'd like to keep things as simple as possible.

I think the minimal script for anything more complicated is straightforward. If you're running in non-interactive mode, error handling doesn't seem like a priority.

import django
django.setup()

from django.contrib.auth import get_user_model
UserModel = get_user_model()

UserModel._default_manager.db_manager('default').create_superuser()

comment:5 Changed 21 months ago by Markus Holtermann

It's for the initial superuser when you can't run the management command in interactive mode. The only field as for AbstractBaseUser is password that needs to be passed via environment variables. However, if you have another required field that contains sensitive parameters (e.g. API key) and that is a required field you want to have that handled through environment variables as well.

Hence my though, let's use the command arguments in the first place (e.g. for username), fallback to environment variables (that allows for sensitive values) and fail if that's not defined. I'm not sure if we _need_ support for env vars in the interactive mode, i believe it wouldn't hurt, though. Not sure how complex that change might get if that's added.

comment:6 Changed 21 months ago by Tim Graham

Triage Stage: UnreviewedAccepted

comment:7 Changed 12 months ago by Jon Dufresne

Another potential script friendly solution would be to read the password from a file. Other non-Django commands implement such a feature. For example, ldapsearch -y passwdfile and the PostgreSQL password file.

comment:8 Changed 3 weeks ago by James Pic

Cc: James Pic added
Easy pickings: set
Has patch: set
Owner: changed from lsmag to James Pic

For our use case, SUPERUSER_PASSWORD works to drop the dependency to expect in automation code.

PR

Last edited 3 weeks ago by Tim Graham (previous) (diff)

comment:9 Changed 3 weeks ago by Tim Graham

Easy pickings: unset
Needs documentation: set
Needs tests: set

Not sure if that would completely address the ticket, but the patch is incomplete without tests and documentation.

Note: See TracTickets for help on using tickets.
Back to Top