def test_getDefault(mockDatabase): """ Can I set a default if a secret is unfound? What if the item and the default are missing? """ got = secret.get('NOTFOUND', ('a', 'b')) assert got == ('a', 'b') with raises(KeyError): secret.get('NOTFOUND')
def asToken(self): """ Create a JSON token for this user """ _, sec = secret.get('localapi') s = Serializer(sec, expires_in=secret.SECRET_EXPIRATION) return s.dumps({'email': self.email})
def test_get(mockDatabase): """ Can I get a manually-placed secret """ sp = secret.SecretPair('hello', 'abc', '!@#') sp.save() assert secret.get('hello') == ('abc', '!@#')
def __init__(self, templateOrFilename, **kwargs): if isinstance(templateOrFilename, Template): self.template = templateOrFilename elif isinstance(templateOrFilename, basestring): self.template = env.get_template(templateOrFilename) else: # pragma: no cover assert 0, "Got %r; needed a template or a template file" % templateOrFilename kwargs.setdefault('preload', {}).update({'apparentURL': CONFIG.apparentURL}) kwargs['preload']['auth0Public'] = secret.get('auth0')[0] self.renderContext = kwargs
def test_loadFromS3(public_hostname, expected, mockConfig, s3client): """ Do I get secrets from the right bucket, given a set of buckets and a certain hostname? """ with patch.object(secret, 'CONFIG', mockConfig): # purge the secrets our test fixture normally adds secret.SecretPair.objects.delete() mockConfig.public_hostname = public_hostname secret.loadFromS3() assert secret.get('auth0')[0] == expected
def __init__(self, templateOrFilename, **kwargs): if isinstance(templateOrFilename, Template): self.template = templateOrFilename elif isinstance(templateOrFilename, basestring): self.template = env.get_template(templateOrFilename) else: # pragma: no cover assert 0, "Got %r; needed a template or a template file" % templateOrFilename kwargs.setdefault('preload', {}).update( {'apparentURL': 'https://' + CONFIG.public_hostname, 'staticHash': CONFIG.staticHash, }) kwargs['preload']['auth0Public'] = secret.get('auth0')[0] self.renderContext = kwargs
def _fromAuthToken(cls, request): """ Check a JSON token to see if it's validly signed """ token = request.getHeader('x-token') if not token: return None _, sec = secret.get('localapi') s = Serializer(sec) try: data = s.loads(token) except (BadSignature, SignatureExpired): return None u = User.objects(email=data['email']).first() assert u, "Got a VALID token for %r, who does not exist??" % data['email'] return u
def postOptions(self): """ Connect to the noms database and make sure a config exists """ alias = self['alias'] assert alias in DBAlias connect(**DBHost[alias]) # compute the current static digest hash staticPath = '%s/static' % os.getcwd() CONFIG.staticHash = digest(staticPath) # get secrets from aws and store them in mongo reactor.callWhenRunning(secret.loadFromS3) # store an internally-shared secret if not secret.get('localapi', None): password = secret.randomPassword() secret.put('localapi', 'localapi', password) print "Stored new localapi password" # ensure that at least the special users exist user.USER() # watch for changes to static files (cache busting) watchCL = "watchmedo shell-command --patterns='{pat}' --recursive --command='{cmd}' {where}" watchCL = watchCL.format( pat=STATIC_FILE_PATTERNS, cmd='whisk digester -U %s/api/sethash/ %s' % (FIXME_LOCALAPI_URL, staticPath), where=staticPath, ) subprocess.Popen(shlex.split(watchCL), stdout=subprocess.PIPE) # run Sass sassCL = "node-sass -w static/scss/base.scss -o static/css" subprocess.Popen(shlex.split(sassCL), stdout=subprocess.PIPE) self.opt_class(MAIN_FUNC) tap.Options.postOptions(self)
def sso(self, request): """ From the browser's access attempt via auth0, acquire the user from auth0 NOTE: This request is always made by an auth0-hosted API client, not by the user's browser. """ # Auth0 begins the handshake by giving us a code for the transaction code = request.args.get('code')[0] # Ask auth0 to continue, passing back the one-use code, and proving # that we are an authorized auth0 SP by using the client_secret. auth0ID, auth0Secret = secret.get('auth0') tokenPayload = { 'client_id': auth0ID, 'client_secret': auth0Secret, 'redirect_uri': 'https://' + CONFIG.public_hostname + '/api/sso', 'code': code, 'grant_type': 'authorization_code' } tokenInfo = yield treq.post(TOKEN_URL, json.dumps(tokenPayload, sort_keys=True), headers={ 'Content-Type': ['application/json'] }).addCallback(treq.json_content) # Ask auth0 to look up the right user in the IdP, by querying with access_token userURL = '{base}{access_token}'.format(base=USER_URL, **tokenInfo) userInfo = yield treq.get(userURL).addCallback(treq.json_content) # Get or create a user account matching auth0's reply u = User.objects(email=userInfo['email']).first() if u is None: u = User.fromSSO(userInfo) u.save() # Also associate that user with the session # TODO - persistent sessions request.getSession().user = u # Tell auth0 to redirect. This makes auth0 tell the browser to redirect. defer.returnValue(request.redirect('/'))
def test_postOptions(mockConfig): """ Does postOptions create the configuration and return options? """ # remove the localapi secret that mockConfig creates, so we can be sure # postOptions will recreate it. secret.SecretPair.objects.get(name='localapi').delete() opts = cli.Run() pPopen = patch.object(subprocess, 'Popen', autospec=True) with pPopen as mPopen: opts.postOptions() calls = mPopen.call_args_list assert calls[0][0][0][0] == 'watchmedo' assert calls[1][0][0][:3] == ['node-sass', '-w', 'static/scss/base.scss'] # did postOptions recreate the localapi secret? assert secret.get('localapi')[0] == 'localapi'
def sso(self, request): """ From the browser's access attempt via auth0, acquire the user from auth0 NOTE: This request is always made by an auth0-hosted API client, not by the user's browser. """ # Auth0 begins the handshake by giving us a code for the transaction code = request.args.get('code')[0] # Ask auth0 to continue, passing back the one-use code, and proving # that we are an authorized auth0 SP by using the client_secret. auth0ID, auth0Secret = secret.get('auth0') tokenPayload = { 'client_id': auth0ID, 'client_secret': auth0Secret, 'redirect_uri': CONFIG.apparentURL + '/api/sso', 'code': code, 'grant_type': 'authorization_code' } tokenInfo = yield treq.post(TOKEN_URL, json.dumps(tokenPayload), headers={'Content-Type': ['application/json']} ).addCallback(treq.json_content) # Ask auth0 to look up the right user in the IdP, by querying with access_token userURL = '{base}{access_token}'.format(base=USER_URL, **tokenInfo) userInfo = yield treq.get(userURL).addCallback(treq.json_content) # Get or create a user account matching auth0's reply u = user.User.objects(email=userInfo['email']).first() if u is None: u = user.User.fromSSO(userInfo) # Also associate that user with the session # TODO - persistent sessions request.getSession().user = u # Tell auth0 to redirect. This makes auth0 tell the browser to redirect. defer.returnValue(request.redirect('/'))
def test_render(self): """ Do I produce a string using my template that uses all the variables I provided? """ pubkey, seckey = secret.get('auth0') self.assertEqual((pubkey, seckey), ('abc123', 'ABC!@#')) self.tplString = cleandoc(""" hi there {{ preload.apparentURL }} {{ preload.auth0Public }} {{ banana }} """) self.tplTemplate = Template(self.tplString) hrTemplate = rendering.HumanReadable(self.tplTemplate, banana='yellow and delicious') expected = cleandoc(""" hi there https://app.nomsbook.com abc123 yellow and delicious """) self.assertEqual(hrTemplate.render(None), expected) expected = cleandoc(""" hi there https://app.nomsbook.com abc123 brown and gross """) with patch.object(rendering.env, 'get_template', return_value=self.tplTemplate): hrString = rendering.HumanReadable('tpl_from_loader.txt', banana='brown and gross') self.assertEqual(hrString.render(None), expected)