diff options
author | KatolaZ <katolaz@freaknet.org> | 2017-07-11 14:38:55 +0100 |
---|---|---|
committer | KatolaZ <katolaz@freaknet.org> | 2017-07-11 14:38:55 +0100 |
commit | 32b09256150d139e77d04533f28d0c26a32b12bd (patch) | |
tree | 9d5aff595a1af5afee566b433d0466416d4f6691 | |
parent | 3b752dc02e8ac2048c3dc6efa37145c679502c84 (diff) |
added notes.txt on the architecture, and a sample worker_config
-rw-r--r-- | commits.go | 101 | ||||
-rw-r--r-- | config.go | 2 | ||||
-rw-r--r-- | notes.txt | 54 | ||||
-rw-r--r-- | scorsh.go | 11 | ||||
-rw-r--r-- | worker_config.cfg | 37 |
5 files changed, 198 insertions, 7 deletions
diff --git a/commits.go b/commits.go new file mode 100644 index 0000000..c429bca --- /dev/null +++ b/commits.go @@ -0,0 +1,101 @@ +package main + +import ( + "fmt" + "github.com/KatolaZ/git2go" + "golang.org/x/crypto/openpgp" + "os" + "strings" + "log" +) + +func CommitToString(commit *git.Commit) string { + + var ret string + + ret += fmt.Sprintf("type: %s\n", commit.Type()) + ret += fmt.Sprintf("Id: %s\n", commit.Id()) + ret += fmt.Sprintf("Author: %s\n", commit.Author()) + ret += fmt.Sprintf("Message: %s\n", commit.Message()) + ret += fmt.Sprintf("Parent-count: %d\n", commit.ParentCount()) + + return ret +} + +// FIXME: RETURN THE ENTITY PROVIDED BY THE CHECK, OR nil +func check_signature(commit *git.Commit, keyring *openpgp.KeyRing) (signature, signed string, err error) { + + signature, signed, err = commit.ExtractSignature() + if err == nil { + + _, err_sig := + openpgp.CheckArmoredDetachedSignature(*keyring, strings.NewReader(signed), + strings.NewReader(signature)) + + if err_sig == nil { + fmt.Printf("Good signature \n") + return signature, signed, nil + } + err = err_sig + } + + return "", "", err +} + + +// traverse all the commits between two references, looking for scorsh +// commands +// fixme: we don't have just one keyring here.... +func walk_commits(msg SCORSHmsg, keyring openpgp.KeyRing) int { + + fmt.Printf("Inside parse_commits\n") + + reponame := msg.repo + old_rev := msg.old_rev + new_rev := msg.new_rev + + repo, err := git.OpenRepository(reponame) + if err != nil { + fmt.Fprintf(os.Stderr, "Error while opening repository %s (%s)\n", + reponame, err) + return SCORSH_ERR_NO_REPO + } + + old_rev_oid, err := git.NewOid(old_rev) + + oldrev_commit, err := repo.LookupCommit(old_rev_oid) + if err != nil { + fmt.Fprintf(os.Stderr, "Commit: %s does not exist\n", old_rev) + return SCORSH_ERR_NO_COMMIT + } + + new_rev_oid, err := git.NewOid(new_rev) + + newrev_commit, err := repo.LookupCommit(new_rev_oid) + if err != nil { + fmt.Fprintf(os.Stderr, "Commit: %s does not exist\n", new_rev) + return SCORSH_ERR_NO_COMMIT + } + + cur_commit := newrev_commit + + for cur_commit.Id().String() != oldrev_commit.Id().String() { + + commit, err := repo.LookupCommit(cur_commit.Id()) + if err == nil { + + fmt.Printf("%s", CommitToString(commit)) + //signature, signed, err := check_signature(commit, &keyring) + _, _, err := check_signature(commit, &keyring) + if err != nil { + log.Printf("%s\n", SCORSHErr(SCORSH_ERR_SIGNATURE)) + + } + cur_commit = commit.Parent(0) + } else { + fmt.Printf("Commit %x not found!\n", cur_commit.Id()) + return SCORSH_ERR_NO_COMMIT + } + } + return 0 +} @@ -28,7 +28,7 @@ type SCORSHcfg struct { // Read a configuration from fname or die -func ReadConfig(fname string) *SCORSHcfg { +func ReadGlobalConfig(fname string) *SCORSHcfg { data, err := ioutil.ReadFile(fname) if err != nil { diff --git a/notes.txt b/notes.txt new file mode 100644 index 0000000..618fcbf --- /dev/null +++ b/notes.txt @@ -0,0 +1,54 @@ +## structure + +- we read the list of workers from the config file. Each worker + record consists of + + - a list of repos/branches + - a folder where the configs and logs are kept + - a logfile + - a tagfile with the definition of tags + - a list of keyring files + +## master logic + +- in main() (master) we create a worker for each worker record, + maintaining a map of which worker can process commands for which + repo/branch + +- The spooler receives and processes CREATE events from the spool. It + parses each message and forwards it to the corresponding worker(s). + +- When the worker is done, it notifies the master, which will delete + the corresponding file from the spool. + + + +## worker logic + +- Each worker reads a configuration file containing the definition of + the tags it can manage. + +- Each tag is associated to a set of commands (URLs) and to a set of + keyrings. + +- A worker maintains a list of accepted scorsh tags, a map of + keyrings[tags], and a map of commands[tags]. + +When a new scorsh message is received by a worker, it looks through +the commit history for commits containing schorsh-tags. For each +scorsh-tag found, the worker looks if the tag is among the supported +ones, then checks if the commit can be verified by one of the keyrings +associated to the tag. If the set of keyrings for that tag is empty, +the tag is not allowed to run (this is a quick way to disable tags). + +(we might want to add an option to the definition of a scorsh-tag, +which allows to run the commands from unsigned and/or unverified +commits. This would be very dangerous though.) + +Then, if the tag is allowed to run, the worker executes each of the +commands in the tag definition, replacing arguments as needed. If a +command is a script (file://...), then it must also correspon to the +hash specified in the config, otherwise it will not be executed. + +When the worker is finished with all the commands for all the commits, +it will notify the master. @@ -14,11 +14,6 @@ const ( SCORSH_ERR_SIGNATURE ) -type SCORSHconf struct { - spool string -} - - type SCORSHmsg struct { repo string @@ -60,8 +55,12 @@ func main() { flag.Parse() - cfg := ReadConfig(*conf_file) + cfg := ReadGlobalConfig(*conf_file) + msg, status := StartWorkers(cfg) + + + log.Printf("%s\n", cfg) } diff --git a/worker_config.cfg b/worker_config.cfg new file mode 100644 index 0000000..5173b6f --- /dev/null +++ b/worker_config.cfg @@ -0,0 +1,37 @@ +# +# This is the typical worker configuration file. The file should be +# called "worker_config.cfg", and will be placed inside the worker +# directory. It defines the tags understood by the worker, with the +# corresponding list of commands +# +# + + +--- +w_tags: + [ + { + t_name: "BUILD", + t_keyrings: ["build_keyring.asc", "general_keyring.asc"], + t_commands: [ + { + c_url: "file:///home/user/bin/script.sh $1 $2", + c_hash: "12da324fb76s924acbce" + }, + { + c_url: "http://my.server.net/call.pl?branch=$1" + } + ] + }, + { + t_name: "PUBLISH", + t_keyrings: ["web_developers.asc"], + t_commands: [ + { + c_url: "file:///usr/local/bin/publish.py $repo $branch", + c_hash: "3234567898765432345678" + } + ] + } + ] +...
\ No newline at end of file |