-
Notifications
You must be signed in to change notification settings - Fork 1
/
generate.go
114 lines (93 loc) · 2.71 KB
/
generate.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
package dev
import (
"fmt"
"net/url"
"os"
"strings"
"github.com/aserto-dev/aserto/pkg/cc"
"github.com/getkin/kin-openapi/openapi3"
"github.com/pkg/errors"
)
type PolicyFromOpenAPI struct {
URL string `arg:"" required:"" help:"URL of the openapi.yaml"`
Name string `arg:"" optional:"" help:"The name for the policy"`
}
const packageTemplate = `package %s
default allowed = false`
func parseURI(uri string) []string {
result := []string{}
parts := strings.Split(uri, "/")
for _, part := range parts[1:] {
if strings.Contains(part, "{") {
clean := strings.Replace(strings.Replace(part, "{", "", -1), "}", "", -1)
result = append(result, "__"+clean)
} else {
result = append(result, part)
}
}
return result
}
func generatePackageName(root, verb, uri string) string {
parts := []string{root, verb}
parts = append(parts, parseURI(uri)...)
return strings.Join(parts, ".")
}
func savePolicy(path, content string) error {
file, err := os.Create(path)
if err != nil {
return errors.Wrapf(err, "Error creating the policy module file [%s]", path)
}
defer file.Close()
if _, err := fmt.Fprint(file, content); err != nil {
return errors.Wrap(err, "failed to write policy")
}
return nil
}
func (cmd *PolicyFromOpenAPI) Run(c *cc.CommonCtx) error {
specURL, err := url.Parse(cmd.URL)
if err != nil {
return errors.Wrapf(err, "Failed to parse spec URL [%s]", cmd.URL)
}
doc, err := openapi3.NewLoader().LoadFromURI(specURL)
if err != nil {
return errors.Wrapf(err, "Failed to load spec from URL [%s]", cmd.URL)
}
root := cmd.Name
if cmd.Name == "" {
root = strings.Replace(strings.ToLower(doc.Info.Title), " ", "_", -1)
}
packages := []string{}
for uri, path := range doc.Paths {
if path.Get != nil {
packages = append(packages, generatePackageName(root, "GET", uri))
}
if path.Post != nil {
packages = append(packages, generatePackageName(root, "POST", uri))
}
if path.Put != nil {
packages = append(packages, generatePackageName(root, "PUT", uri))
}
if path.Delete != nil {
packages = append(packages, generatePackageName(root, "DELETE", uri))
}
if path.Options != nil {
packages = append(packages, generatePackageName(root, "OPTIONS", uri))
}
}
policiesDirectoryName := root + "/src/policies"
if _, err := os.Stat(root); errors.Is(err, os.ErrNotExist) {
err := os.MkdirAll(policiesDirectoryName, os.ModePerm)
if err != nil {
return errors.Wrapf(err, "Failed to create the directory [%s]", policiesDirectoryName)
}
}
for _, pkg := range packages {
policy := fmt.Sprintf(packageTemplate, pkg)
filename := pkg + ".rego"
path := policiesDirectoryName + "/" + filename
if err := savePolicy(path, policy); err != nil {
return err
}
}
return nil
}