예제 #1
0
 def test_serializing_max_length_packet(self):
     m = Macaroon(location='test',
                  identifier='blah',
                  key='secret',
                  version=MACAROON_V1)
     m.add_first_party_caveat('x' * 65526)  # exactly 0xFFFF
     assert_not_equal(m.serialize(), None)
def alice_server_access_service():
    macaroon_cookie = request.cookies.get('macaroonCookie')
    discharge_cookie = request.cookies.get('macaroonDischargeCookie')
    if macaroon_cookie is not None and macaroon_cookie != "" and discharge_cookie is not None and discharge_cookie != "":
        m = Macaroon.deserialize(macaroon_cookie)
        dm = Macaroon.deserialize(discharge_cookie)
        # Should be done on the client
        pm = m.prepare_for_request(dm)
        v = Verifier()
        try:
            verified = v.verify(m, alice_server_keys[m.identifier], [pm])
        except MacaroonInvalidSignatureException:
            verified = False
        if verified:
            resp = make_response(
                render_template("auth_demo.html",
                                result="Successful Authentication"))
        else:
            resp = make_response(
                render_template("auth_demo.html", result="Auth failed"))
        return resp
    else:
        resp = make_response(
            render_template(
                "auth_demo.html",
                result="Couldn't get necessary macaroons from cookies"))
        return resp
예제 #3
0
 def test_serializing_too_long_packet(self):
     m = Macaroon(location='test', identifier='blah', key='secret')
     m.add_first_party_caveat('x' * 65527)  # one byte too long
     assert_raises(
         MacaroonSerializationException,
         m.serialize
     )
예제 #4
0
 def test_serializing_too_long_packet(self):
     m = Macaroon(location='test',
                  identifier='blah',
                  key='secret',
                  version=MACAROON_V1)
     m.add_first_party_caveat('x' * 65527)  # one byte too long
     assert_raises(MacaroonSerializationException, m.serialize)
예제 #5
0
 def test_serializing_max_length_packet(self):
     m = Macaroon(location='test', identifier='blah', key='secret')
     m.add_first_party_caveat('x' * 65526)  # exactly 0xFFFF
     assert_not_equal(
         m.serialize(),
         None
     )
예제 #6
0
def after_login(resp):
    try:
        root = Macaroon.deserialize(flask.session.pop("macaroon_root"))
    except KeyError:
        return (
            flask.render_template("templates/_error_login.html", ),
            400,
        )

    bound = root.prepare_for_request(
        Macaroon.deserialize(resp.extensions["macaroon"].discharge))
    flask.session["authentication_token"] = binary_serialize_macaroons(
        [root, bound]).decode("utf-8")

    if not resp.nickname:
        return flask.redirect(flask.current_app.config["CANONICAL_LOGIN_URL"])

    flask.session["openid"] = {
        "identity_url": resp.identity_url,
        "nickname": resp.nickname,
        "fullname": resp.fullname,
        "image": resp.image,
        "email": resp.email,
    }

    return flask.redirect(open_id.get_next_url())
예제 #7
0
 def discharge_macaroon_raw(self):
     root_macaroon = Macaroon.deserialize(self.root_macaroon_raw)
     unbound_discharge_macaroon = Macaroon.deserialize(
         self.unbound_discharge_macaroon_raw)
     discharge_macaroon = root_macaroon.prepare_for_request(
         unbound_discharge_macaroon)
     return discharge_macaroon.serialize()
예제 #8
0
 def test_upload_no_discharge(self):
     root_key = hashlib.sha256(self.factory.getUniqueString()).hexdigest()
     root_macaroon = Macaroon(key=root_key)
     snapbuild = self.makeUploadableSnapBuild(
         store_secrets={"root": root_macaroon.serialize()})
     transaction.commit()
     self._addUnscannedUploadResponse()
     self._addSnapPushResponse()
     with dbuser(config.ISnapStoreUploadJobSource.dbuser):
         self.assertEqual(
             "http://sca.example/dev/api/snaps/1/builds/1/status",
             self.client.upload(snapbuild))
     requests = [call.request for call in responses.calls]
     self.assertThat(requests, MatchesListwise([
         RequestMatches(
             url=Equals("http://updown.example/unscanned-upload/"),
             method=Equals("POST"),
             form_data={
                 "binary": MatchesStructure.byEquality(
                     name="binary", filename="test-snap.snap",
                     value="dummy snap content",
                     type="application/octet-stream",
                     )}),
         RequestMatches(
             url=Equals("http://sca.example/dev/api/snap-push/"),
             method=Equals("POST"),
             headers=ContainsDict(
                 {"Content-Type": Equals("application/json")}),
             auth=("Macaroon", MacaroonsVerify(root_key)),
             json_data={
                 "name": "test-snap", "updown_id": 1, "series": "rolling",
                 }),
         ]))
 def test_serializing_deserializing_macaroon(self, key_id, loc, key):
     assume(key_id and loc and key)
     macaroon = Macaroon(location=loc, identifier=key_id, key=key)
     deserialized = Macaroon.deserialize(macaroon.serialize())
     assert_equal(macaroon.identifier, deserialized.identifier)
     assert_equal(macaroon.location, deserialized.location)
     assert_equal(macaroon.signature, deserialized.signature)
예제 #10
0
    def test_verify_third_party_caveats_multi_level(self):
        # See https://github.com/ecordell/pymacaroons/issues/37
        root = Macaroon(location="", identifier="root-id", key="root-key")
        root.add_third_party_caveat("bob", "bob-caveat-root-key",
                                    "bob-is-great")

        # Create a discharge macaroon that requires a secondary discharge.
        discharge1 = Macaroon(location="bob",
                              identifier="bob-is-great",
                              key="bob-caveat-root-key")
        discharge1.add_third_party_caveat("barbara", "barbara-caveat-root-key",
                                          "barbara-is-great")

        # Create the secondary discharge macaroon.
        discharge2 = Macaroon(location="barbara",
                              identifier="barbara-is-great",
                              key="barbara-caveat-root-key")

        # Prepare the discharge macaroons for request.
        discharge1 = root.prepare_for_request(discharge1)
        discharge2 = root.prepare_for_request(discharge2)

        verified = Verifier(
            discharge_macaroons=[discharge1, discharge2]).verify(
                root, "root-key")
        assert_true(verified)
예제 #11
0
 def test_verify_unknown_issuer(self):
     macaroon = Macaroon(location=config.vhost.mainsite.hostname,
                         identifier='unknown-issuer',
                         key='test')
     self.assertEqual(
         faults.Unauthorized(),
         self.authserver.verifyMacaroon(macaroon.serialize(),
                                        'LibraryFileAlias', 1))
예제 #12
0
 def callback(request):
     new_macaroon = Macaroon(
         location="sso.example", key=self.discharge_key,
         identifier=self.discharge_caveat_id)
     new_macaroon.add_first_party_caveat("sso|expires|tomorrow")
     return (
         200, {},
         json.dumps({"discharge_macaroon": new_macaroon.serialize()}))
예제 #13
0
 def test_first_party_caveat(self):
     m = Macaroon(
         location='http://mybank/',
         identifier='we used our secret key',
         key='this is our super secret key; only we should know it')
     m.add_first_party_caveat('test = caveat')
     assert_equal(
         m.signature,
         '197bac7a044af33332865b9266e26d493bdd668a660e44d88ce1a998c23dbd67')
예제 #14
0
def bake(user: User, caveats: List[str]) -> str:
    m_obj = Macaroon(location=os.environ.get("ENDPOINT"),
                     identifier=user.username,
                     key=user.key)

    for caveat in caveats:
        m_obj.add_first_party_caveat(caveat)

    return m_obj.serialize()
예제 #15
0
 def test_serializing_json(self):
     m = Macaroon(
         location='http://mybank/',
         identifier='we used our secret key',
         key='this is our super secret key; only we should know it')
     m.add_first_party_caveat('test = caveat')
     assert_equal(
         json.loads(m.serialize(serializer=JsonSerializer()))['signature'],
         "197bac7a044af33332865b9266e26d493bdd668a660e44d88ce1a998c23dbd67")
예제 #16
0
def get_authorization_header(root, discharge):
    """
    Bind root and discharge macaroons and return the authorization header.
    """

    bound = Macaroon.deserialize(root).prepare_for_request(
        Macaroon.deserialize(discharge))

    return "Macaroon root={}, discharge={}".format(root, bound.serialize())
예제 #17
0
 def issueMacaroon(self, context, **kwargs):
     """See `IMacaroonIssuer`."""
     context = self.checkIssuingContext(context, **kwargs)
     macaroon = Macaroon(location=config.vhost.mainsite.hostname,
                         identifier=self.identifier,
                         key=self._root_secret)
     macaroon.add_first_party_caveat("%s %s" %
                                     (self._primary_caveat_name, context))
     return macaroon
예제 #18
0
 def test_serializing_json_v2(self):
     m = Macaroon(
         location='http://mybank/',
         identifier='we used our secret key',
         key='this is our super secret key; only we should know it',
         version=MACAROON_V2)
     m.add_first_party_caveat('test = caveat')
     assert_equal(
         json.loads(m.serialize(serializer=JsonSerializer()))['s64'],
         "GXusegRK8zMyhluSZuJtSTvdZopmDkTYjOGpmMI9vWc")
예제 #19
0
def get_authorization_header(root, discharge):
    """
    Bind root and discharge macaroons and return the authorization header.
    """

    bound = Macaroon.deserialize(root).prepare_for_request(
        Macaroon.deserialize(discharge)
    )

    return "Macaroon root={}, discharge={}".format(root, bound.serialize())
예제 #20
0
    def test_inspect(self):
        m = Macaroon(
            location='http://mybank/',
            identifier='we used our secret key',
            key='this is our super secret key; only we should know it'
        )
        m.add_first_party_caveat('test = caveat')
        assert_equal(m.inspect(), 'location http://mybank/\nidentifier we used\
 our secret key\ncid test = caveat\nsignature 197bac7a044af33332865b9266e26d49\
3bdd668a660e44d88ce1a998c23dbd67')
예제 #21
0
 def test_good_no_discharge(self):
     r = Request()
     root_key = hashlib.sha256("root").hexdigest()
     root_macaroon = Macaroon(key=root_key)
     MacaroonAuth(root_macaroon.serialize())(r)
     auth_value = r.headers["Authorization"]
     self.assertThat(auth_value, StartsWith("Macaroon "))
     self.assertThat(
         parse_dict_header(auth_value[len("Macaroon "):]),
         MacaroonsVerify(root_key))
예제 #22
0
def login_device(macaroon, manufacturer, channel_id):
    m = Macaroon(location='localhost',
                 identifier=manufacturer,
                 key=keys[manufacturer])
    m1 = Macaroon.deserialize(macaroon)
    channels = []
    for caveat in m1.caveats:
        m.add_first_party_caveat(caveat.to_dict()['cid'])
        channels.append(caveat.to_dict()['cid'])
    return m1.signature == m.signature and channel_id in channels[2:]
예제 #23
0
    def generate_macaroon(self, nonce):
        m = Macaroon(
            location='http://mybank/',
            identifier='we used our other secret key',
            key='this is a different super-secret key; \
never use the same secret twice'
        )
        m.add_first_party_caveat('account = 3735928559')
        caveat_key = '4; guaranteed random by a fair toss of the dice'
        identifier = 'this was how we remind auth of key/pred'
        m.add_third_party_caveat(
            'http://auth.mybank/',
            caveat_key,
            identifier,
            nonce=nonce,
        )

        discharge = Macaroon(
            location='http://auth.mybank/',
            key=caveat_key,
            identifier=identifier
        )
        discharge.add_first_party_caveat('time < 2015-01-01T00:00')
        protected = m.prepare_for_request(discharge)
        return protected.signature
예제 #24
0
    def test_verify_third_party_caveats(self):
        m = Macaroon(
            location='http://mybank/',
            identifier='we used our other secret key',
            key='this is a different super-secret key; \
never use the same secret twice'
        )
        m.add_first_party_caveat('account = 3735928559')
        caveat_key = '4; guaranteed random by a fair toss of the dice'
        identifier = 'this was how we remind auth of key/pred'
        m.add_third_party_caveat('http://auth.mybank/', caveat_key, identifier)

        discharge = Macaroon(
            location='http://auth.mybank/',
            key=caveat_key,
            identifier=identifier
        )
        discharge.add_first_party_caveat('time < 2015-01-01T00:00')
        protected = m.prepare_for_request(discharge)

        v = Verifier()
        v.satisfy_exact('account = 3735928559')
        v.satisfy_exact('time < 2015-01-01T00:00')
        verified = v.verify(
            m,
            'this is a different super-secret key; \
never use the same secret twice',
            discharge_macaroons=[protected]
        )
        assert_true(verified)
예제 #25
0
    def test_prepare_for_request(self, rand_nonce):
        # use a fixed nonce to ensure the same signature
        rand_nonce.return_value = truncate_or_pad(
            b'\0',
            size=crypto_box_NONCEBYTES
        )
        m = Macaroon(
            location='http://mybank/',
            identifier='we used our other secret key',
            key='this is a different super-secret key; \
never use the same secret twice'
        )
        m.add_first_party_caveat('account = 3735928559')
        caveat_key = '4; guaranteed random by a fair toss of the dice'
        identifier = 'this was how we remind auth of key/pred'
        m.add_third_party_caveat(
            'http://auth.mybank/',
            caveat_key,
            identifier
        )

        discharge = Macaroon(
            location='http://auth.mybank/',
            key=caveat_key,
            identifier=identifier
        )
        discharge.add_first_party_caveat('time < 2015-01-01T00:00')
        protected = m.prepare_for_request(discharge)
        assert_equal(
            protected.signature,
            '2eb01d0dd2b4475330739140188648cf25dda0425ea9f661f1574ca0a9eac54e'
        )
 def test_serializing_deserializing_macaroon(self, key_id, loc, key):
     assume(key_id and loc and key)
     macaroon = Macaroon(
         location=loc,
         identifier=key_id,
         key=key
     )
     deserialized = Macaroon.deserialize(macaroon.serialize())
     assert_equal(macaroon.identifier, deserialized.identifier)
     assert_equal(macaroon.location, deserialized.location)
     assert_equal(macaroon.signature, deserialized.signature)
예제 #27
0
 def test_serializing_v2(self):
     m = Macaroon(
         location='http://mybank/',
         identifier='we used our secret key',
         key='this is our super secret key; only we should know it',
         version=MACAROON_V2
     )
     m.add_first_party_caveat('test = caveat')
     n = Macaroon.deserialize(m.serialize())
     assert_equal(m.identifier_bytes, n.identifier_bytes)
     assert_equal(m.version, n.version)
예제 #28
0
 def test_serializing_json(self):
     m = Macaroon(
         location='http://mybank/',
         identifier='we used our secret key',
         key='this is our super secret key; only we should know it'
     )
     m.add_first_party_caveat('test = caveat')
     assert_equal(
         json.loads(m.serialize(serializer=JsonSerializer()))['signature'],
         "197bac7a044af33332865b9266e26d493bdd668a660e44d88ce1a998c23dbd67"
     )
예제 #29
0
    def test_serializing(self):
        m = Macaroon(
            location='http://mybank/',
            identifier='we used our secret key',
            key='this is our super secret key; only we should know it')
        m.add_first_party_caveat('test = caveat')
        assert_equal(
            m.serialize(),
            'MDAxY2xvY2F0aW9uIGh0dHA6Ly9teWJhbmsvCjAwMjZpZGVudGlmaWVyIHdlIHVzZ\
WQgb3VyIHNlY3JldCBrZXkKMDAxNmNpZCB0ZXN0ID0gY2F2ZWF0CjAwMmZzaWduYXR1cmUgGXusegR\
K8zMyhluSZuJtSTvdZopmDkTYjOGpmMI9vWcK')
예제 #30
0
 def create_macaroons(self):
     (key_id, key) = create_key_id_pair(prefix='{loc}::{user}::'.format(
         loc=current_app.config['TARGET_SERVICE_LOCATION'],
         user=self.username))
     macaroon = Macaroon(
         location=current_app.config['TARGET_SERVICE_LOCATION'],
         key=key,
         identifier=key_id)
     discharge = self._add_user_caveat(macaroon)
     protected = macaroon.prepare_for_request(discharge)
     return macaroon, protected
예제 #31
0
    def test_verify_failing_first_party_general_caveats(self):
        m = Macaroon(
            location='http://mybank/',
            identifier='we used our secret key',
            key='this is our super secret key; only we should know it')
        m.add_first_party_caveat('general caveat')

        v = Verifier()
        v.satisfy_general(lambda _: False)
        with assert_raises(MacaroonInvalidSignatureException) as cm:
            v.verify(m, 'this is our super secret key; only we should know it')
예제 #32
0
 def test_verify_first_party_exact_caveats(self):
     m = Macaroon(
         location='http://mybank/',
         identifier='we used our secret key',
         key='this is our super secret key; only we should know it')
     m.add_first_party_caveat('test = caveat')
     v = Verifier()
     v.satisfy_exact('test = caveat')
     verified = v.verify(
         m, 'this is our super secret key; only we should know it')
     assert_true(verified)
    def _get_authorization_header(self, session):
        """
        Bind root and discharge macaroons and return the authorization header.
        """
        root = session["macaroon_root"]
        discharge = session["macaroon_discharge"]

        bound = (Macaroon.deserialize(root).prepare_for_request(
            Macaroon.deserialize(discharge)).serialize())

        return {"Authorization": f"Macaroon root={root}, discharge={bound}"}
예제 #34
0
 def test_encrypted_first_party_caveat(self):
     m = Macaroon(
         location='http://mybank/',
         identifier='we used our secret key',
         key='this is our super secret key; only we should know it')
     encryptor = SecretBoxEncryptor(nonce=ZERO_NONCE)
     m.first_party_caveat_delegate = EncryptedFirstPartyCaveatDelegate(
         field_encryptor=encryptor)
     m.add_first_party_caveat('test = caveat', encrypted=True)
     assert_equal(
         m.signature,
         'a443bc61e8f45dca4f0c441d6cfde90b804cebb0b267aab60de1ec2ab8cc8522')
예제 #35
0
 def test_serializing_json_v2(self):
     m = Macaroon(
         location='http://mybank/',
         identifier='we used our secret key',
         key='this is our super secret key; only we should know it',
         version=MACAROON_V2
     )
     m.add_first_party_caveat('test = caveat')
     assert_equal(
         json.loads(m.serialize(serializer=JsonSerializer()))['s64'],
         "GXusegRK8zMyhluSZuJtSTvdZopmDkTYjOGpmMI9vWc"
     )
예제 #36
0
 def test_serializing_with_binary_v2(self):
     identifier = base64.b64decode('AK2o+q0Aq9+bONkXw7ky7HAuhCLO9hhaMMc==')
     m = Macaroon(
         location='http://mybank/',
         identifier=identifier,
         key='this is our super secret key; only we should know it',
         version=MACAROON_V2
     )
     m.add_first_party_caveat('test = caveat')
     n = Macaroon.deserialize(m.serialize())
     assert_equal(m.identifier_bytes, n.identifier_bytes)
     assert_equal(m.version, n.version)
예제 #37
0
 def test_serializing_deserializing_json(self):
     m = Macaroon(
         location='http://test/',
         identifier='first',
         key='secret_key_1'
     )
     m.add_first_party_caveat('test = caveat')
     n = Macaroon.deserialize(
         m.serialize(serializer=JsonSerializer()),
         serializer=JsonSerializer()
     )
     assert_equal(m.signature, n.signature)
예제 #38
0
 def test_serializing_strips_padding(self):
     m = Macaroon(
         location='http://mybank/',
         identifier='we used our secret key',
         key='this is our super secret key; only we should know it')
     m.add_first_party_caveat('test = acaveat')
     assert_equal(
         m.serialize(),
         # In padded base64, this would end with '=='
         ('MDAxY2xvY2F0aW9uIGh0dHA6Ly9teWJhbmsvCjAwMjZpZGVudGlmaWVyIHdlIHVz'
          'ZWQgb3VyIHNlY3JldCBrZXkKMDAxN2NpZCB0ZXN0ID0gYWNhdmVhdAowMDJmc2ln'
          'bmF0dXJlIJRJ_V3WNJQnqlVq5eez7spnltwU_AXs8NIRY739sHooCg'))
 def test_encrypted_first_party_caveat(self):
     m = Macaroon(
         location='http://mybank/',
         identifier='we used our secret key',
         key='this is our super secret key; only we should know it'
     )
     encryptor = SecretBoxEncryptor(nonce=ZERO_NONCE)
     m.first_party_caveat_delegate = EncryptedFirstPartyCaveatDelegate(field_encryptor=encryptor)
     m.add_first_party_caveat('test = caveat', encrypted=True)
     assert_equal(
         m.signature,
         'a443bc61e8f45dca4f0c441d6cfde90b804cebb0b267aab60de1ec2ab8cc8522'
     )
예제 #40
0
    def test_serializing(self):
        m = Macaroon(
            location='http://mybank/',
            identifier='we used our secret key',
            key='this is our super secret key; only we should know it'
        )
        m.add_first_party_caveat('test = caveat')
        assert_equal(
            m.serialize(),
            'MDAxY2xvY2F0aW9uIGh0dHA6Ly9teWJhbmsvCjAwMjZpZGVudGlmaWVyIHdlIHVzZ\
WQgb3VyIHNlY3JldCBrZXkKMDAxNmNpZCB0ZXN0ID0gY2F2ZWF0CjAwMmZzaWduYXR1cmUgGXusegR\
K8zMyhluSZuJtSTvdZopmDkTYjOGpmMI9vWcK'
        )
예제 #41
0
 def test_serializing_json_v2_with_binary(self):
     id = base64.b64decode('AK2o+q0Aq9+bONkXw7ky7HAuhCLO9hhaMMc==')
     m = Macaroon(
         location='http://mybank/',
         identifier=id,
         key='this is our super secret key; only we should know it',
         version=MACAROON_V2)
     assert_equal(
         json.loads(m.serialize(serializer=JsonSerializer()))['i64'],
         "AK2o-q0Aq9-bONkXw7ky7HAuhCLO9hhaMMc")
     n = Macaroon.deserialize(m.serialize(serializer=JsonSerializer()),
                              serializer=JsonSerializer())
     assert_equal(m.identifier_bytes, n.identifier_bytes)
예제 #42
0
 def test_mutual_discharge(self):
     m1 = Macaroon(location="", identifier="root-id", key="root-key")
     m1.add_third_party_caveat("bob", "bob-caveat-root-key", "bob-is-great")
     m2 = Macaroon(location="bob",
                   identifier="bob-is-great",
                   key="bob-caveat-root-key")
     m2.add_third_party_caveat("charlie", "bob-caveat-root-key",
                               "bob-is-great")
     m2 = m1.prepare_for_request(m2)
     Verifier(discharge_macaroons=[m2]).verify(m1, "root-key")
예제 #43
0
    def verify(self, session, discharge):
        session_macaroon = Macaroon.from_binary(session)
        discharge_macaroon = Macaroon.from_binary(discharge)

        self.logger.debug('Root Macaroon:\n' + session_macaroon.inspect())
        self.logger.debug('Discharge Macaroon:\n' +
                          discharge_macaroon.inspect())

        verifier = Verifier()
        verifier.satisfy_general(verify_time)
        verified = verifier.verify(session_macaroon,
                                   self.redis.get(session_macaroon.identifier),
                                   discharge_macaroons=[discharge_macaroon])
        return verified
예제 #44
0
def _prepare_request(method, path, data=None, session=None):
    request = Request(method=method, url=f"{API_URL}{path}")

    if session:
        root = Macaroon.deserialize(session["macaroon_root"])
        discharge = Macaroon.deserialize(session["macaroon_discharge"])
        bound = root.prepare_for_request(discharge)
        token = binary_serialize_macaroons([root, bound]).decode("utf-8")
        request.headers["Authorization"] = f"Macaroon {token}"

    if data is not None:
        request.json = data

    return request.prepare()
예제 #45
0
    def discharge_macaroon(self, macaroon, token):
        # Deserialize the macaroon with pymacaroons
        macaroon = Macaroon.deserialize(macaroon, JsonSerializer())

        # Extract the caveat we are interested in
        caveat = self._extract_caveat_to_discharge(macaroon)

        data = {"id64": caveat, "token64": token, "token-kind": "macaroon"}
        response = self._request(method="POST",
                                 url=f"{CANDID_API_URL}discharge",
                                 data=data)

        return Macaroon.deserialize(json.dumps(response.json()["Macaroon"]),
                                    JsonSerializer())
예제 #46
0
 def test_verify_first_party_exact_caveats(self):
     m = Macaroon(
         location='http://mybank/',
         identifier='we used our secret key',
         key='this is our super secret key; only we should know it'
     )
     m.add_first_party_caveat('test = caveat')
     v = Verifier()
     v.satisfy_exact('test = caveat')
     verified = v.verify(
         m,
         'this is our super secret key; only we should know it'
     )
     assert_true(verified)
예제 #47
0
 def test_serializing_strips_padding(self):
     m = Macaroon(
         location='http://mybank/',
         identifier='we used our secret key',
         key='this is our super secret key; only we should know it'
     )
     m.add_first_party_caveat('test = acaveat')
     assert_equal(
         m.serialize(),
         # In padded base64, this would end with '=='
         ('MDAxY2xvY2F0aW9uIGh0dHA6Ly9teWJhbmsvCjAwMjZpZGVudGlmaWVyIHdlIHVz'
          'ZWQgb3VyIHNlY3JldCBrZXkKMDAxN2NpZCB0ZXN0ID0gYWNhdmVhdAowMDJmc2ln'
          'bmF0dXJlIJRJ_V3WNJQnqlVq5eez7spnltwU_AXs8NIRY739sHooCg')
     )
예제 #48
0
    def test_verify_failing_first_party_general_caveats(self):
        m = Macaroon(
            location='http://mybank/',
            identifier='we used our secret key',
            key='this is our super secret key; only we should know it'
        )
        m.add_first_party_caveat('general caveat')

        v = Verifier()
        v.satisfy_general(lambda _: False)
        with assert_raises(MacaroonInvalidSignatureException) as cm:
            v.verify(
                m,
                'this is our super secret key; only we should know it'
            )
예제 #49
0
 def test_serializing_json_v2_with_binary(self):
     id = base64.b64decode('AK2o+q0Aq9+bONkXw7ky7HAuhCLO9hhaMMc==')
     m = Macaroon(
         location='http://mybank/',
         identifier=id,
         key='this is our super secret key; only we should know it',
         version=MACAROON_V2
     )
     assert_equal(
         json.loads(m.serialize(serializer=JsonSerializer()))['i64'],
         "AK2o-q0Aq9-bONkXw7ky7HAuhCLO9hhaMMc"
     )
     n = Macaroon.deserialize(
         m.serialize(serializer=JsonSerializer()),
         serializer=JsonSerializer()
     )
     assert_equal(m.identifier_bytes, n.identifier_bytes)
    def test_verify_encrypted_first_party_exact_caveats(self):
        m = Macaroon(
            location='http://mybank/',
            identifier='we used our secret key',
            key='this is our super secret key; only we should know it'
        )
        m.first_party_caveat_delegate = EncryptedFirstPartyCaveatDelegate()
        m.add_first_party_caveat('test = caveat', encrypted=True)

        v = Verifier()
        v.first_party_caveat_verifier_delegate = EncryptedFirstPartyCaveatVerifierDelegate()
        v.satisfy_exact('test = caveat')
        verified = v.verify(
            m,
            'this is our super secret key; only we should know it'
        )
        assert_true(verified)
예제 #51
0
 def test_mutual_discharge(self):
     m1 = Macaroon(location="", identifier="root-id", key="root-key")
     m1.add_third_party_caveat("bob", "bob-caveat-root-key", "bob-is-great")
     m2 = Macaroon(location="bob", identifier="bob-is-great", key="bob-caveat-root-key")
     m2.add_third_party_caveat("charlie", "bob-caveat-root-key", "bob-is-great")
     m2 = m1.prepare_for_request(m2)
     Verifier(discharge_macaroons=[m2]).verify(m1, "root-key")
예제 #52
0
    def test_from_go_macaroon_json_v2(self):
        # The following macaroon have been generated with
        # https://github.com/go-macaroon/macaroon
        # to test the deserialization.
        json_v1 = '{"caveats":[{"cid":"fp caveat"},{"cid":"tp caveat",' \
                  '"vid":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAp_MgxHrfLnfvNuYDo' \
                  'zNKWTlRPPx6VemasWnPpJdAWE6FWmOuFX4sB4-a1oAURDp",' \
                  '"cl":"tp location"}],"location":"my location",' \
                  '"identifier":"my identifier",' \
                  '"signature":"483b3881c9990e5099cb6695da3164daa64da60417b' \
                  'caf9e9dc4c0a9968f6636"}'
        json_v1_discharge = '{"caveats":[],"location":"tp location",' \
                            '"identifier":"tp caveat",' \
                            '"signature":"8506007f69ae3e6a654e0b9769f20dd9da5' \
                            'd2af7860070d6776c15989fb7dea6"}'
        m = Macaroon.deserialize(json_v1, serializer=JsonSerializer())
        discharge = Macaroon.deserialize(json_v1_discharge,
                                         serializer=JsonSerializer())
        assert_macaroon(m, discharge, MACAROON_V1)

        binary_v1 = 'MDAxOWxvY2F0aW9uIG15IGxvY2F0aW9uCjAwMWRpZGVudGlmaWVyIG1' \
                    '5IGlkZW50aWZpZXIKMDAxMmNpZCBmcCBjYXZlYXQKMDAxMmNpZCB0cC' \
                    'BjYXZlYXQKMDA1MXZpZCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACn' \
                    '8yDEet8ud+825gOjM0pZOVE8/HpV6Zqxac+kl0BYToVaY64VfiwHj5r' \
                    'WgBREOkKMDAxM2NsIHRwIGxvY2F0aW9uCjAwMmZzaWduYXR1cmUgSDs' \
                    '4gcmZDlCZy2aV2jFk2qZNpgQXvK+encTAqZaPZjYK'
        binary_v1_discharge = 'MDAxOWxvY2F0aW9uIHRwIGxvY2F0aW9uCjAwMTlpZGVud' \
                              'GlmaWVyIHRwIGNhdmVhdAowMDJmc2lnbmF0dXJlIIUGAH' \
                              '9prj5qZU4Ll2nyDdnaXSr3hgBw1ndsFZift96mCg'
        m = Macaroon.deserialize(binary_v1)
        discharge = Macaroon.deserialize(binary_v1_discharge)
        assert_macaroon(m, discharge, MACAROON_V1)

        json_v2 = '{"c":[{"i":"fp caveat"},{"i":"tp caveat",' \
                  '"v64":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAp_MgxHrfLnfvNuYDoz' \
                  'NKWTlRPPx6VemasWnPpJdAWE6FWmOuFX4sB4-a1oAURDp",' \
                  '"l":"tp location"}],"l":"my location","i":"my identifier",' \
                  '"s64":"SDs4gcmZDlCZy2aV2jFk2qZNpgQXvK-encTAqZaPZjY"}'
        json_v2_discharge = '{"l":"tp location","i":"tp caveat","s64":"hQYAf2' \
                            'muPmplTguXafIN2dpdKveGAHDWd2wVmJ-33qY"}'
        m = Macaroon.deserialize(json_v2, serializer=JsonSerializer())
        discharge = Macaroon.deserialize(json_v2_discharge,
                                         serializer=JsonSerializer())
        assert_macaroon(m, discharge, MACAROON_V2)

        binary_v2 = 'AgELbXkgbG9jYXRpb24CDW15IGlkZW50aWZpZXIAAglmcCBjYXZlYXQ' \
                    'AAQt0cCBsb2NhdGlvbgIJdHAgY2F2ZWF0BEgAAAAAAAAAAAAAAAAAAA' \
                    'AAAAAAAAAAAAACn8yDEet8ud+825gOjM0pZOVE8/HpV6Zqxac+kl0BY' \
                    'ToVaY64VfiwHj5rWgBREOkAAAYgSDs4gcmZDlCZy2aV2jFk2qZNpgQX' \
                    'vK+encTAqZaPZjY'
        binary_v2_discharge = 'AgELdHAgbG9jYXRpb24CCXRwIGNhdmVhdAAABiCFBgB/a' \
                              'a4+amVOC5dp8g3Z2l0q94YAcNZ3bBWYn7fepg'
        m = Macaroon.deserialize(binary_v2)
        discharge = Macaroon.deserialize(binary_v2_discharge)
        assert_macaroon(m, discharge, MACAROON_V2)
예제 #53
0
    def test_verify_first_party_general_caveats(self):
        m = Macaroon(
            location='http://mybank/',
            identifier='we used our secret key',
            key='this is our super secret key; only we should know it'
        )
        m.add_first_party_caveat('general caveat')

        def general_caveat_validator(predicate):
            return predicate == 'general caveat'

        v = Verifier()
        v.satisfy_general(general_caveat_validator)
        verified = v.verify(
            m,
            'this is our super secret key; only we should know it'
        )
        assert_true(verified)
예제 #54
0
def macaroon_from_dict(json_macaroon):
    '''Return a pymacaroons.Macaroon object from the given
    JSON-deserialized dict.

    @param JSON-encoded macaroon as dict
    @return the deserialized macaroon object.
    '''
    return Macaroon.deserialize(json.dumps(json_macaroon),
                                json_serializer.JsonSerializer())
예제 #55
0
def get_store_authorization(
        email, permissions=None, channels=None, store_env=None,
        allowed_stores=None, snaps=None):
    """Return the serialised root and discharge macaroon.

    Get a permissions macaroon from SCA and discharge it in SSO.
    """
    headers = DEFAULT_HEADERS.copy()
    # Request a SCA root macaroon with hard expiration in 180 days.
    sca_data = {
        'permissions': permissions or ['package_access'],
        'expires': (
            datetime.date.today() + datetime.timedelta(days=180)
            ).strftime('%Y-%m-%d 00:00:00')
    }
    if channels:
        sca_data['channels'] = channels
    if allowed_stores:
        sca_data['store_ids'] = allowed_stores
    if snaps:
        sca_data['packages'] = [{'name': snap} for snap in snaps]

    response = requests.request(
        url='{}/dev/api/acl/'.format(CONSTANTS[store_env]['sca_base_url']),
        method='POST', json=sca_data, headers=headers)
    if response.status_code != 200:
        error = response.json()['title']
        raise CliError("Error {}: {}".format(response.status_code, error))
    root = response.json()['macaroon']

    caveat, = [
        c for c in Macaroon.deserialize(root).third_party_caveats()
        if c.location == CONSTANTS[store_env]['sso_location']
    ]
    # Request a SSO discharge macaroon.
    sso_data = {
        'email': email,
        'password': getpass.getpass('Password for {}: '.format(email)),
        'caveat_id': caveat.caveat_id,
    }
    response = requests.request(
        url='{}/api/v2/tokens/discharge'.format(
            CONSTANTS[store_env]['sso_base_url']),
        method='POST', json=sso_data, headers=headers)
    # OTP/2FA is optional.
    if (response.status_code == 401 and
            response.json().get('code') == 'TWOFACTOR_REQUIRED'):
        sys.stderr.write('Second-factor auth for {}: '.format(store_env))
        sso_data.update({'otp': input()})
        response = requests.request(
            url='{}/api/v2/tokens/discharge'.format(
                CONSTANTS[store_env]['sso_base_url']),
            method='POST', json=sso_data, headers=headers)
    discharge = response.json()['discharge_macaroon']

    return root, discharge
예제 #56
0
    def test_third_party_caveat(self):
        m = Macaroon(
            location='http://mybank/',
            identifier='we used our other secret key',
            key='this is a different super-secret key; \
never use the same secret twice'
        )
        m.add_first_party_caveat('account = 3735928559')
        caveat_key = '4; guaranteed random by a fair toss of the dice'
        identifier = 'this was how we remind auth of key/pred'
        m.add_third_party_caveat(
            'http://auth.mybank/',
            caveat_key,
            identifier,
            nonce=ZERO_NONCE)
        assert_equal(
            m.signature,
            'd27db2fd1f22760e4c3dae8137e2d8fc1df6c0741c18aed4b97256bf78d1f55c'
        )
예제 #57
0
 def test_deserializing_accepts_padding(self):
     m = Macaroon.deserialize(
         ('MDAxY2xvY2F0aW9uIGh0dHA6Ly9teWJhbmsvCjAwMjZpZGVudGlmaWVyIHdlIHVz'
          'ZWQgb3VyIHNlY3JldCBrZXkKMDAxN2NpZCB0ZXN0ID0gYWNhdmVhdAowMDJmc2ln'
          'bmF0dXJlIJRJ_V3WNJQnqlVq5eez7spnltwU_AXs8NIRY739sHooCg==')
     )
     assert_equal(
         m.signature,
         '9449fd5dd6349427aa556ae5e7b3eeca6796dc14fc05ecf0d21163bdfdb07a28'
     )
예제 #58
0
    def test_deserializing(self):
        m = Macaroon.deserialize(
            'MDAxY2xvY2F0aW9uIGh0dHA6Ly9teWJhbmsvCjAwMjZpZGVudGlmaW\
VyIHdlIHVzZWQgb3VyIHNlY3JldCBrZXkKMDAxNmNpZCB0ZXN0ID0gY2F2ZWF0CjAwMmZzaWduYXR1\
cmUgGXusegRK8zMyhluSZuJtSTvdZopmDkTYjOGpmMI9vWcK'
        )
        assert_equal(
            m.signature,
            '197bac7a044af33332865b9266e26d493bdd668a660e44d88ce1a998c23dbd67'
        )
    def test_macaroon_paper_fig6_fails_with_binding_on_tampered_sig(self):
        ''' Runs a similar test as test_macaroon_paper_fig6 with the discharge
        macaroon binding being done on a tampered signature.
        '''
        locator = bakery.ThirdPartyStore()
        bs = common.new_bakery('bs-loc', locator)
        ts = common.new_bakery('ts-loc', locator)

        # ts creates a macaroon.
        ts_macaroon = ts.oven.macaroon(bakery.LATEST_VERSION,
                                       common.ages, None,
                                       [bakery.LOGIN_OP])
        # ts somehow sends the macaroon to fs which adds a third party caveat
        # to be discharged by as.
        ts_macaroon.add_caveat(checkers.Caveat(condition='user==bob',
                                               location='bs-loc'),
                               ts.oven.key, ts.oven.locator)

        # client asks for a discharge macaroon for each third party caveat
        def get_discharge(cav, payload):
            self.assertEqual(cav.location, 'bs-loc')
            return bakery.discharge(
                common.test_context,
                cav.caveat_id_bytes,
                payload,
                bs.oven.key,
                common.ThirdPartyStrcmpChecker('user==bob'),
                bs.oven.locator,
            )

        d = bakery.discharge_all(ts_macaroon, get_discharge)
        # client has all the discharge macaroons. For each discharge macaroon
        # bind it to our ts_macaroon and add it to our request.
        tampered_macaroon = Macaroon()
        for i, dm in enumerate(d[1:]):
            d[i + 1] = tampered_macaroon.prepare_for_request(dm)

        # client makes request to ts.
        with self.assertRaises(bakery.VerificationError) as exc:
            ts.checker.auth([d]).allow(common.test_context,
                                       bakery.LOGIN_OP)
        self.assertEqual('verification failed: Signatures do not match',
                         exc.exception.args[0])
예제 #60
0
    def test_login_handler_redirect(self):
        m = Macaroon()
        m.add_third_party_caveat("login.ubuntu.com", "key", "id")

        serialized_macaroon = m.serialize()

        responses.add(
            responses.Response(
                method="POST",
                url=self.api_url,
                json={"macaroon": serialized_macaroon},
                status=200,
            )
        )

        response = self.client.get(self.endpoint_url)

        assert len(responses.calls) == 1
        assert response.status_code == 302