Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove client secrets from core code #981

Merged
merged 10 commits into from
Aug 4, 2017
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,7 @@ venv/
.vscode/
webpack-stats.json
workfile.html
semesterly/secrets.py
semesterly/secret_key.py
backup.sh
client_secret.json
50 changes: 24 additions & 26 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,43 +3,41 @@ sudo: required
dist: trusty
language: node_js
node_js:
- "7.1.0"
env:
- 7.1.0
env:
matrix:
- NODE_ENV=production

branches:
only:
- master
- staging

- master
- staging
cache:
apt: true
directories:
- node_modules
- $HOME/.npm
- $HOME/.cache/pip

- node_modules
- $HOME/.npm
- $HOME/.cache/pip
install:
- npm -g install webpack
- npm -g install chromedriver
- npm -g install jest babel-jest
- npm install
- pip install --user -r requirements.txt
- npm -g install webpack
- npm -g install chromedriver
- npm -g install jest babel-jest
- npm install
- pip install --user -r requirements.txt
addons:
apt:
sources:
- google-chrome
- google-chrome
packages:
- google-chrome-stable
- google-chrome-stable
hosts:
- jhu.sem.ly
- jhu.sem.ly
before_script:
- "export DISPLAY=:99.0"
- "sh -e /etc/init.d/xvfb start"
- sleep 3 # give xvfb some time to start
- export DISPLAY=:99.0
- sh -e /etc/init.d/xvfb start
- sleep 3
script:
- npm run build
- npm run lint
- npm run test
- python manage.py test
- make html -C docs
- npm run build
- npm run lint
- npm run test
- python manage.py test
- make html -C docs
5 changes: 3 additions & 2 deletions authpipe/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@
from hashids import Hashids

from student.models import Student
from semesterly.settings import get_secret

hashids = Hashids(salt="x98as7dhg&h*askdj^has!kj?xz<!9")
hashids = Hashids(salt=get_secret('HASHING_SALT'))


def check_student_token(student, token):
Expand Down Expand Up @@ -86,7 +87,7 @@ def create_student(strategy, details, response, user, *args, **kwargs):
response = requests.get(
'https://www.googleapis.com/plus/v1/people/me'.format(
social_user.uid,
settings.GOOGLE_API_KEY),
get_secret('GOOGLE_API_KEY')),
params={'access_token': access_token}
)
new_student.img_url = response.json()['image'].get('url', '')
Expand Down
46 changes: 46 additions & 0 deletions docs/advancedconfig.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
.. _advancedconfig:

.. note:: **This step is not neccessary for most developers.** Only continue reading this section if you need to override the test secrets (API keys/credentials) provided by Semester.ly (which are for testing only).

Advanced Configuration
=======================

Semester.ly makes use of several secrets which allow it to interact securely with third party software providers. These providers include Facebook (for oauth and social graph), Google (oauth), and university APIs.

In order for Semester.ly to run out of the box, we have included credentials to test Google and Facebook applications for development purposes. We override these keys for production use thereby keeping our client secrets... well, secrets! These provided credentials can be found in ``semesterly/dev_credentials.py``::

SECRETS = {
#Credentials for a test application for Semester.ly (+ Google/Facebook)
'SECRET_KEY': ...,
'HASHING_SALT': ...,
'GOOGLE_API_KEY': ...,
'SOCIAL_AUTH_GOOGLE_OAUTH2_KEY': ...,
'SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET': ...,
'SOCIAL_AUTH_FACEBOOK_KEY': ...,
'SOCIAL_AUTH_FACEBOOK_SECRET': ...,
'FB_TEST_EMAIL': ...,
'FB_TEST_PASS': ...,

#Not essential for testing, but can be filled in for advanced usage
...
}

Overriding/Setting Secrets
--------------------------

However, if you wish to override these credentials or add login credentials for a school which requires a client secret, you may add your key/value pair to ``semesterly/sensitive.py``. This file is gitignored and will be kept private so you can safely store the private information you wish within this file. It should have a format indentical to SECRETS above and in ``semesterly/dev_credentials.py``.

Using Secrets
-------------

In order to properly access a secret from anywhere within the code, simply import the ``get_secret`` function and use it to access the secret by key::

from semesterly.settings import get_secret
hashids = Hashids(salt=get_secret('HASHING_SALT'))

This will check the following locations for the secret (in order, using the first value it finds), throwing an error if it does not find the key at all:

1. Check OS environment variables
2. Check ``semesterly/sensitive.py``
3. Default to ``semesterly/dev_credentials.py``
4. Error
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ Students know best
setup
environment
parsing
advancedconfig
howitworks
learning
contributing
Expand Down
14 changes: 7 additions & 7 deletions docs/testing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,34 +7,34 @@ Running Tests
Frontend
~~~~~~~~

Run all tests:
Run all tests::

npm test

Run single test:
Run single test::

npm test -- static/js/redux/__tests__/schema.test.js

Backend
~~~~~~~

Run all tests:
Run all tests::

python manage.py test

Run all tests for a single app:
Run all tests for a single app::

python manage.py test timetable

Run single test suite
Run single test suite::

python manage.py test timetable.tests.UrlsTest

Run single test case
Run single test case::

python manage.py test timetable.tests.UrlTest.test_urls_call_correct_views

Run tests without resetting db:
Run tests without resetting db::

python manage.py test -k

Expand Down
4 changes: 2 additions & 2 deletions exams/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@
from helpers.mixins import FeatureFlowView, CsrfExemptMixin
from exams.models import FinalExamShare
from student.utils import get_student
from semesterly.settings import get_secret


hashids = Hashids(salt="x98as7dhg&h*askdj^has!kj?xz<!9")
hashids = Hashids(salt=get_secret('HASHING_SALT'))


# TODO: use new request shape
Expand Down
7 changes: 4 additions & 3 deletions parsing/schools/gw/courses.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from parsing.library.internal_exceptions import CourseParseError
from parsing.library.utils import safe_cast
from parsing.library.extractor import filter_years_and_terms
from semesterly.settings import get_secret


class Parser(CourseParser):
Expand All @@ -32,9 +33,9 @@ class Parser(CourseParser):

URL = 'https://banweb.gwu.edu/PRODCartridge'
CREDENTIALS = {
'USERNAME': 'G45956511',
'PASSWORD': '052698',
'SECURITY_QUESTION_ANSWER': 'Katie'
'USERNAME': get_secret('GW_USER'),
'PASSWORD': get_secret('GW_PASS'),
'SECURITY_QUESTION_ANSWER': get_secret('GW_SECURITY_ANSWER')
}
YEARS_AND_TERMS = {
2017: {
Expand Down
3 changes: 2 additions & 1 deletion parsing/schools/jhu/courses.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

from parsing.library.base_parser import BaseParser
from parsing.library.extractor import time_12to24, titlize
from semesterly.settings import get_secret


class Parser(BaseParser):
Expand All @@ -33,7 +34,7 @@ class Parser(BaseParser):
"""

API_URL = 'https://isis.jhu.edu/api/classes/'
KEY = 'evZgLDW987P3GofN2FLIhmvQpHASoIxO'
KEY = get_secret('JHU_API_KEY')
DAY_TO_LETTER_MAP = {
'm': 'M',
't': 'T',
Expand Down
5 changes: 3 additions & 2 deletions parsing/schools/queens/courses.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from selenium import webdriver

from parsing.common.peoplesoft.courses import QPeoplesoftParser
from semesterly.settings import get_secret


class Parser(QPeoplesoftParser):
Expand All @@ -26,8 +27,8 @@ class Parser(QPeoplesoftParser):
BASE_URL = 'https://saself.ps.queensu.ca/psc/saself/EMPLOYEE/HRMS/c/'\
'SA_LEARNER_SERVICES.CLASS_SEARCH.GBL'
CREDENTIALS = {
'USERNAME': '1dc4',
'PASSWORD': 'CREOmule1'
'USERNAME': get_secret('QUEENS_USER'),
'PASSWORD': get_secret('QUEENS_PASS')
}

def __init__(self, **kwargs):
Expand Down
6 changes: 4 additions & 2 deletions parsing/schools/queens/qcumber_scraper/queens_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.

USER = "1dc4"
PASS = "CREOmule1"
from semesterly.settings import get_secret

USER = get_secret('QUEENS_USER')
PASS = get_secret('QUEENS_PASS')
OUTPUT_DIR = "./data-dump"
PROFILE = None
MAX_RETRIES = 10
Expand Down
9 changes: 5 additions & 4 deletions parsing/schools/vandy/courses.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,14 @@
import re
import sys

from parsing.library.base_parser import BaseParsr
from parsing.library.base_parser import BaseParser
from parsing.library.internal_exceptions import CourseParseError
from parsing.library.utils import safe_cast
from parsing.library.exceptions import ParseError
from semesterly.settings import get_secret


class Parser(BaseParsr):
class Parser(BaseParser):
"""Vanderbilt course parser.

Attributes:
Expand All @@ -36,8 +37,8 @@ class Parser(BaseParsr):

API_URL = 'https://webapp.mis.vanderbilt.edu/more'
CREDENTIALS = {
'USERNAME': 'khanaf',
'PASSWORD': 'Gainz%2123'
'USERNAME': get_secret('VANDY_USER'),
'PASSWORD': get_secret('VANDY_PASS')
}

def __init__(self, **kwargs):
Expand Down
9 changes: 5 additions & 4 deletions scripts/mailer.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@
from django.template.loader import render_to_string
from student.models import *
from student.views import create_unsubscribe_link
from semesterly.settings import get_secret

class Mailer():
def __init__(self):
# Create server object with SSL option
self.server = smtplib.SMTP_SSL('email-smtp.us-east-1.amazonaws.com')
self.server.login('AKIAJWXCNDO3CMYAIC6A', 'AonOaLbp9FjBkyhP9ihHBge92CEqgMPMbgrUweYxT9Ar')
self.server = smtplib.SMTP_SSL(get_secret('MAILER_SERVER'))
self.server.login(get_secret('MAILER_USER'), get_secret('MAILER_PASSWORD'))

# Define to
self.sender = 'textbooks@semester.ly'
Expand Down Expand Up @@ -71,5 +72,5 @@ def send_mail(self, student, subject, template, params={}):
print("skipped " + str(student.user.email))
traceback.print_exc()

self.server = smtplib.SMTP_SSL('email-smtp.us-east-1.amazonaws.com')
self.server.login('AKIAJWXCNDO3CMYAIC6A', 'AonOaLbp9FjBkyhP9ihHBge92CEqgMPMbgrUweYxT9Ar')
self.server = smtplib.SMTP_SSL(MAILER_SERVER)
self.server.login(MAILER_USER, MAILER_PASSWORD)
50 changes: 50 additions & 0 deletions semesterly/dev_credentials.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Copyright (C) 2017 Semester.ly Technologies, LLC
#
# Semester.ly is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Semester.ly is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.



#DANGER: Should not be used in production
#THE CREDENTIALS PROVIDED HERE ARE FOR TEST USE ONLY
#THEY ARE NOT USED ON SEMESTER.LY NOR SHOULD THEY BE
# USED IN ANY OTHER PRODUCTION ENVIRONMENT.


SECRETS = {
#Credentials for a test application for Semester.ly (+ Google/Facebook)
'SECRET_KEY': 'ca&+%f9xv*$56z@8278xw*ci7_db9w=^dhkqmwu3as&30u%w+$',
'HASHING_SALT': "t9wg0p7x1$x5on89f*yk=tk*+$!g6g",
'GOOGLE_API_KEY': 'AIzaSyBdJi-FTASHxCyH_-3caR-K_IkRUW8dGSQ',
'SOCIAL_AUTH_GOOGLE_OAUTH2_KEY': '993759614355-6sti4ks7kaikb9806ob49p9qvshhpgj7.apps.googleusercontent.com',
'SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET': 'YMy_-3GD7bF8FlASDlLg0dDm',
'SOCIAL_AUTH_FACEBOOK_KEY': '2008148216081463',
'SOCIAL_AUTH_FACEBOOK_SECRET': '75f855457ff18db012e57ccaaf3470eb',
'FB_TEST_EMAIL': 'open_ejvbpxf_user@tfbnw.net',
'FB_TEST_PASS': 'asdfasdfdsfdsfadfdsflsdflglfg',

#Not essential for testing, but can be filled in for advanced usage
'QUEENS_USER': None,
'QUEENS_PASS': None,
'GW_PASS': None,
'GW_SECURITY_ANSWER': None,
'JHU_API_KEY': None,
'VANDY_USER': None,
'VANDY_PASS': None,

#Not essential for testing, but can be filled in for advanced mailing usage
'MAILER_SERVER': None,
'MAILER_USER': None,
'MAILER_PASSWORD': None,
'MAILER_SENDER': None,
'EMAIL_HOST_USER': None,
'EMAIL_HOST_PASSWORD': None,
'EMAIL_PASSWORD': None
}
15 changes: 0 additions & 15 deletions semesterly/middleware/sensitive.py

This file was deleted.

Loading