Is SOFTWARE_SECURE part of the config.yml?

Hi there,

I ran tutor local quickstart and created an ecommerce course with the verification ID checked
When I try to upload the photos I get an error, so I’m wondering if I’m missing something in the config.yml

This is the error I’m getting:

lms_1               | 2020-04-08 20:44:44,050 ERROR 38 [root] signals.py:21 - Uncaught exception from None
lms_1               | Traceback (most recent call last):
lms_1               |   File "/openedx/venv/local/lib/python2.7/site-packages/django/core/handlers/exception.py", line 41, in inner
lms_1               |     response = get_response(request)
lms_1               |   File "/openedx/venv/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 249, in _legacy_get_response
lms_1               |     response = self._get_response(request)
lms_1               |   File "/openedx/venv/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 187, in _get_response
lms_1               |     response = self.process_exception_by_middleware(e, request)
lms_1               |   File "/openedx/venv/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 185, in _get_response
lms_1               |     response = wrapped_callback(request, *callback_args, **callback_kwargs)
lms_1               |   File "/openedx/venv/local/lib/python2.7/site-packages/django/views/generic/base.py", line 68, in view
lms_1               |     return self.dispatch(request, *args, **kwargs)
lms_1               |   File "/openedx/venv/local/lib/python2.7/site-packages/django/utils/decorators.py", line 67, in _wrapper
lms_1               |     return bound_func(*args, **kwargs)
lms_1               |   File "/openedx/venv/local/lib/python2.7/site-packages/django/utils/decorators.py", line 63, in bound_func
lms_1               |     return func.__get__(self, type(self))(*args2, **kwargs2)
lms_1               |   File "/openedx/edx-platform/lms/djangoapps/verify_student/views.py", line 863, in dispatch
lms_1               |     return super(SubmitPhotosView, self).dispatch(request, *args, **kwargs)
lms_1               |   File "/openedx/venv/local/lib/python2.7/site-packages/django/views/generic/base.py", line 88, in dispatch
lms_1               |     return handler(request, *args, **kwargs)
lms_1               |   File "/openedx/venv/local/lib/python2.7/site-packages/django/utils/decorators.py", line 67, in _wrapper
lms_1               |     return bound_func(*args, **kwargs)
lms_1               |   File "/openedx/venv/local/lib/python2.7/site-packages/django/contrib/auth/decorators.py", line 23, in _wrapped_view
lms_1               |     return view_func(request, *args, **kwargs)
lms_1               |   File "/openedx/venv/local/lib/python2.7/site-packages/django/utils/decorators.py", line 63, in bound_func
lms_1               |     return func.__get__(self, type(self))(*args2, **kwargs2)
lms_1               |   File "/openedx/venv/local/lib/python2.7/site-packages/django/utils/decorators.py", line 67, in _wrapper
lms_1               |     return bound_func(*args, **kwargs)
lms_1               |   File "/openedx/venv/local/lib/python2.7/site-packages/django/utils/decorators.py", line 185, in inner
lms_1               |     return func(*args, **kwargs)
lms_1               |   File "/openedx/venv/local/lib/python2.7/site-packages/django/utils/decorators.py", line 63, in bound_func
lms_1               |     return func.__get__(self, type(self))(*args2, **kwargs2)
lms_1               |   File "/openedx/edx-platform/lms/djangoapps/verify_student/views.py", line 916, in post
lms_1               |     self._submit_attempt(request.user, face_image, photo_id_image, initial_verification)
lms_1               |   File "/openedx/edx-platform/lms/djangoapps/verify_student/views.py", line 1045, in _submit_attempt
lms_1               |     attempt.upload_face_image(face_image)
lms_1               |   File "/openedx/edx-platform/lms/djangoapps/verify_student/models.py", line 84, in with_status_check
lms_1               |     return func(obj, *args, **kwargs)
lms_1               |   File "/openedx/edx-platform/lms/djangoapps/verify_student/models.py", line 585, in upload_face_image
lms_1               |     aes_key_str = settings.VERIFY_STUDENT["SOFTWARE_SECURE"]["FACE_IMAGE_AES_KEY"]
lms_1               | KeyError: 'SOFTWARE_SECURE'
lms_1               | 2020-04-08 20:44:44,051 ERROR 38 [django.request] exception.py:135 - Internal Server Error: /verify_student/submit-photos/
lms_1               | Traceback (most recent call last):
lms_1               |   File "/openedx/venv/local/lib/python2.7/site-packages/django/core/handlers/exception.py", line 41, in inner
lms_1               |     response = get_response(request)
lms_1               |   File "/openedx/venv/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 249, in _legacy_get_response
lms_1               |     response = self._get_response(request)
lms_1               |   File "/openedx/venv/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 187, in _get_response
lms_1               |     response = self.process_exception_by_middleware(e, request)
lms_1               |   File "/openedx/venv/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 185, in _get_response
lms_1               |     response = wrapped_callback(request, *callback_args, **callback_kwargs)
lms_1               |   File "/openedx/venv/local/lib/python2.7/site-packages/django/views/generic/base.py", line 68, in view
lms_1               |     return self.dispatch(request, *args, **kwargs)
lms_1               |   File "/openedx/venv/local/lib/python2.7/site-packages/django/utils/decorators.py", line 67, in _wrapper
lms_1               |     return bound_func(*args, **kwargs)
lms_1               |   File "/openedx/venv/local/lib/python2.7/site-packages/django/utils/decorators.py", line 63, in bound_func
lms_1               |     return func.__get__(self, type(self))(*args2, **kwargs2)
lms_1               |   File "/openedx/edx-platform/lms/djangoapps/verify_student/views.py", line 863, in dispatch
lms_1               |     return super(SubmitPhotosView, self).dispatch(request, *args, **kwargs)
lms_1               |   File "/openedx/venv/local/lib/python2.7/site-packages/django/views/generic/base.py", line 88, in dispatch
lms_1               |     return handler(request, *args, **kwargs)
lms_1               |   File "/openedx/venv/local/lib/python2.7/site-packages/django/utils/decorators.py", line 67, in _wrapper
lms_1               |     return bound_func(*args, **kwargs)
lms_1               |   File "/openedx/venv/local/lib/python2.7/site-packages/django/contrib/auth/decorators.py", line 23, in _wrapped_view
lms_1               |     return view_func(request, *args, **kwargs)
lms_1               |   File "/openedx/venv/local/lib/python2.7/site-packages/django/utils/decorators.py", line 63, in bound_func
lms_1               |     return func.__get__(self, type(self))(*args2, **kwargs2)
lms_1               |   File "/openedx/venv/local/lib/python2.7/site-packages/django/utils/decorators.py", line 67, in _wrapper
lms_1               |     return bound_func(*args, **kwargs)
lms_1               |   File "/openedx/venv/local/lib/python2.7/site-packages/django/utils/decorators.py", line 185, in inner
lms_1               |     return func(*args, **kwargs)
lms_1               |   File "/openedx/venv/local/lib/python2.7/site-packages/django/utils/decorators.py", line 63, in bound_func
lms_1               |     return func.__get__(self, type(self))(*args2, **kwargs2)
lms_1               |   File "/openedx/edx-platform/lms/djangoapps/verify_student/views.py", line 916, in post
lms_1               |     self._submit_attempt(request.user, face_image, photo_id_image, initial_verification)
lms_1               |   File "/openedx/edx-platform/lms/djangoapps/verify_student/views.py", line 1045, in _submit_attempt
lms_1               |     attempt.upload_face_image(face_image)
lms_1               |   File "/openedx/edx-platform/lms/djangoapps/verify_student/models.py", line 84, in with_status_check
lms_1               |     return func(obj, *args, **kwargs)
lms_1               |   File "/openedx/edx-platform/lms/djangoapps/verify_student/models.py", line 585, in upload_face_image
lms_1               |     aes_key_str = settings.VERIFY_STUDENT["SOFTWARE_SECURE"]["FACE_IMAGE_AES_KEY"]
lms_1               | KeyError: 'SOFTWARE_SECURE'

Hmmmm :thinking: It looks like you need to customize the VERIFY_STUDENT setting from the LMS. I see that by default, its value is:

VERIFY_STUDENT = {
    "DAYS_GOOD_FOR": 365, 
    "EXPIRING_SOON_WINDOW": 28,
}

Apparently, you need to add the SOFTWARE_SECURE key to this dict. You would have to dig into the edx-platform source code to figure what would be the proper value. I honestly have no idea and would need to further investigate to understand that.

Is this verification performed outside of EDX?
And yes I added it to the env variables for LMS

hi @bryancr89 @regis!

I’m trying do activate these feature . The part of set SOFTWARE_SECURE key i did with a tutor plugin

The image is successfully sent and encrypted. However, Edx tries to send this image to an S3 bucket. I activated the tutor-minio plugin to have this feature. But now Edx accuses him of not having permission to send the photo to the bucket

lms_1               | 2020-10-01 19:31:42,011 ERROR 286 [django.request] [user 4] log.py:228 - Internal Server Error: /verify_student/submit-photos/
lms_1               | Traceback (most recent call last):
lms_1               |   File "/openedx/venv/lib/python3.5/site-packages/django/core/handlers/exception.py", line 34, in inner
lms_1               |     response = get_response(request)
lms_1               |   File "/openedx/venv/lib/python3.5/site-packages/django/core/handlers/base.py", line 115, in _get_response
lms_1               |     response = self.process_exception_by_middleware(e, request)
lms_1               |   File "/openedx/venv/lib/python3.5/site-packages/django/core/handlers/base.py", line 113, in _get_response
lms_1               |     response = wrapped_callback(request, *callback_args, **callback_kwargs)
lms_1               |   File "/openedx/venv/lib/python3.5/site-packages/django/views/generic/base.py", line 71, in view
lms_1               |     return self.dispatch(request, *args, **kwargs)
lms_1               |   File "/openedx/venv/lib/python3.5/site-packages/django/utils/decorators.py", line 45, in _wrapper
lms_1               |     return bound_method(*args, **kwargs)
lms_1               |   File "/openedx/edx-platform/lms/djangoapps/verify_student/views.py", line 865, in dispatch
lms_1               |     return super(SubmitPhotosView, self).dispatch(request, *args, **kwargs)
lms_1               |   File "/openedx/venv/lib/python3.5/site-packages/django/views/generic/base.py", line 97, in dispatch
lms_1               |     return handler(request, *args, **kwargs)
lms_1               |   File "/openedx/venv/lib/python3.5/site-packages/django/utils/decorators.py", line 45, in _wrapper
lms_1               |     return bound_method(*args, **kwargs)
lms_1               |   File "/openedx/venv/lib/python3.5/site-packages/django/contrib/auth/decorators.py", line 21, in _wrapped_view
lms_1               |     return view_func(request, *args, **kwargs)
lms_1               |   File "/openedx/venv/lib/python3.5/site-packages/django/utils/decorators.py", line 45, in _wrapper
lms_1               |     return bound_method(*args, **kwargs)
lms_1               |   File "/opt/pyenv/versions/3.5.9/lib/python3.5/contextlib.py", line 30, in inner
lms_1               |     return func(*args, **kwds)
lms_1               |   File "/openedx/edx-platform/lms/djangoapps/verify_student/views.py", line 918, in post
lms_1               |     self._submit_attempt(request.user, face_image, photo_id_image, initial_verification)
lms_1               |   File "/openedx/edx-platform/lms/djangoapps/verify_student/views.py", line 1047, in _submit_attempt
lms_1               |     attempt.upload_face_image(face_image)
lms_1               |   File "/openedx/edx-platform/lms/djangoapps/verify_student/models.py", line 87, in with_status_check
lms_1               |     return func(obj, *args, **kwargs)
lms_1               |   File "/openedx/edx-platform/lms/djangoapps/verify_student/models.py", line 699, in upload_face_image
lms_1               |     self._storage.save(path, buff)
lms_1               |   File "/openedx/venv/lib/python3.5/site-packages/django/core/files/storage.py", line 52, in save
lms_1               |     return self._save(name, content)
lms_1               |   File "/openedx/venv/lib/python3.5/site-packages/storages/backends/s3boto.py", line 425, in _save
lms_1               |     key = self.bucket.get_key(encoded_name)
lms_1               |   File "/openedx/venv/lib/python3.5/site-packages/boto/s3/bucket.py", line 193, in get_key
lms_1               |     key, resp = self._get_key_internal(key_name, headers, query_args_l)
lms_1               |   File "/openedx/venv/lib/python3.5/site-packages/boto/s3/bucket.py", line 231, in _get_key_internal
lms_1               |     response.status, response.reason, '')
lms_1               | boto.exception.S3ResponseError: S3ResponseError: 403 Forbidden

I looked at the source code of the function that implements this and found this line

image

@regis the S3_BUCKET config would it have to be set for him to try to write in the tutor-minio ?

@ejklock According to this piece of code, I think it’s better if you actually don’t add any value to the settings.VERIFY_STUDENT["SOFTWARE_SECURE"] configuration. That way, all settings will (should?) be loaded from settings.AWS_* values.

Note however that this piece of code relies on the legacy S3BotoStorage backend, not on S3Boto3Storage. This might require different configuration: https://django-storages.readthedocs.io/en/1.8/backends/amazon-S3.html

I encourage you to debug the get_storage function to check what are the attributes of the storage backend, as well as the url where it tries to save the data.