aboutsummaryrefslogtreecommitdiff
path: root/README.md
blob: fde7650c60b864d68eca6c34ce718e4c68f232e4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# Levitating

_A continuous integration system built in Fortran_

## About

Levitating is an overly simple continuous integration system designed entirely in Fortran to, basically, replace Python's buildbot package (circa version 0.8).  The system is comprised of a _captain_, which acts as the control server, and a collection of _players_, each of which can be assigned _jobs_ to perform.  Build results are generally captured and returned to the _captain_ after a task is complete.

The system is drastically simpler than the system it aims to replace.  The _captain_ has no knowledge of the details of jobs themselves.  The _players_ will report results from each _task_ in a _job_ back to the _captain_.  The _captain_ does store these results and display them when requested, but the tasks are only referred to numerically.

## Requirements

To build Levitating, you'll need:

* GNU Fortran or another compiler that supports a handful of extensions used
* libssl
* json-fortran (version 7 series, should work with 8)
* uuidgen (part of Debian's uuid-runtime package)
* mkpasswd (part of Debian's whois package) if your system is having trouble with creating users (see below)

## Instructions

_Instructions_ are the list of _tasks_ that a _player_ needs to perform to complete a _job_.  The instructions are entirely written in JSON, which the _players_ then interpret.  Currently, 5 types of actions are supported:

 * __shell__ - Execute a shell command on the host operating system's default shell
 * __git__ - Either clone or pull, whichever is appropriate, from a git repo
 * __download__ - Download a particular file from the _captain_
 * __upload__ - Upload a file or files (globbing supported) to the _captain_
 * __delete_tree__ - Delete a directory tree
 
The above steps encompass what I needed to replace in buildbot personally.  If someone has a suggestion, write in!

It should be noted that _players_ have absolutely no restrictions on functions like __download__ or __delete_tree__, and they will happily try to download system files or delete a root directory.
 
## Protocol

The _player_ processes will communicate with the _captain_ via the [Gemini protocol](https://gemini.circumlunar.space/), a quasi-standard that is meant as a simpler alternative to HTTP.  The _players_ will upload files to the server via the [Titan protocol](https://communitywiki.org/wiki/Titan), a system for uploading files meant to pair with the Gemini protocol.

Currently, the only way to access the portal for starting _jobs_, adding _players_, or viewing results is also via the Gemini protocol.  You'll need to keep port 1965 open for the _captain_, which must be run via xinetd or inetd.

A CGI gateway (that's not a typo) for a compatible HTTP server is planned but non-existent.

## Security

The system currently implements a simple user model.  Access levels are defined as 0 through 10, and are listed in the file pointed to by *permissions_file* in the main configuration.  An example (and quite reasonable) access model is included in the example folder.  Certain access levels, including the public (0), can be restricted from accessing all sorts of features relatively easily.

Currently, the system provides a command line method of creating an administrator using the *--new-admin* command line option when you execute the captain's executable from the command line.  This action will create a user with access level set to 10.  At this time, there is no way to create other users through the web or Gemini interfaces, though that would make sense if an administrator is indeed logged in.

The Gemini login process will pass the user's password as a query.  Consider this fact when setting up logins.

Despite this software being written in Fortran (albeit a modern variant), the password hashing and storage is robust be default.  Passwords are hashed via blowfish and stored in the database, and a system-wide salt, appearing in the configuration file, is used prior to blowfish encryption.

Some older distros that have not included standard blowfish utilities in their runtimes or are just using older Fortran compilers may actually fail to create users.  In this case, Levitating includes an alternate *m_crypt* module in the *captain/cryptcl.f90* file that uses the *mkpasswd* command and relies on SHA-512 hashing of passwords instead.  Users should really only use this solution if all else fails.

## License

Levitating is subject to the following license:

Copyright (c) 2021, 2022 Approximatrix, LLC <support@approximatrix.com>

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

The Software shall be used for Good, not Evil.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.