def agent_visit(url, request):
            if request.method != "POST":
                raise Exception('unexpected method')
            log.info('agent_visit url {}'.format(url))
            body = json.loads(request.body.decode('utf-8'))
            if body['username'] != 'test-user':
                raise Exception('unexpected username in body {!r}'.format(request.body))
            public_key = bakery.PublicKey.deserialize(body['public_key'])
            ms = httpbakery.extract_macaroons(request.headers)
            if len(ms) == 0:
                b = bakery.Bakery(key=discharge_key)
                m = b.oven.macaroon(
                    version=bakery.LATEST_VERSION,
                    expiry=datetime.utcnow() + timedelta(days=1),
                    caveats=[bakery.local_third_party_caveat(
                        public_key,
                        version=httpbakery.request_version(request.headers))],
                    ops=[bakery.Op(entity='agent', action='login')])
                content, headers = httpbakery.discharge_required_response(
                    m, '/',
                    'test',
                    'message')
                resp = response(status_code=401,
                                content=content,
                                headers=headers)
                return request.hooks['response'][0](resp)

            return {
                'status_code': 200,
                'content': {
                    'agent_login': True
                }
            }
 def server_get(url, request):
     ctx = checkers.AuthContext()
     test_ops = [bakery.Op(entity='test-op', action='read')]
     auth_checker = server_bakery.checker.auth(
         httpbakery.extract_macaroons(request.headers))
     try:
         auth_checker.allow(ctx, test_ops)
         resp = response(status_code=200,
                         content='done')
     except bakery.PermissionDenied:
         caveats = [
             checkers.Caveat(location='http://0.3.2.1',
                             condition='is-ok')
         ]
         m = server_bakery.oven.macaroon(
             version=bakery.LATEST_VERSION,
             expiry=datetime.utcnow() + timedelta(days=1),
             caveats=caveats, ops=test_ops)
         content, headers = httpbakery.discharge_required_response(
             m, '/',
             'test',
             'message')
         resp = response(status_code=401,
                         content=content,
                         headers=headers)
     return request.hooks['response'][0](resp)
Пример #3
0
        def visit(url, request):
            if request.headers.get('Accept') == 'application/json':
                return {'status_code': 200, 'content': {'agent': request.url}}
            cs = SimpleCookie()
            cookies = request.headers.get('Cookie')
            if cookies is not None:
                cs.load(str(cookies))
            public_key = None
            for c in cs:
                if c == 'agent-login':
                    json_cookie = json.loads(
                        base64.b64decode(cs[c].value).decode('utf-8'))
                    public_key = bakery.PublicKey.deserialize(
                        json_cookie.get('public_key'))
            ms = httpbakery.extract_macaroons(request.headers)
            if len(ms) == 0:
                b = bakery.Bakery(key=discharge_key)
                m = b.oven.macaroon(
                    version=bakery.LATEST_VERSION,
                    expiry=datetime.utcnow() + timedelta(days=1),
                    caveats=[
                        bakery.local_third_party_caveat(
                            public_key,
                            version=httpbakery.request_version(
                                request.headers))
                    ],
                    ops=[bakery.Op(entity='agent', action='login')])
                content, headers = httpbakery.discharge_required_response(
                    m, '/', 'test', 'message')
                resp = response(status_code=401,
                                content=content,
                                headers=headers)
                return request.hooks['response'][0](resp)

            return {'status_code': 200, 'content': {'agent-login': True}}
Пример #4
0
    def _write_discharge_error(self, exc):
        version = httpbakery.request_version(self.headers)
        if version < bakery.LATEST_VERSION:
            self._server_version = version

        caveats = []
        if self._auth_location != '':
            caveats = [
                checkers.Caveat(location=self._auth_location,
                                condition='is-ok')
            ]
        if self._caveats is not None:
            caveats.extend(self._caveats)

        m = self._bakery.oven.macaroon(version=bakery.LATEST_VERSION,
                                       expiry=self._expiry,
                                       caveats=caveats,
                                       ops=[TEST_OP])

        content, headers = httpbakery.discharge_required_response(
            m, '/', 'test', exc.args[0])
        self.send_response(401)
        for h in headers:
            self.send_header(h, headers[h])
        self.send_header('Connection', 'close')
        self.end_headers()
        self.wfile.write(content)
Пример #5
0
        def agent_visit(url, request):
            if request.method != "POST":
                raise Exception('unexpected method')
            log.info('agent_visit url {}'.format(url))
            body = json.loads(request.body.decode('utf-8'))
            if body['username'] != 'test-user':
                raise Exception('unexpected username in body {!r}'.format(
                    request.body))
            public_key = bakery.PublicKey.deserialize(body['public_key'])
            ms = httpbakery.extract_macaroons(request.headers)
            if len(ms) == 0:
                b = bakery.Bakery(key=discharge_key)
                m = b.oven.macaroon(
                    version=bakery.LATEST_VERSION,
                    expiry=datetime.utcnow() + timedelta(days=1),
                    caveats=[
                        bakery.local_third_party_caveat(
                            public_key,
                            version=httpbakery.request_version(
                                request.headers))
                    ],
                    ops=[bakery.Op(entity='agent', action='login')])
                content, headers = httpbakery.discharge_required_response(
                    m, '/', 'test', 'message')
                resp = response(status_code=401,
                                content=content,
                                headers=headers)
                return request.hooks['response'][0](resp)

            return {'status_code': 200, 'content': {'agent_login': True}}
Пример #6
0
 def server_get(url, request):
     ctx = checkers.AuthContext()
     test_ops = [bakery.Op(entity='test-op', action='read')]
     auth_checker = server_bakery.checker.auth(
         httpbakery.extract_macaroons(request.headers))
     try:
         auth_checker.allow(ctx, test_ops)
         resp = response(status_code=200, content='done')
     except bakery.PermissionDenied:
         caveats = [
             checkers.Caveat(location='http://0.3.2.1',
                             condition='is-ok')
         ]
         m = server_bakery.oven.macaroon(version=bakery.LATEST_VERSION,
                                         expiry=datetime.utcnow() +
                                         timedelta(days=1),
                                         caveats=caveats,
                                         ops=test_ops)
         content, headers = httpbakery.discharge_required_response(
             m, '/', 'test', 'message')
         resp = response(
             status_code=401,
             content=content,
             headers=headers,
         )
     return request.hooks['response'][0](resp)
    def _write_discharge_error(self, exc):
        version = httpbakery.request_version(self.headers)
        if version < bakery.LATEST_VERSION:
            self._server_version = version

        caveats = []
        if self._auth_location != '':
            caveats = [
                checkers.Caveat(location=self._auth_location,
                                condition='is-ok')
            ]
        if self._caveats is not None:
            caveats.extend(self._caveats)

        m = self._bakery.oven.macaroon(
            version=bakery.LATEST_VERSION, expiry=self._expiry,
            caveats=caveats, ops=[TEST_OP])

        content, headers = httpbakery.discharge_required_response(
            m, '/', 'test', exc.args[0])
        self.send_response(401)
        for h in headers:
            self.send_header(h, headers[h])
        self.send_header('Connection', 'close')
        self.end_headers()
        self.wfile.write(content)
Пример #8
0
def whoami():
    """Return authenticated user details."""
    try:
        account = _authenticate(request)
    except:
        content, headers = httpbakery.discharge_required_response(
            bkry.new(), '/', 'cookie-suffix')
        return content, 401, headers
    return account, 200
Пример #9
0
    def is_authorized(*args, **kwargs):
        macaroon_bakery = bakery.Bakery(
            location="ubuntu.com/security",
            locator=httpbakery.ThirdPartyLocator(),
            identity_client=IdentityClient(),
            key=bakery.generate_key(),
            root_key_store=bakery.MemoryKeyStore(
                flask.current_app.config["SECRET_KEY"]),
        )
        macaroons = httpbakery.extract_macaroons(flask.request.headers)
        auth_checker = macaroon_bakery.checker.auth(macaroons)
        launchpad = Launchpad.login_anonymously("ubuntu.com/security",
                                                "production",
                                                version="devel")

        try:
            auth_info = auth_checker.allow(checkers.AuthContext(),
                                           [bakery.LOGIN_OP])
        except bakery._error.DischargeRequiredError:
            macaroon = macaroon_bakery.oven.macaroon(
                version=bakery.VERSION_2,
                expiry=datetime.utcnow() + timedelta(days=1),
                caveats=IDENTITY_CAVEATS,
                ops=[bakery.LOGIN_OP],
            )

            content, headers = httpbakery.discharge_required_response(
                macaroon, "/", "cookie-suffix")
            return content, 401, headers

        username = auth_info.identity.username()
        lp_user = launchpad.people(username)
        authorized = False

        for team in AUTHORIZED_TEAMS:
            if lp_user in launchpad.people(team).members:
                authorized = True
                break

        if not authorized:
            return (
                f"{username} is not in any of the authorized teams: "
                f"{str(AUTHORIZED_TEAMS)}",
                401,
            )

        # Validate authentication token
        return func(*args, **kwargs)
Пример #10
0
 def _authorization_request(self, request, req_headers, bakery, err):
     """Return a 401 response with a macaroon discharge request."""
     expiry_duration = min(
         MACAROON_LIFESPAN,
         timedelta(seconds=request.session.get_expiry_age()))
     expiration = datetime.utcnow() + expiry_duration
     macaroon = bakery.oven.macaroon(
         httpbakery.request_version(req_headers),
         expiration, err.cavs(), err.ops())
     content, headers = httpbakery.discharge_required_response(
         macaroon, '/', 'authz')
     response = HttpResponse(
         status=401, reason='Unauthorized', content=content)
     for key, value in headers.items():
         response[key] = value
     return response
Пример #11
0
def _authorization_request(bakery, derr=None, auth_endpoint=None,
                           req_headers=None):
    """Return a 401 response with a macaroon discharge request."""
    bakery_version = httpbakery.request_version(req_headers or {})
    if derr:
        caveats, ops = derr.cavs(), derr.ops()
    else:
        caveats, ops = _get_macaroon_caveats_ops(auth_endpoint)
    expiration = datetime.utcnow() + MACAROON_LIFESPAN
    macaroon = bakery.oven.macaroon(bakery_version, expiration, caveats, ops)
    content, headers = httpbakery.discharge_required_response(
        macaroon, '/', 'maas')
    response = HttpResponse(
        status=401, reason='Unauthorized', content=content)
    for key, value in headers.items():
        response[key] = value
    return response