def test_logging(self): r = Request() root_key = hashlib.sha256("root").hexdigest() root_macaroon = Macaroon(key=root_key) discharge_key = hashlib.sha256("discharge").hexdigest() discharge_caveat_id = '{"secret": "thing"}' root_macaroon.add_third_party_caveat( "sso.example", discharge_key, discharge_caveat_id) root_macaroon.add_first_party_caveat( "store.example|package_id|{}".format( json.dumps(["example-package"]))) unbound_discharge_macaroon = Macaroon( location="sso.example", key=discharge_key, identifier=discharge_caveat_id) unbound_discharge_macaroon.add_first_party_caveat( "sso.example|account|{}".format( base64.b64encode(json.dumps({ "openid": "1234567", "email": "*****@*****.**", })))) logger = BufferLogger() MacaroonAuth( root_macaroon.serialize(), unbound_discharge_macaroon.serialize(), logger=logger)(r) self.assertEqual( ['DEBUG root macaroon: snap-ids: ["example-package"]', 'DEBUG discharge macaroon: OpenID identifier: 1234567'], logger.getLogBuffer().splitlines())
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_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 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)
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 )
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 _make_store_secrets(self): self.root_key = hashlib.sha256( self.factory.getUniqueString()).hexdigest() root_macaroon = Macaroon(key=self.root_key) self.discharge_key = hashlib.sha256( self.factory.getUniqueString()).hexdigest() self.discharge_caveat_id = self.factory.getUniqueString() root_macaroon.add_third_party_caveat( "sso.example", self.discharge_key, self.discharge_caveat_id) unbound_discharge_macaroon = Macaroon( location="sso.example", key=self.discharge_key, identifier=self.discharge_caveat_id) return { "root": root_macaroon.serialize(), "discharge": unbound_discharge_macaroon.serialize(), }
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)
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_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))
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()}))
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()
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")
def test_good(self): r = Request() root_key = hashlib.sha256("root").hexdigest() root_macaroon = Macaroon(key=root_key) discharge_key = hashlib.sha256("discharge").hexdigest() discharge_caveat_id = '{"secret": "thing"}' root_macaroon.add_third_party_caveat( "sso.example", discharge_key, discharge_caveat_id) unbound_discharge_macaroon = Macaroon( location="sso.example", key=discharge_key, identifier=discharge_caveat_id) MacaroonAuth( root_macaroon.serialize(), unbound_discharge_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))
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")
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))
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)
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)
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" )
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')
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)
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)
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" )
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)
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)
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 make_token(): form = forms.MakeToken() #Grab image names from uploads/images folder names = get_images() names.insert(0, "Select Image") form.image_name.choices = [(name, name) for name in names] form.expiry_time.choices = [(x, '{} minutes'.format(x)) for x in range(1, 31)] #On valid for submission if form.validate_on_submit(): email = form.user_email.data #Create macaroon so entered user email can view image m = Macaroon(location='http://localhost:5000/gallery/{}'.format( form.image_name.data), identifier='secret-key', key=keys['secret-key']) #Get chosen expiry time chosen_expiry = int(form.expiry_time.data) expiry_time = datetime.now() + timedelta(minutes=chosen_expiry) #Add first party caveas to Macaroon m.add_first_party_caveat('email = {}'.format(email)) m.add_first_party_caveat('image_name = {}'.format( form.image_name.data)) m.add_first_party_caveat('time < {}'.format(expiry_time)) #Determine IP address for creating access link try: vm_ip = ni.ifaddresses('ens33')[ni.AF_INET][0]['addr'] except: try: vm_ip = ni.ifaddresses('eth0')[ni.AF_INET][0]['addr'] except: vm_ip = ni.ifaddresses('wlan0')[ni.AF_INET][0]['addr'] #Create share link to be given to user final_link = "http://{}:5000/gallery/{}/{}".format( vm_ip, m.serialize(), form.image_name.data) flash( Markup("Give this user the following link:<br /><a href={}>{}</a>". format(final_link, final_link))) return render_template('make_token.html', form=form, images=names)
def test_serializing_macaroon_with_first_and_third_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) n = Macaroon.deserialize(m.serialize()) assert_equal(m.signature, n.signature)
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' )
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 auth_server_login(): user_name = request.form['username'] for user in auth_server_users: if user["name"] == user_name and user["identifier"] != "": dm = Macaroon(location='http://auth-server.example.com/', key=user["caveat_key"], identifier=user["identifier"]) # dm = dm.add_first_party_caveat('time < 2020-01-01T00:00') serialized = dm.serialize() resp = make_response( render_template("auth_demo.html", discharge_macaroon=dm.inspect().replace( "\n", "<br/>"))) resp.set_cookie('macaroonDischargeCookie', serialized) return resp resp = make_response( render_template("auth_demo.html", result="Auth failed")) return resp
def test_serializing_macaroon_with_first_and_third_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) n = Macaroon.deserialize(m.serialize()) assert_equal( m.signature, n.signature )
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
def generate_macaroons(device, manufacturer, channels): # Check if we have key for the existing device # If so, revoke it and add the new one if check_macaroon(device): revoke_macaroon_by_device(device) m = Macaroon(location='localhost', identifier=manufacturer, key=keys[manufacturer]) m.add_first_party_caveat(device) validity = "Valid till: " + str(time.time() + 31556952) m.add_first_party_caveat(validity) for channel in channels: m.add_first_party_caveat(channel) # Add to a file for blacklisting and whitelisting with open('whitelist.csv', 'a') as csvfile: writer = csv.writer(csvfile, delimiter=',') writer.writerow([device, validity, m.serialize()] + channels) return m
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
async def r_prepay_wallet(*_, amount: int, memo: str): if amount < 10000: return Error( "InsufficientFunds", "Prepaid Wallets must have a value of at least 10000 sats", ) expiry_time = 3600 * 24 preimage = token_bytes(32) macaroon_key = token_bytes(32) request = ln.Invoice( value=amount, memo=memo, expiry=expiry_time, r_preimage=preimage ) inv = await LND.stub.AddInvoice(request) macaroon = Macaroon( location=os.environ.get("ENDPOINT"), identifier=b64encode(inv.r_hash).decode(), key=macaroon_key, ) # add macaroon caveats macaroon.add_first_party_caveat("uses = 1") macaroon.add_first_party_caveat("action = REDEEM_WALLET") # caveat is unecessary for validation and is only included so the token holder may know the amount being redeemed macaroon.add_first_party_caveat(f"amount = {amount}") lsat = await LSAT.create( key=macaroon_key, payment_hash=b64encode(inv.r_hash).decode(), preimage=b64encode(preimage).decode(), used=0, uses=1, ) lsat.macaroon = macaroon.serialize() lsat.payment_request = inv.payment_request lsat.amount = amount return lsat
def photo_album_login(): login_successful = True if login_successful: m = Macaroon(location='cool-picture-service.example.com', identifier='key-for-bob', key=keys['key-for-bob']) # Add a caveat for the target service m.add_first_party_caveat('view_pictures = True') serialized = m.serialize() images = [True, True, True] resp = make_response( render_template("home.html", showimages=True, images=images, macaroon=m.inspect().replace("\n", "<br/>"))) resp.set_cookie('macaroonCookie', serialized) return resp else: return redirect(url_for("login"))
def alice_server_get_macaroon(): m = Macaroon(location='alices-server.example.com', identifier='key-for-bob', key=alice_server_keys['key-for-bob']) # should be random caveat_key = 'randomKey' predicate = 'Bob' identifier = auth_server_get_identifier(caveat_key, predicate) # location is unused m.add_third_party_caveat('http://auth-server.example.com/', caveat_key, identifier) serialized = m.serialize() resp = make_response( render_template("auth_demo.html", macaroon=m.inspect().replace("\n", "<br/>"), caveat_key=caveat_key, identifier=identifier)) resp.set_cookie('macaroonCookie', serialized) return resp
def test_release_no_discharge(self): root_key = hashlib.sha256(self.factory.getUniqueString()).hexdigest() root_macaroon = Macaroon(key=root_key) snap = self.factory.makeSnap( store_upload=True, store_series=self.factory.makeSnappySeries(name="rolling"), store_name="test-snap", store_secrets={"root": root_macaroon.serialize()}, store_channels=["stable", "edge"]) snapbuild = self.factory.makeSnapBuild(snap=snap) self._addSnapReleaseResponse() self.client.release(snapbuild, 1) self.assertThat(responses.calls[-1].request, RequestMatches( url=Equals("http://sca.example/dev/api/snap-release/"), method=Equals("POST"), headers=ContainsDict({"Content-Type": Equals("application/json")}), auth=("Macaroon", MacaroonsVerify(root_key)), json_data={ "name": "test-snap", "revision": 1, "channels": ["stable", "edge"], "series": "rolling", }))