-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathmain.go
125 lines (101 loc) · 3.18 KB
/
main.go
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
113
114
115
116
117
118
119
120
121
122
123
124
125
package main
import (
"bytes"
"errors"
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"github.com/spf13/cobra"
"k8s.io/helm/pkg/chartutil"
)
const globalUsage = `
Enable an RBAC profile for Tiller
An RBAC profile at the moment is a Helm chart that contains a set of Kubernetes manifests defining roles, role-bindings, service accounts that can be templated
Example Usage:
$ helm tiller-rbac dev-team-rbac-profile-chart/
`
var namespace string
var version = "DEV"
func main() {
cmd := &cobra.Command{
Use: "tiller-rbac [RBAC_PROFILE]",
Short: globalUsage,
RunE: run,
}
f := cmd.Flags()
f.StringVar(&namespace, "namespace", "default", "namespace of Tiller to apply profile")
if err := cmd.Execute(); err != nil {
os.Exit(1)
}
}
func run(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return errors.New("missing argument: path to chart containing rbac profile")
}
if len(args) > 1 {
return errors.New("TMI")
}
profilePath := args[0]
profileName := filepath.Base(profilePath)
var outb bytes.Buffer
var errb bytes.Buffer
_, err := chartutil.Load(profilePath)
if err != nil {
return err
}
renderTemplates := exec.Command("helm", "template", "--namespace", namespace, profilePath)
renderTemplates.Stdout = &outb
renderTemplates.Stderr = &errb
err = renderTemplates.Run()
if err != nil {
return errors.New(errb.String())
}
manifests := []byte(outb.String())
dir, err := ioutil.TempDir("", "tiller-rbac")
if err != nil {
return err
}
defer os.RemoveAll(dir) // clean up
manifestsFile := filepath.Join(dir, "profile")
if err := ioutil.WriteFile(manifestsFile, manifests, 0666); err != nil {
return err
}
outb.Reset()
errb.Reset()
createSvcAccount := exec.Command("kubectl", "create", "serviceaccount", profileName, "--namespace", namespace)
createSvcAccount.Stdout = &outb
createSvcAccount.Stderr = &errb
err = createSvcAccount.Run()
if err != nil {
return errors.New(errb.String())
}
fmt.Print(outb.String())
outb.Reset()
errb.Reset()
createRoleBindingBits := exec.Command("kubectl", "apply", "-f", manifestsFile)
createRoleBindingBits.Stdout = &outb
createRoleBindingBits.Stderr = &errb
err = createRoleBindingBits.Run()
if err != nil {
return errors.New(errb.String())
}
fmt.Println(outb.String())
outb.Reset()
errb.Reset()
specPatch := `{"spec":{"template":{"spec":{"serviceAccount":"` + profileName + `","serviceAccountName":"` + profileName + `"}}}}`
outb.Reset()
errb.Reset()
// this command will terminate & retstart pods automatically after attaching the service account
attachSvcAccount := exec.Command("kubectl", "patch", "--namespace", namespace, "deployment", "tiller-deploy", "-p", specPatch)
attachSvcAccount.Stdout = &outb
attachSvcAccount.Stderr = &errb
err = attachSvcAccount.Run()
if err != nil {
return errors.New(errb.String())
}
fmt.Println("Congrats! Your Tiller in the " + namespace + " namespace is secured with the " + profileName + " service account\nYou can verify your Tiller config by running this command\n\t$ kubectl -n " + namespace + " get deployment tiller-deploy -o json\n")
//TODO: verify that the service account you wanted is now part of the tiller deployment spec
return nil
}