edx-certificates
This is the code we use the generate certificates at edX.
Generate edX certificates
This script will continuously monitor an xqueue queue for the purpose of generating a course certificate for a user.
Generating sample certificates
-
Create a new python virtualenv
mkvirtualenv certificates
-
Clone the certificate repo
git clone https://github.com/edx/edx-certificates.git
-
Clone the internal certificate repo for templates and private data (optional)
git clone git@github.com:edx/edx-certificates-internal
-
Install the python requirements into the virtualenv
pip install -r edx-certificates/requirements.txt
-
In order to generate sample certificates that are uploaded to S3 you will need access to the verify-test bucket, create a
~/.boto
file in your home directory[Credentials] aws_access_key_id = ***** aws_secret_access_key = ****
-
Or for edX use the
boto.example
in the${CERT_PRIVATE_DIR}
repo:cp edx-certificates-internal/boto.example ~/.boto
-
-
Set an environment variable to point to the internal repo for certificate templates
export CERT_PRIVATE_DIR=/path/to/edx-certificates-internal
-
In the edx-certificates directory generate a sample certificate:
cd edx-certificates python create_pdfs.py \ --course-id 'course-v1:edX+DemoX+Demo_Course' \ --name 'Guido' \ --no-upload \ ;
-
course-v1:edX+DemoX+Demo_Course
should be a valid course id found in${CERT_PRIVATE_DIR}
-
View all options with:
python create_pdfs.py --help
-
Behavioral Overview
The certificate_agent.py
script will continuously monitor a queue for
certificate generation, it does the following:
- Connect to the xqueue server
- Poll for a single certificate request
- If it finds one, it:
- Processes the request
- Post a results json back to the xqueue server
A global exception handler will catch any error during the certificate generation process and post a result back to the LMS via the xqueue server indicating there was a problem.
optional arguments:
-h, --help show this help message and exit
--aws-id AWS_ID AWS ID for write access to the S3 bucket
--aws-key AWS_KEY AWS KEY for write access to the S3 bucket
Generation overview
TODO
Internationalization and Localization
There is none. Every renderer should have complete Unicode support throughout,
but every certificate template render method is built around English-grammar
sentence interpolation. Consequently, if the target language of the certificate
has very different sentence structure, you may find the easiest way to add
support for your language is to fork an existing renderer. We suggest
_generate_v3_dynamic_certificate
.
If you think that your new renderer would be useful to the international Open edX community, please issue a pull request! We'd love to have 3_dynamic renderers for new languages.
Some members of the Open edX community maintain multiple private modifications to the open source edX projects, and use a branching scheme similar to the one described by Giulio Gratta in this edX Eng blog post. If you have many changes to the code base, a system like this might help you stay organized. If, on the other hand you are only forking one template renderer, this may be too complex. Please do whatever works best for your site.
Logging
Logging is setup similar to Django logging, logsettings.py will generate a configuration dict for logging where in a production environment all log messages are sent through rsyslog
Tests
To run the test suite:
-
Configure your credential information in
settings.py
. You will need to specify:CERT_KEY_ID = # The id for the key which will be used by gpg to sign certificates CERT_AWS_ID = # Amazon Web Services ID CERT_AWS_KEY = # Amazon Web Services Key CERT_BUCKET = # Amazon Web Services S3 bucket name
It is also acceptable to leave the AWS KEY and ID values as none and instead use .boto file or run this code from a server that has an IAM role that gives it write access to the bucket in the configuration.
-
To run all of the tests from the
certificates
directory, run:nosetests
These are more integration tests than unit tests, and will be exercising your certificate configuration, your file pathing, and your S3 credentials. Some tests may fail, but the code may still be working properly; you'll have to investigate to discover what the failed test is diagnostic of. To run just the tests for local on-disk publishing run:
nosetests tests.gen_cert_test:test_cert_gen
Troubleshooting:
-
If tests fail with errors, try running:
pip install -r requirements.txt
to install necessary requirements.
-
If your verification pages are wrong or gnupg starts throwing errors, you may not have
gpg
installed. See gnupg for help installing. -
If you run
create_pdf.py
and get unicode errors, you may need to set the LC_ALL environment variable. To set it permanently, like from your ~/.bashrc, try:export LC_ALL=en_US.UTF-8
But if you only want to set it for one test run, you could say:
LC_ALL=en_US.UTF-8 python ./create_pdf.py
-
If you are running on a Linux virtual machine being hosted by MacOS, and your git checkout is being NFS mounted, you may have library import errors because of Mac case-folding semantic preservation by Python's pathlib. Try doing a git checkout inside the vm that isn't exported from MacOS.
Roadmap/TODO/Future Features
-
Paralellism - Certification should be embarassingly parallel, except we deal with xqueue, which lacks atomic pop(). If we ever refactor queue.py to use raw celery queues or similar, we should also actualize parallel certification.
-
Dynamic scaling and placement of signatures from scanned bitmaps, making cert rendering completely dynamic and freeing us from the tyranny of template preparation. (Freeing us from the tyranny of configuration preparation would come in a future PR.)
-
Kill XQueue - nobody really likes xqueue. Several ops people have expressed a desire to see it replaced by smarter intermediate layers that use celery task queues or similar. This repo should be sufficiently modular that only queue.py should need to be changed to work this way.