-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Hide secrets #1553
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Hide secrets #1553
Conversation
807651f
to
0cd8171
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please do not run black
and isort
in this PR, even though I love both tools it makes reviewing a PR much harder due to unrelated changes.
@trbs I can remove the commit where I did, rebase, and send again. Is there another change to make in this PR? |
You can make it into a separate PR for this file and I will merge it. |
0cd8171
to
74a9292
Compare
@staticmethod | ||
def safe_settings(): | ||
try: | ||
return SafeExceptionReporterFilter().get_safe_settings() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same comment as on the other PR :-)
Either the comment below is wrong or the code is... if django < 3.0 does not have the class then the imports at the top will already have raised an ImportError.
Also if this method does not serve any other purpose just deal with this in its entirely at the top of the file and at startup time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@trbs do you mean, have a try-catch block at the top of the file and make an alias for the correct import? Like:
try:
from django.views.debug import SafeExceptionReporterFilter as settings
except ImportError:
from django.views.debug import get_safe_settings
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I made this function because Django > 3.0 does exist in this class and inside of it, there's the method. For Django < 3.0 does exist only the method
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, if the problem is an ImportError
then the above should do otherwise you can so something similar with an AttributeError
.
But in the latter case at the very least the comment needs to be updated to reflect this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should keep in this way:
try:
from django.views.debug import SafeExceptionReporterFilter
except ImportError:
from django.views.debug import get_safe_settings
...
@staticmethod
def safe_settings():
try:
return SafeExceptionReporterFilter().get_safe_settings()
except AttributeError:
# In django < 3.0 does not have this class
# We have to make a different import
return get_safe_settings()
Is safer, we have only one function to return the safe settings and we can update the comment. How'd you think should be the new comment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This won't work because SafeExceptionReporterFilter
will not exist and raise a NameError
instead of an AttributeError
.
Why if the ImportError
gives us all the information not just use that ?
try:
from django.views.debug import SafeExceptionReporterFilter
except ImportError:
# Django >= 3.0
from django.views.debug import get_safe_settings
else:
def get_safe_settings():
return SafeExceptionReporterFilter().get_safe_settings()
Having the separate method on the class only makes sense to me if one would expect users to override that.. which I don't think will happen... then something like settings.PRINT_SETTINGS_SAFE_FUNC
makes more sense so people have a way to override it... (but we also don't need that right now)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I liked your suggestion. I'll add it. Thanks for help me with this!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@trbs Actually, I made a mistake.Django < 3.0
does have the class SafeExceptionReporterFilter
, but the method get_safe_settings
is outside this class in those versions, only in recent versions the SafeExceptionReporterFilter
does have the method get_safe_settings
. Look at these links:
https://github.com/django/django/blob/stable/2.2.x/django/views/debug.py#L125
https://github.com/django/django/blob/stable/2.2.x/django/views/debug.py#L72
Even in Django == 3.0
https://github.com/django/django/blob/stable/3.0.x/django/views/debug.py#L72
https://github.com/django/django/blob/stable/3.0.x/django/views/debug.py#L125
Only in Django 3.1 occurs the change
https://github.com/django/django/blob/stable/3.1.x/django/views/debug.py#L108
That's why I used AttributeError
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see... maybe I made a typo when I got the ImportError
before...
But we can still use the same style:
try:
from django.views.debug import SafeExceptionReporterFilter
def get_safe_settings():
return SafeExceptionReporterFilter().get_safe_settings()
except AttributeError:
# Django < 3.1
from django.views.debug import get_safe_settings
Alternatively we can add this to django_extensions/compat.py
and keep this file a little bit cleaner :-)
Sure. I will finish the adjustments here and send this PR |
if self.include_attr(attr, options['setting']): | ||
value = getattr(settings, attr) | ||
a_dict[attr] = value | ||
if show_secrets: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should be able to do this cleaner.... it smells like a lot of code duplication to me...
Makes more sense to do something like:
if show_secrets:
settings_dct = {k: getattr(settings, k) for k in dir(settings) if k.isupper()}
else:
settings_dct = get_safe_settings()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I agree!
While looking at your pull request I did some cleanup in Regretfully this does mean you will need to rebase.... (If you do not want to do this I can understand that and I can implement |
@trbs No problem at all! I'll rebase it |
|
||
out, err = capsys.readouterr() | ||
|
||
assert '*******' in out |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we make the check a little bit more explicit ?
eg use --format=pprint
that would allow checking for {'SECRET_KEY': 'dummy'}
$ ./manage.py print_settings --format=pprint SECRET_KEY
{'SECRET_KEY': 'dummy'}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and adding an explicit check for the variant with --show-secrets
would be even cooler ;-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure!
dest='indent', | ||
type=int, | ||
help='Specifies indent level for JSON and YAML' | ||
) | ||
parser.add_argument( | ||
'--show-secrets', | ||
default=DEFAULT_SECRETS, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use action='store_true'
like the --fail
option that way we don't need DEFAULT_SECRETS
and the cli parser knows how to do the "right-thing"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right. Thanks for the tip!
This PR adds a new option during
print settings
call, to hide/show the secrets, replacing them with '*****'. #1524