summaryrefslogtreecommitdiffstats
path: root/gustodia.go
blob: 9757542e24c7d800d315ce2b57e092c5a36e3ffa (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
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package main

import (
    "fmt"
    "encoding/json"
    "errors"
    "net"
    "net/http"
    "os"
    "strings"
    "syscall"
)

const PREFIX string = "CUSTODIA_"
const SECRET_PREFIX string = PREFIX + "SECRET_"
const BASE_PATH string = "http://localhost/secrets/"
const SOCKET string = "./server_socket"

type CustodiaMessage struct {
    Type string  `json:"type"`
    Value string `json:"value"`
}

type CustodiaSecret struct {
    Name string
    Value string
    Secret string
}

func unixDial(proto, addr string) (conn net.Conn, err error) {
    typ := "unix"
    conn, err = net.DialUnix(typ, nil, &net.UnixAddr{SOCKET, typ})
    return conn, err
}

func query_custodia(secrets []*CustodiaSecret) {
    tr := &http.Transport{
        Dial: unixDial,
    }
    client := &http.Client{Transport: tr}

    for _, sec := range secrets {
        path := BASE_PATH + sec.Value
        req, err := http.NewRequest(
            "GET", path, nil)
        if err != nil {
            panic(err)
        }
        req.Header.Add("REMOTE_USER", "gustodia")
        resp, err := client.Do(req)
        if err != nil {
            panic(err)
        }
        defer resp.Body.Close()

        if resp.StatusCode != http.StatusOK {
            msg := fmt.Sprintf("%s: %s", path, resp.Status)
            err := errors.New(msg)
            panic(err)
        }
        var m CustodiaMessage
        body := json.NewDecoder(resp.Body)
        body.Decode(&m)
        sec.Secret = m.Value;
    }
}

func get_custodia_envs() ([]*CustodiaSecret) {
    secrets := []*CustodiaSecret{}
    for _, env := range os.Environ() {
        if strings.HasPrefix(env, SECRET_PREFIX) {
            pair := strings.SplitN(env, "=", 2)
            sec := &CustodiaSecret{
                Name: pair[0][len(SECRET_PREFIX):],
                Value: pair[1],
                Secret: "",
            }
            secrets = append(secrets, sec)
        }
    }
    return secrets
}

func make_env(secrets []*CustodiaSecret) []string {
    environ := []string{}
    for _, env := range os.Environ() {
        if ! strings.HasPrefix(env, PREFIX) {
            environ = append(environ, env)
        }
    }
    for _, sec := range secrets {
        env := fmt.Sprintf("%s=%s", sec.Name, sec.Secret)
        environ = append(environ, env)
    }
    return environ
}

func main() {
    secrets := get_custodia_envs()
    query_custodia(secrets)
    environ := make_env(secrets)
    /*
    for _, sec := range secrets {
        fmt.Printf("%+v\n", *sec)
    }
    for _, env := range environ {
        fmt.Println(env)
    }
    */
    args := os.Args[1:]
    syscall.Exec(args[0], args, environ)
}