Modern ActivityPub compliant server, designed for simplicity and accessibility. Includes calendar, news and sharing economy features to empower your federated community. We spent a year testing this for a hyper local indymedia codebase.
 
 
 
 
 
Go to file
Bob Mottram 994ce34a76 Check for capabilities storage 2019-07-07 16:51:04 +01:00
img Name on logo 2019-07-04 21:56:04 +01:00
LICENSE Initial 2019-06-28 19:55:29 +01:00
Makefile Initial 2019-06-28 19:55:29 +01:00
README.md Random string 2019-07-07 15:34:49 +01:00
acceptreject.py Check for capabilities storage 2019-07-07 16:51:04 +01:00
announce.py Add capabilities to follow requests 2019-07-07 12:53:32 +01:00
auth.py Reduce some line lengths 2019-07-06 18:00:22 +01:00
cache.py Reduce some line lengths 2019-07-06 18:00:22 +01:00
capabilities.py Check for capabilities storage 2019-07-07 16:51:04 +01:00
code-of-conduct.md Add CoC 2019-07-04 22:52:39 +01:00
config.py Configuration file functions 2019-07-05 10:20:54 +01:00
daemon.py Add capabilities to follow requests 2019-07-07 12:53:32 +01:00
epicyon.py Add capabilities to follow requests 2019-07-07 12:53:32 +01:00
follow.py Example json 2019-07-07 14:53:12 +01:00
httpsig.py Fixing public key lookup 2019-07-04 15:36:29 +01:00
inbox.py Check for capabilities storage 2019-07-07 16:51:04 +01:00
like.py Add capabilities to follow requests 2019-07-07 12:53:32 +01:00
person.py Comma 2019-07-05 23:17:06 +01:00
posts.py Add capabilities to follow requests 2019-07-07 12:53:32 +01:00
session.py Add capabilities to follow requests 2019-07-07 12:53:32 +01:00
tests.py Check for capabilities storage 2019-07-07 16:51:04 +01:00
threads.py Move tests to their own file 2019-06-30 21:14:03 +01:00
utils.py Add capabilities to follow requests 2019-07-07 12:53:32 +01:00
webfinger.py Tidying 2019-07-05 17:13:31 +01:00

README.md

A minimal ActivityPub server.

Based on the specification: https://www.w3.org/TR/activitypub

Also: https://raw.githubusercontent.com/w3c/activitypub/gh-pages/activitypub-tutorial.txt

https://blog.dereferenced.org/what-is-ocap-and-why-should-i-care

https://alexcastano.com/what-is-activity-pub

This project is currently pre alpha and not recommended for any real world uses.

Goals

  • A minimal ActivityPub server, comparable to an email MTA.
  • AGPLv3+
  • Server-to-server and client-to-server protocols supported.
  • Implemented in a common language (Python 3)
  • Opt-in federation. Federate with a well-defined list of instances.
  • Keyword filtering.
  • Being able to define roles and skills, similar to the Pursuance project.
  • Sharings collection, similar to the gnusocial sharings plugin
  • Resistant to flooding, hellthreads, etc.
  • Support content warnings, reporting and blocking.
  • http signatures and basic auth.
  • Compatible with http (onion addresses), https and dat.
  • Minimal dependencies.
  • Capabilities based security
  • Data minimization principle. Configurable post expiry time.
  • Commandline interface. If there's a GUI it should be a separate project.
  • Designed for intermittent connectivity. Assume network disruptions.
  • Suitable for single board computers.

Object capabilities workflow

This is one proposed way that OCAP could work.

Default capabilities are initially set up when a follow request is made. The Accept activity sent back from a follow request can be received by any instance. A capabilities accept activity is attached to the follow accept.

                            Alice
                              |
                              V
                        Follow Request
                              |
                              V
                             Bob
                              |
                              V
               Create/store default Capabilities
                          for Alice
                              |
                              V
              Follow Accept + default Capabilities
                              |
                              V
                            Alice
                              |
                              V
                   Store Granted Capabilities

The default capabilities could be any preferred policy of the instance. They could be no capabilities at all, read only or full access to everything.

Example Follow request from Alice to Bob:

{'actor': 'http://alicedomain.net/users/alice',
 'cc': ['https://www.w3.org/ns/activitystreams#Public'],
 'id': 'http://alicedomain.net/users/alice/statuses/1562507338839876',
 'object': 'http://bobdomain.net/users/bob',
 'published': '2019-07-07T13:48:58Z',
 'to': ['http://bobdomain.net/users/bob'],
 'type': 'Follow'}

Follow Accept from Bob to Alice with attached capabilities.

{'actor': 'http://bobdomain.net/users/bob',
 'capabilities': {'actor': 'http://bobdomain.net/users/bob',
                  'capability': ['inbox:write', 'objects:read'],
                  'id': 'http://bobdomain.net/caps/rOYtHApyr4ZWDUgEE1KqjhTe0kI3T2wJ',
                  'scope': 'http://alicedomain.net/users/alice',
                  'type': 'Capability'},
 'cc': [],
 'object': {'actor': 'http://alicedomain.net/users/alice',
            'cc': ['https://www.w3.org/ns/activitystreams#Public'],
            'id': 'http://alicedomain.net/users/alice/statuses/1562507338839876',
            'object': 'http://bobdomain.net/users/bob',
            'published': '2019-07-07T13:48:58Z',
            'to': ['http://bobdomain.net/users/bob'],
            'type': 'Follow'},
 'to': ['http://alicedomain.net/users/alice'],
 'type': 'Accept'}

When posts are subsequently sent from the following instance (server-to-server) they should have the corresponding capability id string attached within the Create wrapper. In the above example that would be http://bobdomain.net/caps/rOYtHApyr4ZWDUgEE1KqjhTe0kI3T2wJ. It should contain a random string which is hard to guess by brute force methods.

                            Alice
                              |
                              V
                          Send Post
	     Attach id from Stored Capabilities
	              granted by Bob
                              |
                              V
                             Bob
                              |
                              V
                 Check Capability id matches
                     stored capabilities
                              |
                              V
               http signature and other checks
                              |
                              V
               Accept or reject incoming post		   

Subsequently Bob could change the stored capabilities for Alice in their database, giving the new object a different id. This could be sent back to Alice, perhaps as another follow Accept activity with attached capabilities. This could then change the way in which Alice can interact with Bob, for example by adding or removing the ability to like or reply to posts.

Object capabilities adversaries

If Eve subsequently learns what the capabilities id is for Alice by somehow intercepting the traffic (eg. suppose she works for Eveflare) then she can't gain the capabilities of Alice due to the scope parameter against which the actors of incoming posts are checked.

Eve could create a post pretending to be from Alice's domain, but the http signature check would fail due to her not having Alice's keys.

The only scenarios in which Eve might triumph would be if she could also do DNS highjacking and:

  • Bob isn't storing Alice's public key and looks it up repeatedly
  • Alice and Bob's instances are foolishly configured to perform blind key rotation such that her being in the middle is indistinguishable from expected key changes

Even if Eve has an account on Alice's instance this won't help her very much unless she can get write access to the database.

Install

sudo pacman -S tor python-pip python-pysocks python-pycryptodome python-beautifulsoup4
sudo pip install commentjson

Running Tests

To run the unit tests:

python3 epicyon.py --tests

To run the network tests. These simulate instances exchanging messages.

python3 epicyon.py --testsnetwork

Viewing Public Posts

To view the public posts for a person:

python3 epicyon.py --posts nickname@domain

If you want to view the raw json:

python3 epicyon.py --postsraw nickname@domain

Account Management

To add a new account:

python3 epicyon.py --addaccount nickname@domain --password [yourpassword]

To remove an account (be careful!):

python3 epicyon.py --rmaccount nickname@domain

To change the password for an account:

python3 epicyon.py --changepassword nickname@domain newpassword

Running the Server

To run with defaults:

python3 epicyon.py

In a browser of choice (but not Tor browser) you can then navigate to:

http://localhost:8085/users/admin

If it's working then you should see the json actor for the default admin account.

For a more realistic installation you can run on a defined domain and port:

python3 epicyon.py --domain [name] --port 8000 --https

You will need to proxy port 8000 through your web server and set up CA certificates as needed.

By default data will be stored in the directory in which you run the server, but you can also specify a directory:

python3 epicyon.py --domain [name] --port 8000 --https --path [data directory]

By default the server will federate with any others. You can limit this to a well-defined list with the --federate option.

python3 epicyon.py --domain [name] --port 8000 --https --federate domain1.net domain2.org domain3.co.uk