Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DONE] Yaal Coop/Add ActivityPub functionality #1170

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from

Conversation

LoanR
Copy link
Contributor

@LoanR LoanR commented Jun 27, 2024

New configuration

  • USE_ACTIVITYPUB: bool
  • DEFAULT_AP_THUMBNAIL: default ActivityPub thumbnail in png format (there is a svg default format but it is currently not allowed by Peertube)

ActivityPub signature

Full documentation about ActivityPub requests signatures can be found pod/activitypub/README.md -> new public and private keys are needed for ActivityPub to work pod/activitypub/ap.key pod/activitypub/ap.pub.

Requirements before running container

You need to run migrations for the new ActivityPub models Follower, Following, ExternalVideo and for some changes in Video model.

ElasticSearch index needs also to be rebuilt: id was a long number, it is now a keyword, and is_external is a new boolean.

Local testing

docker-compose-full-dev-with-volumes.yml now launches a Peertube instance available on peertube.localhost:9000 for testing purpose.

To be able to use a local version, from previous builds, the Site object must be changed on Django admin to point on pod.localhost:8000.

You can federate to an instance by adding its url in Django admin, Following then Send the federation request action.
To get existing videos via ActivityPub of a followed instance, you also need to Reindex the instance videos.

@LoanR LoanR changed the base branch from master to develop June 27, 2024 13:14
Copy link

gitguardian bot commented Jun 27, 2024

️✅ There are no secrets present in this pull request anymore.

If these secrets were true positive and are still valid, we highly recommend you to revoke them.
Once a secret has been leaked into a git repository, you should consider it compromised, even if it was deleted immediately.
Find here more information about risks.


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

@LoanR LoanR force-pushed the activitypub branch 3 times, most recently from b2e297c to c06326f Compare June 28, 2024 15:02
@Badatos
Copy link
Collaborator

Badatos commented Jun 28, 2024

Bonjour,

Si vous êtes certains que les "secrets" détectés par GitGuardian n'en sont pas, je vous invite à insérer les variables à ignorer dans un cartouche de ce type :

# ggignore-start
# gitguardian:ignore
# Generate one using `openssl rand -hex 32`
 PEERTUBE_SECRET=804061c0547350xxxxx
# ggignore-end

Ou pour éviter que toutes les configurations laissées par défaut partagent le même secret, mettez

# Generate one using `openssl rand -hex 32`
PEERTUBE_SECRET=TO_CHANGE

@SebastienCozeDev
Copy link
Contributor

La migration de develop vers activitypub fonctionnement correctement pour les vidéos 👍

@ptitloup
Copy link
Contributor

Bonjour,
Est-ce possible de terminer cette PR pour ce vendredi svp ?
Merci

@LoanR
Copy link
Contributor Author

LoanR commented Jul 10, 2024

Je pense que ça va être compliqué de s'engager sur une livraison vendredi... Il nous reste des ajustements à faire et je suis en arrêt pour covid...
Je pense que ce sera plus raisonnable pour un autre jour. Une release est prévue à la fin de la semaine ?

@ptitloup
Copy link
Contributor

nous prévoyons en effet une 3.8 pour mercredi prochain. Nous voulions avoir le temps de faire les review et test fonctionnel de votre contribution.
Quel serait votre délais de réalisation ?

@ptitloup
Copy link
Contributor

Vous pouvez mettre à jour votre branche depuis develop pour recupérer la dernière version de pod et fixer les conflits

@LoanR LoanR marked this pull request as draft July 11, 2024 08:21
@LoanR LoanR force-pushed the activitypub branch 2 times, most recently from 3233327 to b957ed5 Compare July 11, 2024 10:37
@LoanR LoanR changed the title [WIP] Yaal Coop/Add ActivityPub functionnality [WIP] Yaal Coop/Add ActivityPub functionality Jul 11, 2024
@LoanR LoanR force-pushed the activitypub branch 6 times, most recently from 7a90a1b to 2a45f72 Compare July 11, 2024 14:20
@LoanR
Copy link
Contributor Author

LoanR commented Jul 11, 2024

Hello @Badatos ,

Concernant GitGuardian, j'ai tenté :

Localement, le précommit GitGuardian ne renvoie pas d'incidents.

Mais la CI échoue toujours sur ces deux variables...
Est-ce que le GitGuardian du projet est configuré pour ignorer la conf ?
Est-ce qu'il faut signaler cette conf ailleurs ?
J'ai l'impression d'avoir pourtant reproduit ce que j'ai pu trouver comme cas similaires dans le code...

@ptitloup
Copy link
Contributor

Petite question, mise à part les gitguardian, est-ce que la PR est terminée ? si oui, pouvez-vous la passer en DONE qu'on puisse review svp ? Merci !

@LoanR
Copy link
Contributor Author

LoanR commented Jul 11, 2024

Non, je pense que la PR ne sera pas terminée avant la release...
On pourrait avoir une bonne surprise, dans ce cas là, je préviendrai, mais je n'y crois pas trop.

@ptitloup
Copy link
Contributor

ha ok, comme la PR passait les tests, je le croyais mais pas grave !

@LoanR
Copy link
Contributor Author

LoanR commented Nov 12, 2024

Super pour la commande. On a dû oublier d'enlever ces lignes qui nous aidaient en local...

Bizarre, il y a pourtant bien un fichier pod/activitypub/tasks.py...

@Badatos
Copy link
Collaborator

Badatos commented Nov 12, 2024

En effet ! l'erreur vient en fait un peu plus bas :

File "/web/django_projects/pod-prod/pod/activitypub/tasks.py", line 16, in <module>
    CELERY_TASK_ALWAYS_EAGER = getattr(settings, "CELERY_TASK_ALWAYS_EAGER", False)
  File "/home/pod/.virtualenvs/django_prepod/lib/python3.10/site-packages/django/conf/__init__.py", line 82, in __getattr__
    self._setup(name)
  File "/home/pod/.virtualenvs/django_prepod/lib/python3.10/site-packages/django/conf/__init__.py", line 63, in _setup
    raise ImproperlyConfigured(
django.core.exceptions.ImproperlyConfigured: Requested setting CELERY_TASK_ALWAYS_EAGER, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.

@LoanR
Copy link
Contributor Author

LoanR commented Nov 12, 2024

Ah, oui, c'est pour ça qu'il y a cette première ligne dans my-entrypoint-activitypub.sh :
env DJANGO_SETTINGS_MODULE=pod.settings
Pour indiquer où se trouve la configuration.

@Badatos
Copy link
Collaborator

Badatos commented Nov 12, 2024

OOOOK ! :)
J'ai donc fait ceci :

export DJANGO_SETTINGS_MODULE="pod.settings"
celery --app pod.activitypub.tasks worker --loglevel INFO --queues activitypub --concurrency 1 --hostname activitypub

Et cette fois, les requêtes partent bien !! ;) Merci pour l'aide.
(bon, ok, je ne recois que des 403 forbidden des différents peertubes, mais c'est un autre probleme ^^.)

Reste maintenant à trouver comment mettre ce worker celery en place en tant que service...

@LoanR
Copy link
Contributor Author

LoanR commented Nov 12, 2024

Je pousse un correctif sur cet entrypoint et sur la doc

@LoanR
Copy link
Contributor Author

LoanR commented Nov 12, 2024

J'imagine qu'il faudra mettre cette doc à jour pour ajouter la partie ActivityPub : https://www.esup-portail.org/wiki/display/ES/Gestion+de+l%27encodage%2C+de+la+transcription+et+de+l%27xAPI

@Badatos
Copy link
Collaborator

Badatos commented Nov 12, 2024

J'ai essayé de documenter ce que j'ai fait ici :
https://www.esup-portail.org/wiki/display/ES/Mise+en+place+du+protocole+ActivityPub+sur+le+serveur+d%27encodage

Si vous voyez une erreur n'hésitez-pas ;)

Je m'interroge tout de meme sur le fait de devoir ajouter la ligne export DJANGO_SETTINGS_MODULE="pod.settings" au script pour que cela fonctionne, ca m'embete un peu, surtout que pour les autres taches celery ce n'est pas nécessaire.

Peut-être serait-il plus simple d'ajouter les lignes suivantes directement dans la tache :

import os
# Set the default Django settings module for the 'celery' program.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'proj.settings')

... tel que c'est recommandé dans la doc Celery (https://docs.celeryq.dev/en/latest/django/first-steps-with-django.html#django-first-steps)

Ca simplifierait la doc d'installation, et éviterait de potentielles erreurs.

@LoanR
Copy link
Contributor Author

LoanR commented Nov 12, 2024

Je pense qu'il y a un copié collé malheureux au niveau de la configuration à ajouter dans la config pour l'installation sur le serveur d'encodage, ce sont les variables pour xAPI.

J'ai poussé les corrections !

@Badatos
Copy link
Collaborator

Badatos commented Nov 12, 2024

Bien vu ! je corrige la doc.
Et merci pour les modifs ;)

@Badatos
Copy link
Collaborator

Badatos commented Nov 20, 2024

Bonjour @LoanR,
Je dispose maintenant de 2 serveurs Pod sur la branche ActivityPub :

  • pod-test.univ-cotedazur.fr (serveur de pré-prod)
  • pod.localhost:8000 (docker local)

Je tente d'ajouter le 1er dans les "followings" du 2e. Au début, cela fonctionne : le statut passe bien en Following request sent, mais ça ne va pas plus loin, et rien n'apparait dans les "Followers" du 1er serveur. Est-ce que j'ai loupé une étape ?

Ci-dessous le log du conteneur pod-activitypub-with-volumes :

[2024-11-20 13:43:03,376: INFO/MainProcess] Task pod.activitypub.tasks.task_follow[7c42d708-790f-4552-9f61-xxxx] received
[2024-11-20 13:43:03,922: WARNING/ForkPoolWorker-1] Posting to AP endpoint: http://pod-test.univ-cotedazur.fr/ap/inbox
{
 "@context": [
  "https://www.w3.org/ns/activitystreams",
  "https://w3id.org/security/v1",
  {
   "RsaSignature2017": "https://w3id.org/security#RsaSignature2017"
  }
 ],
 "type": "Follow",
 "id": "http://pod.localhost:8000/ap/following/1",
 "actor": "http://pod.localhost:8000/ap",
 "object": "http://pod-test.univ-cotedazur.fr/ap"
}
[2024-11-20 13:43:17,830: INFO/ForkPoolWorker-1] Task pod.activitypub.tasks.task_follow[7c42d708-790f-4552-9f61-xxxx] succeeded in 14.442281448000358s: False

@Badatos
Copy link
Collaborator

Badatos commented Nov 20, 2024

Côté serveur n°1, la requête est bien arrivée mais a déclenché une erreur :

TypeError at /ap/inbox
'NoneType' object is not subscriptable

Request Method: GET
Request URL: https://pod-test.univ-cotedazur.fr/ap/inbox

Exception Location: 	./pod/activitypub/views.py, line 137, in inbox

            data["type"] in ("Announce", "Update", "Delete")

==> il semble que data soit None. Il doit manquer une vérif ici.

@LoanR
Copy link
Contributor Author

LoanR commented Nov 20, 2024

Dans les logs du serveur n°1, on devrait avoir un warning juste avant cette erreur qui est un dump du contenu de la requête ActivityPub, quelque chose commençant par inbox query: (voir ici)
Quel est ce contenu ?

@Badatos
Copy link
Collaborator

Badatos commented Nov 20, 2024

Dans les logs du serveur n°1, on devrait avoir un warning juste avant cette erreur qui est un dump du contenu de la requête ActivityPub, quelque chose commençant par inbox query: (voir ici) Quel est ce contenu ?

Le dump en question n'a rien a afficher quand data = None

@LoanR
Copy link
Contributor Author

LoanR commented Nov 20, 2024

Étrange, c'est comme si la requête arrivait bien sur le serveur 2, mais sans contenu...

@Badatos
Copy link
Collaborator

Badatos commented Nov 20, 2024

L'objet "Following" que j'ai créé sur le serveur 2 a comme url https://pod-test.univ-cotedazur.fr (en https), mais dans les log on trouve ceci :
Posting to AP endpoint: http://pod-test.univ-cotedazur.fr/ap/inbox

Est-ce voulu que le https soit converti en http ?

@Badatos
Copy link
Collaborator

Badatos commented Nov 20, 2024

J'ai l'impression que la fonction make_url ne devrait pas pas ajouter "https" uniquement quand SECURE_SSL_REDIRECT est True, car ca empeche un serveur HTTP de contacter un serveur HTTPS

@LoanR
Copy link
Contributor Author

LoanR commented Nov 20, 2024

Bonne piste, soit il y a effectivement un problème avec http en local et https en prod, ou alors le well-known n'envoie pas la bonne url... ⏳

@Badatos
Copy link
Collaborator

Badatos commented Nov 20, 2024

En effet :
https://pod-test.univ-cotedazur.fr/.well-known/nodeinfo

{
"links": [{"rel": "http://nodeinfo.diaspora.software/ns/schema/2.0",
 "href": "http://pod-test.univ-cotedazur.fr/nodeinfo/2.0.json"},
{"rel": "https://www.w3.org/ns/activitystreams#Application",
 "href": "http://pod-test.univ-cotedazur.fr/ap"}]}

@Badatos
Copy link
Collaborator

Badatos commented Nov 20, 2024

On avance :)
J'ai donc mis le paramètre "SECURE_SSL_REDIRECT" du serveur pod-test à True, et cette fois le nodeinfo est correct, la tache "follow" renvoit enfin "True" :

Task pod.activitypub.tasks.task_follow[efd84c95-f4a5-4969-9a3f-xxx] succeeded in 13.38195166200012s: True

... Mais toujours aucun "Follower" n'apparait sur pod-test :/

@LoanR
Copy link
Contributor Author

LoanR commented Nov 20, 2024

Le dump de data est toujours à None ?

@Badatos
Copy link
Collaborator

Badatos commented Nov 21, 2024

Lorsque le serveur 2 envoie une requete "follow" au serveur 1, voici ce qui apparait dans les requetes du serveur 1 :

[21/Nov/2024:09:50:04 +0100] "GET /.well-known/nodeinfo HTTP/1.1" 200 246 "-" "python-requests/2.32.0"
[21/Nov/2024:09:50:04 +0100] "GET /ap HTTP/1.1" 200 1234 "-" "python-requests/2.32.0"
[21/Nov/2024:09:50:17 +0100] "POST /ap/inbox HTTP/1.1" 204 0 "-" "python-requests/2.32.0"

La dernière requete "/ap/inbox" est en HTTP 204 No Content, c'est normal ?

@Badatos
Copy link
Collaborator

Badatos commented Nov 21, 2024

Voici le data dump :

inbox query: {
 "@context": [
  "https://www.w3.org/ns/activitystreams",
  "https://w3id.org/security/v1",
  {
   "RsaSignature2017": "https://w3id.org/security#RsaSignature2017"
  }
 ],
 "type": "Follow",
 "id": "http://pod.localhost:8000/ap/following/1",
 "actor": "http://pod.localhost:8000/ap",
 "object": "https://pod-test.univ-cotedazur.fr/ap",
 "signature": {
  "type": "RsaSignature2017",
  "creator": "http://pod.localhost:8000/ap",
  "created": "2024-11-21T09:21:49.758230+00:00",
  "signatureValue": "JDMf0B8wp4KKSK4/c6eSIdGUxtZniFqMDD+BzJtz8iVQYmCw5iUj3nW1MJO1fGQ1ZSnSKMFeBw5LOX4ojCnjTShRybXl4d9xmWVPBqqV6/oPIUA1AD0+MGRLXfnECLHSv23WNyagJlbemlV9Gq7/ks7sJ3KMddi6Bj0NM3CrvvA2xgZQsOnmx1gwTwNrG+4zI8bZNlhmvHZCJ5qxshLstiF9+LQf24Lldp08y7LXIIOpC9hmEKtuo/0ApAQKufg4AE1X5plpg6D+h1tqPKkumzBwYFHbuC9pVpR4EsK+Rr8gjCJdN16JvSwFKswEE7f7JMQkiaAJvNmN22EuBWgZng=="
 }
} 

@LoanR
Copy link
Contributor Author

LoanR commented Nov 21, 2024

Je pense qu'avec un pod dans un conteneur en local ça ne peut pas fonctionner. J'explique ce que je pense qu'il se passe :

  • pod.localhost:8000 envoie une activité follow vers pod-test.univ-cotedazur.fr
  • pod-test.univ-cotedazur.fr reçoit bien cette requête avec les bonnes data.
  • pour poursuivre, pod-test.univ-cotedazur.fr doit récupérer un certain nombre d'informations sur l'actor, il fait donc une requête sur l'url de l'actor, dans notre cas http://pod.localhost:8000/ap
  • cette url ne répond pas, on se retrouve avec des data à None, la demande de follow échoue.

Pour pouvoir aller plus loin, il faudrait avoir deux instances de pod accessibles l'une pour l'autre. Donc une autre instance de test, ou bien utiliser un service comme ngrok pour avoir une url pour le pod local dockerisé accessible depuis le web.

@Badatos
Copy link
Collaborator

Badatos commented Nov 21, 2024

Ok, merci pour les infos !
Attendons donc d'avoir un 2e serveur Pod sous activitypub pour la suite des tests.

En attendant, je vous invite tout de même à modifier la ligne 136 du fichier views.py :
Avant :

if (
        data["type"] in ("Announce", "Update", "Delete")
        and not settings.TEST_SETTINGS
        and not check_signatures(request)
    ):
        return HttpResponse("Signature could not be verified", status=403)

Après :

if (
        data is None or 
        (data["type"] in ("Announce", "Update", "Delete")
        and not settings.TEST_SETTINGS
        and not check_signatures(request))
    ):
        return HttpResponse("Signature could not be verified", status=403)

Ca évitera de déclencher une Exception quand data est None.

@LoanR
Copy link
Contributor Author

LoanR commented Nov 21, 2024

J'ai 'ajouté un try except pour clarifier et logger les erreurs.

@LoanR
Copy link
Contributor Author

LoanR commented Dec 10, 2024

J'ai rebase sur develop, il y avait un conflit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants