Esempio n. 1
0
def create_local_accounts(factories, count, dependencies):
    password = factories["users.User"].build().password
    users = factories["users.User"].build_batch(size=count)
    for user in users:
        # we set the hashed password by hand, because computing one for each user
        # is CPU intensive
        user.password = password
    users = users_models.User.objects.bulk_create(users, batch_size=BATCH_SIZE)
    actors = []
    domain = federation_models.Domain.objects.get_or_create(
        name=settings.FEDERATION_HOSTNAME)[0]
    users = [u for u in users if u.pk]
    private, public = keys.get_key_pair()
    for user in users:
        if not user.pk:
            continue
        actor = federation_models.Actor(private_key=private.decode("utf-8"),
                                        public_key=public.decode("utf-8"),
                                        **users_models.get_actor_data(
                                            user.username, domain=domain))
        actors.append(actor)
    actors = federation_models.Actor.objects.bulk_create(actors,
                                                         batch_size=BATCH_SIZE)
    for user, actor in zip(users, actors):
        user.actor = actor
    users_models.User.objects.bulk_update(users, ["actor"])
    return actors
Esempio n. 2
0
def create_actor(user):
    args = get_actor_data(user)
    private, public = keys.get_key_pair()
    args["private_key"] = private.decode("utf-8")
    args["public_key"] = public.decode("utf-8")

    return federation_models.Actor.objects.create(user=user, **args)
Esempio n. 3
0
def generate_actor(username, **kwargs):
    actor_data = user_models.get_actor_data(username, **kwargs)
    private, public = keys.get_key_pair()
    actor_data["private_key"] = private.decode("utf-8")
    actor_data["public_key"] = public.decode("utf-8")

    return federation_models.Actor.objects.create(**actor_data)
Esempio n. 4
0
def test_can_verify_django_request(factories, fake_request):
    private_key, public_key = keys.get_key_pair()
    signed_request = factories["federation.SignedRequest"](
        auth__key=private_key, auth__headers=["date"])
    prepared = signed_request.prepare()
    django_request = fake_request.get(
        "/", **{
            "HTTP_DATE": prepared.headers["date"],
            "HTTP_SIGNATURE": prepared.headers["signature"],
        })
    assert signing.verify_django(django_request, public_key) is None
Esempio n. 5
0
def test_can_verify_django_request_failure(factories, fake_request, now):
    private_key, public_key = keys.get_key_pair()
    signed_request = factories["federation.SignedRequest"](
        auth__key=private_key, auth__headers=["date"])
    prepared = signed_request.prepare()
    django_request = fake_request.get(
        "/", **{
            "HTTP_DATE":
            http_date((now + datetime.timedelta(seconds=31)).timestamp()),
            "HTTP_SIGNATURE":
            prepared.headers["signature"],
        })
    with pytest.raises(forms.ValidationError):
        signing.verify_django(django_request, public_key)
Esempio n. 6
0
def test_can_verify_django_request_digest_failure(factories, fake_request):
    private_key, public_key = keys.get_key_pair()
    signed_request = factories["federation.SignedRequest"](
        auth__key=private_key,
        method="post",
        data=b"hello=world",
        auth__headers=["date", "digest"],
    )
    prepared = signed_request.prepare()
    django_request = fake_request.post(
        "/", **{
            "HTTP_DATE": prepared.headers["date"],
            "HTTP_DIGEST": prepared.headers["digest"] + "noop",
            "HTTP_SIGNATURE": prepared.headers["signature"],
        })

    with pytest.raises(cryptography.exceptions.InvalidSignature):
        signing.verify_django(django_request, public_key)
Esempio n. 7
0
def test_authenticate(factories, mocker, api_request):
    private, public = keys.get_key_pair()
    factories["federation.Domain"](name="test.federation",
                                   nodeinfo_fetch_date=None)
    actor_url = "https://test.federation/actor"
    mocker.patch(
        "funkwhale_api.federation.actors.get_actor_data",
        return_value={
            "@context": jsonld.get_default_context(),
            "id": actor_url,
            "type": "Person",
            "outbox": "https://test.com",
            "inbox": "https://test.com",
            "followers": "https://test.com",
            "preferredUsername": "******",
            "publicKey": {
                "publicKeyPem": public.decode("utf-8"),
                "owner": actor_url,
                "id": actor_url + "#main-key",
            },
        },
    )
    update_domain_nodeinfo = mocker.patch(
        "funkwhale_api.federation.tasks.update_domain_nodeinfo")

    signed_request = factories["federation.SignedRequest"](
        auth__key=private,
        auth__key_id=actor_url + "#main-key",
        auth__headers=["date"])
    prepared = signed_request.prepare()
    django_request = api_request.get(
        "/", **{
            "HTTP_DATE": prepared.headers["date"],
            "HTTP_SIGNATURE": prepared.headers["signature"],
        })
    authenticator = authentication.SignatureAuthentication()
    user, _ = authenticator.authenticate(django_request)
    actor = django_request.actor

    assert user.is_anonymous is True
    assert actor.public_key == public.decode("utf-8")
    assert actor.fid == actor_url
    update_domain_nodeinfo.assert_called_once_with(
        domain_name="test.federation")
Esempio n. 8
0
def test_authenticate_skips_blocked_actor(factories, api_request):
    policy = factories["moderation.InstancePolicy"](block_all=True,
                                                    for_actor=True)
    private, public = keys.get_key_pair()
    actor_url = policy.target_actor.fid

    signed_request = factories["federation.SignedRequest"](
        auth__key=private,
        auth__key_id=actor_url + "#main-key",
        auth__headers=["date"])
    prepared = signed_request.prepare()
    django_request = api_request.get(
        "/", **{
            "HTTP_DATE": prepared.headers["date"],
            "HTTP_SIGNATURE": prepared.headers["signature"],
        })
    authenticator = authentication.SignatureAuthentication()

    with pytest.raises(exceptions.BlockedActorOrDomain):
        authenticator.authenticate(django_request)
Esempio n. 9
0
def test_autenthicate_supports_blind_key_rotation(factories, mocker,
                                                  api_request):
    actor = factories["federation.Actor"]()
    actor_url = actor.fid
    # request is signed with a pair of new keys
    new_private, new_public = keys.get_key_pair()
    mocker.patch(
        "funkwhale_api.federation.actors.get_actor_data",
        return_value={
            "@context": jsonld.get_default_context(),
            "id": actor_url,
            "type": "Person",
            "outbox": "https://test.com",
            "inbox": "https://test.com",
            "followers": "https://test.com",
            "preferredUsername": "******",
            "publicKey": {
                "publicKeyPem": new_public.decode("utf-8"),
                "owner": actor_url,
                "id": actor_url + "#main-key",
            },
        },
    )
    signed_request = factories["federation.SignedRequest"](
        auth__key=new_private,
        auth__key_id=actor_url + "#main-key",
        auth__headers=["date"],
    )
    prepared = signed_request.prepare()
    django_request = api_request.get(
        "/", **{
            "HTTP_DATE": prepared.headers["date"],
            "HTTP_SIGNATURE": prepared.headers["signature"],
        })
    authenticator = authentication.SignatureAuthentication()
    user, _ = authenticator.authenticate(django_request)
    actor = django_request.actor

    assert user.is_anonymous is True
    assert actor.public_key == new_public.decode("utf-8")
    assert actor.fid == actor_url
Esempio n. 10
0
def test_authenticate_checks_signature_with_allow_list(preferences, factories,
                                                       api_request):
    preferences["moderation__allow_list_enabled"] = True
    domain = factories["federation.Domain"](allowed=False)
    private, public = keys.get_key_pair()
    actor_url = "https://{}/actor".format(domain.name)

    signed_request = factories["federation.SignedRequest"](
        auth__key=private,
        auth__key_id=actor_url + "#main-key",
        auth__headers=["date"])
    prepared = signed_request.prepare()
    django_request = api_request.get(
        "/", **{
            "HTTP_DATE": prepared.headers["date"],
            "HTTP_SIGNATURE": prepared.headers["signature"],
        })
    authenticator = authentication.SignatureAuthentication()

    with pytest.raises(exceptions.BlockedActorOrDomain):
        authenticator.authenticate(django_request)
Esempio n. 11
0
def test_authenticate_ignore_inactive_policy(factories, api_request, mocker):
    policy = factories["moderation.InstancePolicy"](block_all=True,
                                                    for_domain=True,
                                                    is_active=False)
    private, public = keys.get_key_pair()
    actor_url = "https://{}/actor".format(policy.target_domain.name)

    signed_request = factories["federation.SignedRequest"](
        auth__key=private,
        auth__key_id=actor_url + "#main-key",
        auth__headers=["date"])
    mocker.patch(
        "funkwhale_api.federation.actors.get_actor_data",
        return_value={
            "@context": jsonld.get_default_context(),
            "id": actor_url,
            "type": "Person",
            "outbox": "https://test.com",
            "inbox": "https://test.com",
            "followers": "https://test.com",
            "preferredUsername": "******",
            "publicKey": {
                "publicKeyPem": public.decode("utf-8"),
                "owner": actor_url,
                "id": actor_url + "#main-key",
            },
        },
    )
    prepared = signed_request.prepare()
    django_request = api_request.get(
        "/", **{
            "HTTP_DATE": prepared.headers["date"],
            "HTTP_SIGNATURE": prepared.headers["signature"],
        })
    authenticator = authentication.SignatureAuthentication()
    authenticator.authenticate(django_request)
    actor = django_request.actor

    assert actor.public_key == public.decode("utf-8")
    assert actor.fid == actor_url