Example #1
0
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')
Example #2
0
 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})
Example #3
0
def test_get(mockDatabase):
    """
    Can I get a manually-placed secret
    """
    sp = secret.SecretPair('hello', 'abc', '!@#')
    sp.save()
    assert secret.get('hello') == ('abc', '!@#')
Example #4
0
 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
Example #5
0
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
Example #6
0
 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
Example #7
0
    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
Example #8
0
    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)
Example #9
0
    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('/'))
Example #10
0
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'
Example #11
0
    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('/'))
Example #12
0
    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)