Error when upload files to Azure Blob storage through Django App
I need to build a file manager to upload images from a Django app to Azure blob storage. However, when I try to upload a file to Azure's blob storage, I get the following error:
Traceback (most recent call last): File "/Users/marilynmarquez/Desktop/webster/python/file_manager/venv/lib/python3.10/site-packages/django/core/handlers/exception.py", line 55, in inner response = get_response(request) File "/Users/marilynmarquez/Desktop/webster/python/file_manager/venv/lib/python3.10/site-packages/django/core/handlers/base.py", line 197, in _get_response response = wrapped_callback(request, *callback_args, **callback_kwargs) File "/Users/marilynmarquez/Desktop/webster/python/file_manager/website/files/views.py", line 27, in upload_file new_file=upload_file_to_blob(file) File "/Users/marilynmarquez/Desktop/webster/python/file_manager/website/files/azure_controller.py", line 57, in upload_file_to_blob blob_client =create_blob_client(file_name = file_name) #problem File "/Users/marilynmarquez/Desktop/webster/python/file_manager/website/files/azure_controller.py", line 20, in create_blob_client storage_credentials = secret_client.get_secret(name=settings.AZURE_STORAGE_KEY_NAME) #problem File "/Users/marilynmarquez/Desktop/webster/python/file_manager/venv/lib/python3.10/site-packages/azure/core/tracing/decorator.py", line 78, in wrapper_use_tracer return func(*args, **kwargs) File "/Users/marilynmarquez/Desktop/webster/python/file_manager/venv/lib/python3.10/site-packages/azure/keyvault/secrets/_client.py", line 72, in get_secret bundle = self._client.get_secret( File "/Users/marilynmarquez/Desktop/webster/python/file_manager/venv/lib/python3.10/site-packages/azure/keyvault/secrets/_generated/_operations_mixin.py", line 1574, in get_secret return mixin_instance.get_secret(vault_base_url, secret_name, secret_version, **kwargs) File "/Users/marilynmarquez/Desktop/webster/python/file_manager/venv/lib/python3.10/site-packages/azure/core/tracing/decorator.py", line 78, in wrapper_use_tracer return func(*args, **kwargs) File "/Users/marilynmarquez/Desktop/webster/python/file_manager/venv/lib/python3.10/site-packages/azure/keyvault/secrets/_generated/v7_3/operations/_key_vault_client_operations.py", line 694, in get_secret pipeline_response = self._client._pipeline.run( # pylint: disable=protected-access File "/Users/marilynmarquez/Desktop/webster/python/file_manager/venv/lib/python3.10/site-packages/azure/core/pipeline/_base.py", line 211, in run return first_node.send(pipeline_request) # type: ignore File "/Users/marilynmarquez/Desktop/webster/python/file_manager/venv/lib/python3.10/site-packages/azure/core/pipeline/_base.py", line 71, in send response = self.next.send(request) File "/Users/marilynmarquez/Desktop/webster/python/file_manager/venv/lib/python3.10/site-packages/azure/core/pipeline/_base.py", line 71, in send response = self.next.send(request) File "/Users/marilynmarquez/Desktop/webster/python/file_manager/venv/lib/python3.10/site-packages/azure/core/pipeline/_base.py", line 71, in send response = self.next.send(request) [Previous line repeated 2 more times] File "/Users/marilynmarquez/Desktop/webster/python/file_manager/venv/lib/python3.10/site-packages/azure/core/pipeline/policies/_redirect.py", line 160, in send response = self.next.send(request) File "/Users/marilynmarquez/Desktop/webster/python/file_manager/venv/lib/python3.10/site-packages/azure/core/pipeline/policies/_retry.py", line 512, in send raise err File "/Users/marilynmarquez/Desktop/webster/python/file_manager/venv/lib/python3.10/site-packages/azure/core/pipeline/policies/_retry.py", line 484, in send response = self.next.send(request) File "/Users/marilynmarquez/Desktop/webster/python/file_manager/venv/lib/python3.10/site-packages/azure/core/pipeline/policies/_authentication.py", line 116, in send self.on_request(request) File "/Users/marilynmarquez/Desktop/webster/python/file_manager/venv/lib/python3.10/site-packages/azure/keyvault/secrets/_shared/challenge_auth_policy.py", line 71, in on_request _enforce_tls(request) File "/Users/marilynmarquez/Desktop/webster/python/file_manager/venv/lib/python3.10/site-packages/azure/keyvault/secrets/_shared/challenge_auth_policy.py", line 41, in _enforce_tls raise ServiceRequestError( azure.core.exceptions.ServiceRequestError: Bearer token authentication is not permitted for non-TLS protected (non-https) URLs. [06/Feb/2023 18:44:58] "POST /upload_file/ HTTP/1.1" 500 155467
This is my azure_controller.py:
from io import BytesIO
import uuid
from pathlib import Path
from azure.identity import DefaultAzureCredential
from azure.keyvault.secrets import SecretClient
from azure.storage.blob import BlobClient
from django.conf import settings
from . import models
ALLOWED_EXTENSIONS = ['.png', '.jpg']
def create_blob_client(file_name):
default_credential = DefaultAzureCredential()
secret_client=SecretClient(
vault_url = settings.AZURE_VAULT_ACCOUNT,
credential = default_credential
)
storage_credentials = secret_client.get_secret(name=settings.AZURE_STORAGE_KEY_NAME)
return BlobClient(
account_url = settings.AZURE_STORAGE_ACCOUNT,
container_name = settings.AZURE_APP_BLOB_NAME,
blob_name = file_name,
credential = storage_credentials.value,
)
def check_file_ext(path):
ext = Path(path).suffix
return ext in ALLOWED_EXTENSIONS
def download_blob(file):
blob_client=create_blob_client(file)
if not blob_client.exists():
return
blob_content = blob_client.download_blob()
return blob_content
def save_file_url_to_db(file_url):
new_file = models.File.objects.create(file_url = file_url)
new_file.save()
return new_file
def upload_file_to_blob(file):
if not check_file_ext(file.name):
return
file_prefix = uuid.uuid4().hex
ext=Path(file.name).suffix
file_name = f"{file_prefix}{ext}"
file_content = file.read()
file_io = BytesIO(file_content)
blob_client =create_blob_client(file_name = file_name)
blob_client.upload_blob(data=file_io)
file_object=save_file_url_to_db(blob_client.url)
return file_object
This is my settings.py:
Django settings for website project.
from pathlib import Path
import environ
BASE_DIR = Path(__file__).resolve().parent.parent
env = environ.Env()
environ.Env.read_env()
AZURE_STORAGE_ACCOUNT=env.str('AZURE_STORAGE_ACCOUNT')
AZURE_VAULT_ACCOUNT=env.str('AZURE_VAULT_ACCOUNT')
AZURE_STORAGE_KEY_NAME=env.str('AZURE_STORAGE_KEY_NAME')
AZURE_APP_BLOB_NAME=env.str('AZURE_APP_BLOB_NAME')
SECRET_KEY = env('MY_SECRET')
DEBUG = True
ALLOWED_HOSTS = []
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'files',
'django_extensions',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'website.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'website.wsgi.application'
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
# Password validation
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
STATIC_URL = 'static/'
# Default primary key field type
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
Some of the documentation I read advises using a Security Prncipal in Azure, which implies setting up Azure AD, but every time I try to go to Azure AD in my account, I get a message saying I'm not allowed (I'm the owner of the account). I honestly have no idea where to go from here or how to begin to fix this. Can someone help?
Any help will be greatly appreciated