Documentation
Generated from trident:doc/Trident.mdTrident
Trident is a Trusted Information Exchange Toolkit.
This is the upcoming new iteration of code that runs Ops-Trust and a variety of other instances.
The Trident database and functionality are based on the Portal code, but Trident is a full redesign and from scratch rewrite in Go.
Useful links: * Trident Website * GitHub * Email * Twitter
License
Trident is placed under the Apache Version 2.0 License.
Components
This section briefly describes the components inside Trident.
tridentd
tridentd
is the Trident Daemon. It runs in the background and
published a webserver on localhost
and port 8333
.
This HTTP-based webserver provides an /api/
URL for
Trident API calls and the rest of the exported details consist
of the Trident web interface.
The tridentd webservice can be published to the general Internet by using a HTTP proxy like Nginx or Apache and forwarding the correct requests to it.
tridentd contains all the logic in Trident and is the tool that talks to the Database. All commands are routed throug tridentd. Permission handling is thus checked by tridentd.
Configuration for tridentd is stored in /etc/trident/trident.conf
.
This file should only be readable by tridentd which runs under the trident
user account.
Trident API
The API is available under /api/
.
The API is always accessible from localhost
, it can be limited
for publishing to other hosts with the API_Enabled
config option.
Authentication is done using JSON Web Tokens.
One can retrieve a token by using the system login
command.
This is compatible with the OAuth2 protocol.
(XXX: Todo - further specification to follow)
Web CLI
The Web CLI under /cli/
allows access to a simple HTML form that
can be used to type in custom commands, in a similar way of using
the tcli
command.
OAuth2 / OpenID Connect
Trident allows external sites to verify and authenticate that the user is an authorized user of the Trident installation.
Wiki
The Wiki built-in to Trident can operate either in no-javascript mode, where a simple HTML textarea is used to edit the Markdown, or a very nice inline editor that has direct Preview of what is being edited.
The Wiki format is the standard Markdown with SmartyPants GitHub Flavored Markdown extensions.
Before providing the rendered HTML to the user it is sanitized using Blue Monday Sanitizer thus avoiding inline javascript and other possible XSS options.
Due to use of two different Markdown engines (EpicEditor’s “marked” and Black Friday) and then filtering through Blue Monday some inconsistencies between the preview and the final output are to be expected. The “Source” tab can be used to identify such differences.
Differences between pages can be seen using the History tab.
A Table of Contents is automatically generated from the headers of a page.
The Child Pages tab can be seen used to list all the sub pages for that Page.
Formatting Examples
Headers
First Level Header (h1)
=======================
Double Underlined
Second Level Header (h2)
------------------------
Single Underlined
# First Level Header (h1)
First Paragraph text
## Second Level Header (h2)
Second Paragraph text
### Third Level Header (h3)
Third Paragraph text
Emphasis
*Italic characters*
_Italic characters_
**bold characters**
__bold characters__
~~strikethrough text~~
Tables
| Column One | Column Left | Column Right |
|--------------|:------------|-------------:|
| Value 1 | Value One | 10 |
| Value Two | Value 2 | 200 |
| Value Three | Value 3 | 300 |
Unordered Lists
* Item One
* Item Two
* Item Two Sub 1
* Item Two Sub 2
* Item Three
Ordered Lists
1. Item 1
2. Item 2
a. Item 2a
b. Item 2b
3. Item 3
Code Examples
Either indent with four spaces or ```
```
function test()
{
test
}
```
With formatting:
#include <stdio.h>
int main(void)
{
printf(stdout, "Hello World");
}
Links
[WikiPage](WikiPage/)
[WikiPage](WikiPage/)
[External Site](https://example.net)
[Email Address](mailto:user@example.net)
trident arguments
The following arguments can be provided in DAEMON_OPTS
setting of /etc/default/trident
or as arguments directlya to the tridentd binary.
Argument | Description |
---|---|
–config | Configuration File Directory |
–syslog | Log to syslog (also enabled when –daemonize is given) |
–daemonize | Daemonize tridentd |
–pidfile | PID File (useful in combo with daemonize) |
–username | Username to daemonize into |
Following arguments should only used during testing or development and not on a production system:
Argument | Description |
---|---|
–debug | Enable verbose Debug output |
–insecurecookies | Disables the HTTP requirement for cookies |
–disabletwofactor | Disable Two Factor Authentication Check |
–verbosedb | Log all SQL Queries |
tcli
tcli
is the Trident CLI. It is in effect a simple HTTP client that speaks directly to the API of tridentd.
As in the Web CLI typing tcli help
will provide details on available commands.
tcli stores its JSON Web Token (JWT) authentication token in ~/.trident_token
.
tcli
is pronounced as “Tickly”.
tsetup
tsetup
is the Trident Setup command. It helps in configuring the
PostgreSQL database and in upgrading schemas where needed.
This command must be run from the postgres
user account or
another account having unix-loopback PostgreSQL administrative capabilities.
To add a user to the system use (as user postgres
):
tsetup adduser <username> <password>
Note that the username
must be lowercase letters, and numbers, but the first character may not be a number.
This has to used to add an initial administrative (sysadmin
) user after
which tcli
or the Trident UI can be used to configure the rest of the system.
Directories
Directory | Permissions | Description |
---|---|---|
/etc/trident/ |
755 root:root | Trident Configuration |
/usr/share/trident/ |
755 root:root | Read-only files (templates, dbschemas, webroot) |
/var/lib/trident/ |
700 trident:trident | Trident intermediary files |
Installation
Debian packaging is provided (use ‘dpkg-buildpackage -b -uc -us’ to create. FreeBSD packaging might follow at a later date.
Trident requires PostgreSQL 9.1+ as a database and Postfix for SMTP.
Trident prefers to be run behind Nginx or another HTTP proxy providing HTTPS access. This avoids having Trident needing to know any SSL keys.
Trident should only be exposed to the outside world using HTTPS. Thus do not send your details in cleartext HTTP.
One can also run Trident directly from source, see the Development section for more details.
After installing the Trident package one has to edit /etc/trident/trident.conf
and
provide the correct database details (See Database Setup in the next sections).
The package automatically generates new RSA keys used for the JSON Web Token (JWT) that are used for authentication at package installation time ensuring that every installation has unique JWTs.
Quick and Dirty
The quick and dirty method of installing Trident:
apt-get install postgresql nginx postfix
dpkg -i trident-VERSION.deb
# edit /etc/trident/trident.conf
su - postgres -c "/usr/sbin/tsetup setup_db"
su - postgres -c "/usr/sbin/tsetup adduser USERNAME PASSWORD"
Then configure postfix + nginx as per details below.
Actual details about these commands can be found in the more specific sections of this document.
Database Setup
Depending on having a local or remote database one has to follow the next two sections.
Local Database
Either have the PostgreSQL server package installed before installing the Trident package
or make sure that the postgres
user is in the trident
group with:
adduser postgres trident
This allows the postgres user to read /etc/trident/trident.conf
and thus retrieve
the configuration settings needed for the database details.
As this is a local Database we can use peer authentication /etc/trident/trident.conf
should have:
"db_host": "/var/run/postgresql/",
"db_port": "5432",
"db_name": "trident",
"db_user": "trident",
"db_pass": "",
The package performs that if the postgres server is installed at the time the Trident package is installed.
To create the database and the users that access it one can just run:
su - postgres -c "/usr/sbin/tsetup setup_db"
This will create the trident
PostgreSQL user and the trident
database.
Remote Database
Likely easiest is to temporarily install Trident on the
remote server and then run tsetup
like normal and
then after setup_db
to remove the package from the server.
In a nutshell what needs to be done:
* Create the trident
user on the remote server.
* Create the trident
database on the remote server.
* Provide permissions for the user to access the database.
* Check that pg_ha.conf
contains the correct settings.
* Ensure reachability of the port (firewalling, listener etc).
* Configure /etc/trident/trident.conf
correctly.
* Run tsetup
from the remote server as normal.
As this is a remote Database we must use md5 authentication /etc/trident/trident.conf
should have:
"db_host": "db.trident.example.net",
"db_port": "5432",
"db_name": "trident",
"db_user": "trident",
"db_pass": "trident",
Database Security
Trident’s tsetup
configures the postgres user to be the owner of the database.
The trident
user only has access to SELECT
, UPDATE
,
INSERT
and DELETE
on the various tables.
Database Versions
The share/dbschemas/
directory contains files that describe the
Trident Database Schema.
Each DB change will be codified in a migration. Migrations with assigned
versions will be named DB_<version>.psql
. Where the version is the current
version of the database at the time that the given file should be applied.
For example if the current version is 3 and you would like to make a change to
the schema, set the name of the file to DB_3.psql
. Your update will set the
database version to 4 as it’s last action.
The contents of the migration are in the form of a PSQL file. All activity
should be within a transaction (BEGIN
, COMMIT
).
his is so that if the update fails in any way, no update will occur.
Database permissions (read: GRANTS
) are managed by Trident itself,
these should not be given/revoked in these scripts.
Member States
(XXX: this section is out of date, see state_mon and schema.psql for truth.)
The following member states exist:
State | Description |
---|---|
nominated | means somebody has nominated you but you don’t know yet. |
vetted | means you’ve been invouched and you still don’t know about it |
approved | will someday mean that admin@ has noted your vettedness and noted the absence of controversy about you. Right now you just go from vetted to approved immediately (criteria is identical.) |
active | means you’ve done everything you need to do and the system is not sending you any annoy-o-grams about your checklist |
inactive | means you used to be approved but lost your pgp key or lost a vouch or the vouch criteria was raised and now excludes you |
blocked | means somebody negvouched you and there’s an investigation. |
idle | means it’s been X days (imagine “60”) since you either logged into the UI or sent e-mail to one of the lists. |
soonidle | means you will soon be “idle” (we send mail warning of this so that you can log into the portal and prevent going idle.) |
failed | means your nomination timed out without reaching “vetted” |
On this table the rows are membership states and the columns are member capabilities/permissions.
state | can_login | can_see | can_send | can_recv | blocked | hidden |
---|---|---|---|---|---|---|
nominated | false | false | false | false | false | false |
vetted | false | false | false | false | false | false |
approved | true | true | false | false | false | false |
active | true | true | true | true | false | false |
inactive | true | true | true | false | false | false |
blocked | false | false | false | false | true | true |
failed | false | false | false | false | false | true |
soonidle | true | true | true | true | false | false |
idle | true | true | true | false | false | false |
deceased | false | false | false | false | true | false |
Transitions:
From | To | Description |
---|---|---|
NULL | nominated | When somebody nominates you, and mail is sent to vetting@ asking that folks check you out |
nominated | vetted | When a cron job detects that you have enough invouches (target_invouches), and notifies admin@ about this) |
vetted | approved | When an admin notes that there are no negvouches and manually slots you into “approved” status, and you finally hear for the first time that you are a member, or if that’s not implemented yet, it’s when a cron job notices that you’ve been vetted and automatically approves you |
approved | active | when a cron job detects that you’re approved but that you need to input a pgp (if that’s required) and outvouch (if that’s required) |
active | inactive | When you lose your pgp key or it’s suddenly required, or when you used to have enough invouches (min_invouches) but now you don’t.) |
inactive | active | When a cron job detects that you’ve outvouched and input a pgp key, and notifies by e-mail you about this |
ANY | blocked | When an admin wants the system to camp onto your e-mail address and not allow further state changes or new nominations) |
active | soonidle | When a cron job detects that you have not logged in or sent mail for some significant period of time, and sends you mail telling you that you will soon be idle.) |
soonidle | active | When you log back into the UI or transmit to a mailinglist. |
soonidle | idle | When you go a few more days without activity after being told you will soon be idle |
idle | active | Same as soonidle -> active |
Member permissions
Permission | Description |
---|---|
can_login | means your password works at the main web portal UI |
can_see | means you can see the membership list and other primary materials, including the wiki |
can_send | means you’re allowed to send mail to the non-public-access mailing lists |
can_recv | means you can receive mail to the subscription-checkbox mailing lists |
blocked | means you can’t be nominated, nor log in, nor receive or send e-mail, nor be seen |
Webserver setup
Following sections detail how to configure the webserver (HTTP Proxy).
Nginx
The directories doc/conf/nginx/
(source) or /etc/trident/nginx/
(when installed from Debian package) contain Nginx configuration includes
for enabling Trident behind a Nginx server.
Drop the following in /etc/nginx/conf.d/trident.conf
and of course, change as needed/wanted.
Items to change at minimum:
* Hostname [trident.example.net
]
* SSL keys, referenced, but files are not included in this example
* SSL Options
* HTTP Key Pinning
Definitely verify the configuration with the Qualsys SSL Test: https://www.ssllabs.com/
Example /etc/nginx/conf.d/trident.conf
or /etc/nginx/sites-available/
depending on preference.
# The Trident Daemon Upstream
include /etc/trident/nginx/trident-upstream.inc;
# Redirect all HTTP (80) traffic to HTTPS (443)
# Trident should only be exposed over HTTPS
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _default_;
rewrite ^ https://$host$request_uri permanent;
}
# The HTTPS (443) server that exposed Trident
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name trident.example.net;
ssl_certificate trident.crt;
ssl_certificate_key trident.key;
ssl_prefer_server_ciphers on;
# And other SSL options, recommended:
# - ssl_dhparam
# - ssl_protocols
# - ssl_ciphers
# See https://cipherli.st/ for details
# STS header
add_header Strict-Transport-Security "max-age=31536001";
# HTTP Key Pinning
add_header Public-Key-Pins "Public-Key-Pins: max-age=5184000; pin-sha256=\"...\""
access_log /var/log/nginx/trident-access.log;
# Include the config for making Trident work
include /etc/trident/nginx/trident-server.inc;
}
E-mail setup
Trident can be run behind both Postfix and Sendmail or likely other SMTP servers.
We provide details for configuring behind Postfix in the next section.
Postfix
Postfix is used as an inbound email setup. This handles all SMTP specific things like STARTTLS, connection/rate limiting etc.
To make Postfix know about Trident one needs to add to /etc/aliases:
trident-handler: "|/usr/sbin/trident-wrapper"
and to /etc/postfix/virtual something similar to:
mail-handler@example.net trident-handler
@example.net trident-handler
Of course do configure the rest of Postfix properly.
Reporting of Security Issues
Please contact project@trident.li directly, we’ll deal with problems swiftly and of course with proper attribution of any issues found.
Note that Trident is a community project, thus we do not offer any bounties as there is no money involved in the project.
We do very much appreciate responsible disclosure, thus do please contact us so that any issues can be properly addressed and existing installations updated.
Problem solving
tridentd
per default logs to syslog, which is a good place to check for issues.
Checklist
The following items should be checked:
- Verify that the configuration is correct (
/etc/trident/trident.conf
) - Verify that the database is setup correctly and is accessible
- Check syslog
Debug mode
One can enable verbose debugging by adding the --debug
option to DAEMON_OPTS
.
Passwords and Twofactor tokens are masked, other properties are all visible, thus be careful as it might reveal sensitive details.
Running without HTTPS
For testing only, if a SSL certificate is not present or if one wants to inspect the HTTP traffic
between the client and the server one could forward proxy in nginx from port 80 instead of 443.
In this case add to DAEMON_OPTS
the --insecurecookies
option to disable the HTTPS requirement
for cookies and thus enabling the cookies to be stored in the browser.
Trident Development
Following are some details about developing and improving Trident.
Problem reports / Feature Requests
Please file issues on our GitHub account.
Running Trident from source
This is a note for development purposes.
One requires golang
(Go) to be installed for running.
After checking Trident out of git one needs to configure the GOPATH
properly.
We store external libraries in ext/. To use these set GOPATH
like this:
export GOPATH=$(pwd)/ext/_gopath/
Then fetch dependencies:
doc/deps.sh
You can then execute tridentd with:
src/cmd/tridentd/tridentd.go --disabletwofactor --insecurecookies --config=doc/conf/
Of course, don’t forget to setup the database as detailed in the Database section.
Repository Organization
We use git as a distributed revision control system. Mainline is tracked in the master branch, development happens in sub-branches per feature.
The src
directory contains all the source code, this directory is subdivided in:
Directory | Description |
---|---|
ui | Web User Interface (UI) components. Each module relates to a related component in lib and has templates for actually rendingering HTML in share/templates/<component>/ |
lib | The per-component libraries of functions. These contain each a component head which links into the Menu system and thus also CLI code. Only code in this directory can execute SQL queries |
The share
directory contains SQL Schemas in dbschemas
, the web root in webroot
and Golang templates in templates
.
The ext
directory contains external dependencies (update/fetch with doc/deps.sh
).
Coding Style
We use the excellent vim-go by Fatih Arslan to enforce formatting.
Emacs users might want to try go-mode. This provides a gofmt-before-save hook that can be installed by adding this line to your .emacs file:
(add-hook 'before-save-hook #'gofmt-before-save)
In general, please verify that whitespace is not affected while commiting next to what is being commited is correct and properly tested.
We use a Model View Controller (MVC) approach to the code, though on two levels. The UI is strict-MVC.
Releasing New Packages
Update debian/changelog
with new date/timestamp and optional details, commit these details.
Then the below described sbuild procedure should be used to ensure vanilla builds that can be reproduced.
sbuild
On build.vm.trident.li we have an sbuild instance per instructions on https://wiki.debian.org/sbuild. apt-cacher-ng and lintian are installed and configured for speed and verification.
~/.sbuildrc options:
$run_lintian = 1;
$lintian_opts = ['-i', '-I'];
$purge_session = 'successful';
$purge_build_deps = 'successful';
$purge_build_directory = 'successful';
The purge options are to allow debugging unsuccesful builds.
Check out a pristine git clone, then use:
sbuild -v -d sid
to build the package.
If package building fails either check the ‘Keeping session’ line in the output or use the following to list sessions:
schroot -al
then start a shell inside the session with:
SESSION=sid-amd64-sbuild-<<UID>>
schroot -r -c ${SESSION}
providing the correct SESSION
id to the variable from the details above.
The build root can be found inside the chroot in /build/
Afterwards the session can be cleaned with:
schroot -e -c ${SESSION}
To generally clean sessions use:
schroot -e --all-sessions
Manual packages
Make sure that all dependencies are up to date:
doc/deps.sh
Build a new Debian package:
dpkb-buildpackage -b -uc -us
Voila, a new package.
Credits
Following is a short list of credits related to the Trident Project:
- Trident by Jeroen Massar
- Original Ops-Trust Portal code by the Ops-Trust Sysadmins
- XKCD 936 ‘Password Strength’ comic by Randall Munroe of xkcd.com.
- Go Crypto library by Jeramey Crawford and Jonas mg.
- Go UUID library by Google Inc.
- Go JSON Web Token (JWT) by Dave Grijalva.
- Go PostgreSQL driver ‘pq’ by Blake Mizerany and ‘pq’ Contributors.
- EpicEditor by Oscar Godson.
- Black Friday by Russ Ross
- Blue Monday by David Kitchen.
Further details are available in the Debian package copyright file in the source
or to be found in /usr/share/doc/trident/copyright
for installed Trident package on Debian.