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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
package main
import (
"flag"
"io/ioutil"
"log"
"encoding/json"
)
var (
challenges = []Challenge{}
seedFilePath* string
)
func registerSeedFlags() {
seedFilePath = flag.String("seedFile", "/etc/companion.json", "Path to seedfile")
}
// Read a given seed file and return their containing challenges
func readSeedFile(path string) ([]Challenge) {
var jsonContents map[string]interface{}
// Read file
rawContents, readError := ioutil.ReadFile(path)
if readError != nil {
log.Printf("Failed to read seed file at %s: %s", *seedFilePath, readError.Error())
return nil
}
// Convert JSON String to map
unmarshalError := json.Unmarshal(rawContents, &jsonContents)
if unmarshalError != nil {
log.Printf("Failed to parse JSON in seed file at %s: %s", *seedFilePath, unmarshalError.Error())
return nil
}
tmpChallenges := []Challenge{}
// Iterate over challenges
for index, challengeObject := range jsonContents["challenges"].([]interface{}) {
challenge := challengeObject.(map[string]interface{})
// add our parsed challenge to array
name, nameOK := challenge["name"].(string)
desc, descOK := challenge["description"].(string)
flag, flagOK := challenge["flag"].(string)
cont, contOK := challenge["container"].(string)
category, categoryOK := challenge["category"].(string)
if nameOK && descOK && flagOK && contOK && categoryOK {
tmpChallenges = append(tmpChallenges, Challenge{
Name: name,
Description: desc,
Flag: flag,
FoundFlag: false,
FlagTries: 0,
Container: cont,
Category: category,
})
} else {
log.Printf("Ignoring challenge at position %d: Not all values are parseable (name: %b, desc: %b, flag: %b, container: %b, category: %b", index, nameOK, descOK, flagOK, contOK, categoryOK)
}
}
return tmpChallenges
}
// Read the file we set up using flags and store the returned challenge array
func getChallengesFromSeedFile() {
tmpChallenges := readSeedFile(*seedFilePath)
if tmpChallenges != nil {
challenges = tmpChallenges
}
}
// Generate a JSON string from the stored challenges, stripped from content which might spoil the user
func generateJSONFromChallenges() (string, error) {
// To avoid leakage of container name or the flag towards the user, we need to strip the challenges
var strippedChallenges []StrippedChallenge
categories := map[string]int{}
for _, challenge := range challenges {
// Append challenge to list
strippedChallenges = append(strippedChallenges, stripChallenge(challenge))
categories[challenge.Category]++
}
marshalled, marshalError := json.Marshal(map[string]interface{}{
"challenges": strippedChallenges,
"categories": categories,
})
return string(marshalled), marshalError
}
|