encode / starlette

The little ASGI framework that shines. 🌟
https://www.starlette.io/
BSD 3-Clause "New" or "Revised" License
10.26k stars 933 forks source link

Starlette secrets and Cryptography #1381

Closed MaelAbgrall closed 2 years ago

MaelAbgrall commented 2 years ago

Checklist

Describe the bug

Hello! I'm using Starlette through FastAPI (latest), and I'm having some trouble with configuration files.

Starlette's Config secret is converting a string into a Bytes type. The problem is since I need to cast this secret to a string to access it, it creates a strange data structure.

I am trying to save in secrets a Fernet key from the cryptography pipy library. My goal is to encrypt data saved in a database. However, as you can see in the examples, I'm unable to convert back this key into a type that can be read by cryptography

Steps to reproduce the bug

requirements.txt

starlette
cryptography

.env

CRYPTO_KEY=mystring

Python interactive shell

from starlette.config import Config
from starlette.datastructures import Secret

config = Config(".env")
CRYPTO_KEY = config("CRYPTO_KEY", cast=Secret)

print(str(CRYPTO_KEY))
# b'mystring'
print(str(CRYPTO_KEY).encode())
# b"b'mystring'"

from cryptography.fernet import Fernet
Fernet(str(CRYPTO_KEY))
# Traceback (most recent call last):
#  File "<stdin>", line 1, in <module>
#   File "/usr/local/lib/python3.8/site-packages/cryptography/fernet.py", line 35,  in __init__
#     raise ValueError(
# ValueError: Fernet key must be 32 url-safe base64-encoded bytes.

Expected behavior

Either:

Actual behavior

Secrets have an unknown type, that can't be encoded or used

Debugging material

see "Steps to reproduce bug"

Environment

Additional context

No response

Kludex commented 2 years ago

I can't reproduce your issue. I'm unsure what's happening, but my guess is that it should be related to the open() of the .env file.

In any case, can you do the same check with this snippet i.e. using Environ?

from starlette.datastructures import Secret
from starlette.config import Config, Environ

config = Config(environ=Environ({"SECRET": "mystring"}))
SECRET = config("SECRET", cast=Secret)
MaelAbgrall commented 2 years ago

Hello, My apologies, I did not realise that docker restart was not updating the environment variables, and I originally stored as a Byte string.

When starting my setup this morning, the env has been updated to the new string (not byte) and all is fine!

Thank you for the quick reply