Skip to content

Commit 32725eb

Browse files
Radu Andriespoiana
Radu Andries
authored andcommitted
Publish kilt golang library
Signed-off-by: Radu Andries <radu.andries@sysdig.com>
1 parent b637d05 commit 32725eb

15 files changed

+468
-0
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.idea/

pkg/go.mod

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
module github.com/falcosecurity/kilt/pkg
2+
3+
go 1.15
4+
5+
require (
6+
github.com/go-akka/configuration v0.0.0-20200606091224-a002c0330665
7+
github.com/stretchr/testify v1.6.1
8+
)

pkg/go.sum

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
2+
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3+
github.com/go-akka/configuration v0.0.0-20200606091224-a002c0330665 h1:Iz3aEheYgn+//VX7VisgCmF/wW3BMtXCLbvHV4jMQJA=
4+
github.com/go-akka/configuration v0.0.0-20200606091224-a002c0330665/go.mod h1:19bUnum2ZAeftfwwLZ/wRe7idyfoW2MfmXO464Hrfbw=
5+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
6+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
7+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
8+
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
9+
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
10+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
11+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
12+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
13+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

pkg/hocon/build.go

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package hocon
2+
3+
import (
4+
"fmt"
5+
"github.com/falcosecurity/kilt/pkg/kilt"
6+
"github.com/go-akka/configuration"
7+
)
8+
9+
func extractBuild(config *configuration.Config) (*kilt.Build, error) {
10+
b := new(kilt.Build)
11+
12+
b.Image = config.GetString("build.image")
13+
b.EntryPoint = config.GetStringList("build.entry_point")
14+
b.Command = config.GetStringList("build.command")
15+
16+
b.EnvironmentVariables = extractToStringMap(config, "build.environment_variables")
17+
18+
if config.IsArray("build.mount") {
19+
mounts := config.GetValue("build.mount").GetArray()
20+
21+
for k, m := range mounts {
22+
if m.IsObject() {
23+
mount := m.GetObject()
24+
25+
resource := kilt.BuildResource{
26+
Name: mount.GetKey("name").GetString(),
27+
Image: mount.GetKey("image").GetString(),
28+
Volumes: mount.GetKey("volumes").GetStringList(),
29+
EntryPoint: mount.GetKey("entry_point").GetStringList(),
30+
}
31+
32+
if resource.Image == "" || len(resource.Volumes) == 0 || len(resource.EntryPoint) == 0 {
33+
return nil, fmt.Errorf("error at build.mount.%d: image, volumes and entry_point are all required ", k)
34+
}
35+
36+
b.Resources = append(b.Resources, resource)
37+
}
38+
}
39+
}
40+
41+
return b, nil
42+
}

pkg/hocon/fixtures/input.json

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"image": "busybox:latest",
3+
"container_name": "test",
4+
"container_group_name": "test_group",
5+
"entry_point": ["/bin/stuff"],
6+
"command": ["/bin/sh"]
7+
}

pkg/hocon/fixtures/kilt.cfg

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
build {
2+
entry_point: [/falco/pdig] ${?original.entry_point}
3+
environment_variables: {
4+
TEST: "true"
5+
}
6+
mount: [
7+
{
8+
name: "TestImage"
9+
image: "falco/falco:latest"
10+
volumes: ["/falco"]
11+
entry_point: ["/falco/waitforever"]
12+
}
13+
]
14+
}
15+
runtime {
16+
upload: [
17+
{
18+
url: "https://storage.googleapis.com/kubernetes-release/release/v1.19.0/bin/linux/amd64/"
19+
as: "/bin/kubectl"
20+
}
21+
]
22+
exec: [
23+
{
24+
run: ["/bin/kubectl", "--version"]
25+
}
26+
]
27+
}

pkg/hocon/hocon.go

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package hocon
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"github.com/falcosecurity/kilt/pkg/kilt"
7+
"github.com/go-akka/configuration"
8+
)
9+
10+
var defaults = `
11+
build {
12+
entry_point: ${original.entry_point}
13+
command: ${original.command}
14+
image: ${original.image}
15+
environment_variables: ${original.environment_variables}
16+
17+
mount: []
18+
}
19+
`
20+
21+
type KiltHocon struct {
22+
definition string
23+
}
24+
25+
func NewKiltHocon(definition string) *KiltHocon {
26+
h := new(KiltHocon)
27+
h.definition = definition
28+
return h
29+
}
30+
31+
func (k *KiltHocon) prepareFullStringConfig(info *kilt.TargetInfo) (*configuration.Config, error) {
32+
rawVars, err := json.Marshal(info)
33+
if err != nil {
34+
return nil, fmt.Errorf("could not serialize info: %w", err)
35+
}
36+
configString := "original:" + string(rawVars) + "\n" + defaults + k.definition
37+
38+
return configuration.ParseString(configString), nil
39+
}
40+
41+
func (k *KiltHocon) Build(info *kilt.TargetInfo) (*kilt.Build, error) {
42+
config, err := k.prepareFullStringConfig(info)
43+
if err != nil {
44+
return nil, fmt.Errorf("could not assemble full config: %w", err)
45+
}
46+
47+
return extractBuild(config)
48+
}
49+
50+
func (k *KiltHocon) Runtime(info *kilt.TargetInfo) (*kilt.Runtime, error) {
51+
config, err := k.prepareFullStringConfig(info)
52+
if err != nil {
53+
return nil, fmt.Errorf("could not assemble full config: %w", err)
54+
}
55+
if ! config.HasPath("runtime"){
56+
return nil, fmt.Errorf("definition does not have a runtime section")
57+
}
58+
return extractRuntime(config)
59+
}
60+

pkg/hocon/hocon_test.go

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package hocon
2+
3+
import (
4+
"encoding/json"
5+
"github.com/falcosecurity/kilt/pkg/kilt"
6+
"github.com/stretchr/testify/assert"
7+
"io/ioutil"
8+
"testing"
9+
)
10+
11+
func TestSimpleRuntime(t *testing.T) {
12+
targetInfoString, _ := ioutil.ReadFile("./fixtures/input.json")
13+
definitionString, _ := ioutil.ReadFile("./fixtures/kilt.cfg")
14+
k := NewKiltHocon(string(definitionString))
15+
info := new(kilt.TargetInfo)
16+
_ = json.Unmarshal(targetInfoString, info)
17+
r, _ := k.Runtime(info)
18+
19+
assert.Equal(t, 1, len(r.Uploads), "expected 1 executable")
20+
assert.Equal(t, "https://storage.googleapis.com/kubernetes-release/release/v1.19.0/bin/linux/amd64/",
21+
r.Uploads[0].Payload.Contents)
22+
assert.Equal(t, kilt.URL, r.Uploads[0].Payload.Type)
23+
24+
assert.Equal(t, 1, len(r.Executables))
25+
assert.Equal(t, "/bin/kubectl", r.Executables[0].Run[0])
26+
}
27+
28+
func TestSimpleBuild(t *testing.T) {
29+
targetInfoString, _ := ioutil.ReadFile("./fixtures/input.json")
30+
definitionString, _ := ioutil.ReadFile("./fixtures/kilt.cfg")
31+
k := NewKiltHocon(string(definitionString))
32+
info := new(kilt.TargetInfo)
33+
_ = json.Unmarshal(targetInfoString, info)
34+
b, _ := k.Build(info)
35+
36+
assert.Equal(t, "busybox:latest", b.Image)
37+
assert.Equal(t, "/falco/pdig", b.EntryPoint[0])
38+
assert.Equal(t, "true", b.EnvironmentVariables["TEST"])
39+
assert.Equal(t, 1, len(b.Resources))
40+
}

pkg/hocon/payload.go

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package hocon
2+
3+
import (
4+
"fmt"
5+
"github.com/falcosecurity/kilt/pkg/kilt"
6+
"github.com/go-akka/configuration/hocon"
7+
)
8+
9+
func retrievePayload(object *hocon.HoconObject) (*kilt.Payload, error) {
10+
payload := new(kilt.Payload)
11+
payload.Type = kilt.Unknown
12+
if object.GetKey("url").IsString() {
13+
payload.Contents = object.GetKey("url").GetString()
14+
payload.Type = kilt.URL
15+
} else if object.GetKey("file").IsString() {
16+
payload.Contents = object.GetKey("file").GetString()
17+
payload.Type = kilt.LocalPath
18+
} else if object.GetKey("payload").IsString() {
19+
payload.Contents = object.GetKey("payload").GetString()
20+
payload.Type = kilt.Base64
21+
} else if object.GetKey("text").IsString() {
22+
payload.Contents = object.GetKey("text").GetString()
23+
payload.Type = kilt.Text
24+
}
25+
if object.GetKey("gzipped") != nil && object.GetKey("gzipped").IsString() && object.GetKey("gzipped").GetBoolean() {
26+
payload.Gzipped = true
27+
}
28+
29+
if payload.Type == kilt.Unknown {
30+
return nil, fmt.Errorf("could not identify payload type for %s", object.ToString(1))
31+
}
32+
33+
34+
return payload, nil
35+
}

pkg/hocon/runtime.go

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package hocon
2+
3+
import (
4+
"fmt"
5+
"github.com/falcosecurity/kilt/pkg/kilt"
6+
"github.com/go-akka/configuration"
7+
)
8+
9+
func extractRuntime(config *configuration.Config) (*kilt.Runtime, error) {
10+
r := new(kilt.Runtime)
11+
12+
if config.IsArray("runtime.upload") {
13+
uploads := config.GetValue("runtime.upload").GetArray()
14+
15+
for k, u := range uploads {
16+
if u.IsObject() {
17+
var err error
18+
upload := u.GetObject()
19+
20+
newUpload := new(kilt.RuntimeUpload)
21+
22+
newUpload.Payload, err = retrievePayload(upload)
23+
24+
if err != nil {
25+
return nil, fmt.Errorf("could not extract payload for entry %d: %w", k, err)
26+
}
27+
28+
newUpload.Destination = upload.GetKey("as").GetString()
29+
30+
if newUpload.Destination == "" {
31+
return nil, fmt.Errorf("could not extract destination for entry %d: 'as' cannot be empty", k)
32+
}
33+
34+
newUpload.Uid = getWithDefaultUint16(upload, "uid", kilt.DefaultUserID)
35+
newUpload.Gid = getWithDefaultUint16(upload, "gid", kilt.DefaultGroupID)
36+
newUpload.Permissions = getWithDefaultUint32(upload, "permissions", kilt.DefaultPermissions)
37+
38+
r.Uploads = append(r.Uploads, *newUpload)
39+
}
40+
}
41+
}
42+
43+
if config.IsArray("runtime.exec") {
44+
for k, e := range config.GetValue("runtime.exec").GetArray() {
45+
if e.IsObject() {
46+
exec := e.GetObject()
47+
48+
execParams := exec.GetKey("run").GetStringList()
49+
50+
if len(execParams) == 0 {
51+
return nil, fmt.Errorf("could not add exec at entry %d: run cannot have 0 arguments", k)
52+
}
53+
54+
r.Executables = append(r.Executables, kilt.RuntimeExecutable{Run: execParams})
55+
}
56+
}
57+
}
58+
59+
return r, nil
60+
}

pkg/hocon/util.go

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package hocon
2+
3+
import (
4+
"github.com/go-akka/configuration"
5+
"github.com/go-akka/configuration/hocon"
6+
)
7+
8+
func extractToStringMap(config *configuration.Config, path string) map[string]string {
9+
value := make(map[string]string)
10+
11+
if config.HasPath(path) && config.IsObject(path) {
12+
obj := config.GetNode(path).GetObject()
13+
14+
for k, v := range obj.Items() {
15+
value[k] = v.GetString()
16+
}
17+
}
18+
19+
return value
20+
}
21+
22+
func getWithDefaultUint16(object *hocon.HoconObject, key string, fallback uint16) uint16 {
23+
t := object.GetKey(key)
24+
25+
if t == nil || t.IsEmpty() {
26+
return fallback
27+
}
28+
29+
return uint16(t.GetInt32())
30+
}
31+
32+
func getWithDefaultUint32(object *hocon.HoconObject, key string, fallback uint32) uint32 {
33+
t := object.GetKey(key)
34+
35+
if t==nil || t.IsEmpty() {
36+
return fallback
37+
}
38+
39+
return uint32(t.GetInt64())
40+
}
41+
42+
func emptyIncludeCallback(filename string) *hocon.HoconRoot {
43+
return hocon.Parse("", emptyIncludeCallback)
44+
}

pkg/kilt/kilt.go

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package kilt
2+
3+
4+
5+
type Kilt struct {
6+
definition LanguageInterface
7+
}
8+
9+
func NewKilt(impl LanguageInterface) *Kilt {
10+
k := new(Kilt)
11+
k.definition = impl
12+
return k
13+
}
14+
15+
func (k *Kilt) Build(info *TargetInfo) (*Build, error) {
16+
return k.definition.Build(info)
17+
}
18+
19+
func (k *Kilt) Runtime(info *TargetInfo) (*Runtime, error) {
20+
return k.definition.Runtime(info)
21+
}

0 commit comments

Comments
 (0)