-
Notifications
You must be signed in to change notification settings - Fork 10
/
export_iam.go
86 lines (81 loc) · 2.28 KB
/
export_iam.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
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"os"
"os/exec"
"strings"
)
// IAMPolicy is for capturing the project iam policy
type IAMPolicy struct {
Bindings []struct {
Members []string
Role string
}
}
// buildMemberToRoles builds the reverse mapping
func (i IAMPolicy) buildMemberToRoles() map[string][]string {
memberToRoles := map[string][]string{}
for _, each := range i.Bindings {
role := each.Role
for _, member := range each.Members {
list, ok := memberToRoles[member]
if !ok {
list = []string{}
}
memberToRoles[member] = append(list, role)
}
}
return memberToRoles
}
func fetchIAMPolicy(cmdline []string, verbose bool) (IAMPolicy, error) {
var p IAMPolicy
if verbose {
log.Println(strings.Join(cmdline, " "))
}
cmd := exec.Command(cmdline[0], cmdline[1:]...)
combined, err := runCommand(cmd)
if err != nil {
return p, err
}
if err := json.Unmarshal(combined, &p); err != nil {
return p, err
}
return p, nil
}
// ExportProjectsIAMPolicy reads the current IAM bindings on project level
// and outputs the contents of a gmig migration file.
// Return the filename of the migration.
func ExportProjectsIAMPolicy(cfg Config) error {
policy, err := fetchIAMPolicy([]string{"gcloud", "projects", "get-iam-policy", cfg.Project, "--format", "json"}, cfg.verbose)
if err != nil {
return err
}
memberToRoles := policy.buildMemberToRoles()
content := new(bytes.Buffer)
fmt.Fprintln(content, "# exported projects iam policy")
fmt.Fprint(content, "\ndo:")
for member, roles := range memberToRoles {
fmt.Fprintf(content, "\n # member = %s\n", member)
for _, role := range roles {
cmd := fmt.Sprintf(" - gcloud projects add-iam-policy-binding $PROJECT --member %s --role %s\n", member, role)
fmt.Fprintf(content, cmd)
}
}
fmt.Fprintf(content, "\nundo:")
for member, roles := range memberToRoles {
fmt.Fprintf(content, "\n # member = %s\n", member)
for _, role := range roles {
cmd := fmt.Sprintf(" - gcloud projects remove-iam-policy-binding $PROJECT --member %s --role %s\n", member, role)
fmt.Fprintf(content, cmd)
}
}
filename := NewFilenameWithIndex("exported project iam policy")
if cfg.verbose {
log.Println("writing", filename)
}
return ioutil.WriteFile(filename, content.Bytes(), os.ModePerm)
}