From ab6018a0e58bec1125fee7ac1f319cca96e312fa Mon Sep 17 00:00:00 2001 From: David Ormsbee Date: Mon, 16 Sep 2013 02:00:30 -0400 Subject: [PATCH] Replace signature validation with access-key and add logging around Software Secure callbacks. --- lms/djangoapps/verify_student/models.py | 20 +++++++++++++++ lms/djangoapps/verify_student/views.py | 34 ++++++++++++++++++++----- 2 files changed, 48 insertions(+), 6 deletions(-) diff --git a/lms/djangoapps/verify_student/models.py b/lms/djangoapps/verify_student/models.py index 485214d88b..5905a9288f 100644 --- a/lms/djangoapps/verify_student/models.py +++ b/lms/djangoapps/verify_student/models.py @@ -356,6 +356,26 @@ class PhotoVerification(StatusModel): self.status = "denied" self.save() + @status_before_must_be("must_retry", "submitted", "approved", "denied") + def system_error(self, + error_msg, + error_code="", + reviewing_user=None, + reviewing_service=""): + """ + Mark that this attempt could not be completed because of a system error. + Status should be moved to `must_retry`. + """ + if self.status in ["approved", "denied"]: + return # If we were already approved or denied, just leave it. + + self.error_msg = error_msg + self.error_code = error_code + self.reviewing_user = reviewing_user + self.reviewing_service = reviewing_service + self.status = "must_retry" + self.save() + class SoftwareSecurePhotoVerification(PhotoVerification): """ diff --git a/lms/djangoapps/verify_student/views.py b/lms/djangoapps/verify_student/views.py index f315c2136f..e1ec69f724 100644 --- a/lms/djangoapps/verify_student/views.py +++ b/lms/djangoapps/verify_student/views.py @@ -180,21 +180,43 @@ def results_callback(request): settings.VERIFY_STUDENT["SOFTWARE_SECURE"]["API_SECRET_KEY"] ) - if not sig_valid: - return HttpResponseBadRequest(_("Signature is invalid")) + _, access_key_and_sig = headers["Authorization"].split(" ") + access_key = access_key_and_sig.split(":")[0] + + # This is what we should be doing... + #if not sig_valid: + # return HttpResponseBadRequest("Signature is invalid") + + # This is what we're doing until we can figure out why we disagree on sigs + if access_key != settings.VERIFY_STUDENT["SOFTWARE_SECURE"]["API_ACCESS_KEY"]: + return HttpResponseBadRequest("Access key invalid") receipt_id = body_dict.get("EdX-ID") result = body_dict.get("Result") reason = body_dict.get("Reason", "") error_code = body_dict.get("MessageType", "") - attempt = SoftwareSecurePhotoVerification.objects.get(receipt_id=receipt_id) - if result == "PASSED": + try: + attempt = SoftwareSecurePhotoVerification.objects.get(receipt_id=receipt_id) + except SoftwareSecurePhotoVerification.DoesNotExist: + log.error("Software Secure posted back for receipt_id {}, but not found".format(receipt_id)) + return HttpResponseBadRequest("edX ID {} not found".format(receipt_id)) + + if result == "PASS": + log.debug("Approving verification for {}".format(receipt_id)) attempt.approve() - elif result == "FAILED": - attempt.deny(reason, error_code=error_code) + elif result == "FAIL": + log.debug("Denying verification for {}".format(receipt_id)) + attempt.deny(json.dumps(reason), error_code=error_code) elif result == "SYSTEM FAIL": + log.debug("System failure for {} -- resetting to must_retry".format(receipt_id)) + attempt.system_error(json.dumps(reason), error_code=error_code) log.error("Software Secure callback attempt for %s failed: %s", receipt_id, reason) + else: + log.error("Software Secure returned unknown result {}".format(result)) + return HttpResponseBadRequest( + "Result {} not understood. Known results: PASS, FAIL, SYSTEM FAIL".format(result) + ) return HttpResponse("OK!")