package main
import (
"fmt"
"io/ioutil"
"os"
"sort"
"strings"
)
const permsFile = "website/content/docs/concepts/permissions.mdx"
var (
iamScopes = []string{"Global", "Org"}
infraScope = []string{"Project"}
)
type Table struct {
Header *Header
Body *Body
}
type Header struct {
Titles []string
}
type Body struct {
Resources []*Resource
}
type Resource struct {
Type string
Scopes []string
Endpoints []*Endpoint
}
type Endpoint struct {
Path string
Params map[string]string
Actions []*Action
}
type Action struct {
Name string
Description string
Examples []string
}
var table = &Table{
Header: &Header{
Titles: []string{
"Resource Type",
"Applicable Scopes",
"API Endpoint",
"Parameters into Permissions Engine",
"Available Actions / Examples",
},
},
Body: &Body{
Resources: make([]*Resource, 0, 12),
},
}
func main() {
table.Body.Resources = append(table.Body.Resources,
account,
authMethod,
authToken,
group,
host,
hostCatalog,
hostSet,
role,
scope,
session,
target,
user,
)
fileContents, err := ioutil.ReadFile(permsFile)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
lines := strings.Split(string(fileContents), "\n")
var pre, post []string
var marker int
for i, line := range lines {
if strings.Contains(line, "BEGIN TABLE") {
marker = i
}
pre = append(pre, line)
if marker != 0 {
break
}
}
for i := marker + 1; i < len(lines); i++ {
if !strings.Contains(lines[i], "END TABLE") {
continue
}
marker = i
break
}
for i := marker; i < len(lines); i++ {
post = append(post, lines[i])
}
final := fmt.Sprintf("%s\n\n%s\n\n%s",
strings.Join(pre, "\n"),
strings.Join(table.Marshal(), "\n"),
strings.Join(post, "\n"))
if err := ioutil.WriteFile(permsFile, []byte(final), 0644); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
func (t *Table) Marshal() (ret []string) {
ret = append(ret, "
")
ret = append(ret, " ")
ret = append(ret, t.Header.Marshal()...)
ret = append(ret, " ")
ret = append(ret, " ")
ret = append(ret, t.Body.Marshal()...)
ret = append(ret, " ")
ret = append(ret, "
")
return
}
func (h *Header) Marshal() (ret []string) {
ret = append(ret, fmt.Sprintf(`%s`, indent(4)))
for _, v := range h.Titles {
ret = append(ret,
fmt.Sprintf("%s| %s | ", indent(6), v),
)
}
ret = append(ret, fmt.Sprintf(`%s
`, indent(4)))
return
}
func (b *Body) Marshal() (ret []string) {
for _, v := range b.Resources {
ret = append(ret, v.Marshal()...)
}
return
}
func (r *Resource) Marshal() (ret []string) {
for i, v := range r.Endpoints {
ret = append(ret, fmt.Sprintf(`%s`, indent(4)))
if i == 0 {
ret = append(ret,
fmt.Sprintf(`%s| %s | `, indent(6), len(r.Endpoints), r.Type),
fmt.Sprintf(`%s`, indent(6), len(r.Endpoints)),
fmt.Sprintf(`%s`, indent(8)),
)
for _, s := range r.Scopes {
ret = append(ret,
fmt.Sprintf(`%s- %s
`, indent(10), s),
)
}
ret = append(ret,
fmt.Sprintf(`%s `, indent(8)),
fmt.Sprintf(`%s | `, indent(6)),
)
}
ret = append(ret, v.Marshal()...)
ret = append(ret, fmt.Sprintf(`%s
`, indent(4)))
}
return
}
func (e *Endpoint) Marshal() (ret []string) {
ret = append(ret,
fmt.Sprintf(`%s`, indent(6)),
fmt.Sprintf(`%s%s`, indent(8), escape(e.Path)),
fmt.Sprintf(`%s | `, indent(6)),
fmt.Sprintf(`%s`, indent(6)),
fmt.Sprintf(`%s`, indent(8)),
)
for _, v := range sortedKeys(e.Params) {
ret = append(ret,
fmt.Sprintf(`%s- %s
`, indent(10), v),
fmt.Sprintf(`%s`, indent(12)),
fmt.Sprintf(`%s- `, indent(14)),
fmt.Sprintf(`%s
%s`, indent(16), escape(e.Params[v])),
fmt.Sprintf(`%s `, indent(14)),
fmt.Sprintf(`%s `, indent(12)),
)
}
ret = append(ret,
fmt.Sprintf(`%s `, indent(8)),
fmt.Sprintf(`%s | `, indent(6)),
fmt.Sprintf(`%s`, indent(6)),
fmt.Sprintf(`%s`, indent(8)),
)
for _, v := range e.Actions {
ret = append(ret,
fmt.Sprintf(`%s- `, indent(10)),
fmt.Sprintf(`%s
%s: %s`, indent(12), v.Name, v.Description),
fmt.Sprintf(`%s `, indent(10)),
)
ret = append(ret,
fmt.Sprintf(`%s`, indent(12)),
)
for _, x := range v.Examples {
ret = append(ret,
fmt.Sprintf(`%s%s `, indent(14), escape(x)),
)
}
ret = append(ret,
fmt.Sprintf(`%s `, indent(12)),
)
}
ret = append(ret,
fmt.Sprintf(`%s `, indent(8)),
fmt.Sprintf(`%s | `, indent(6)),
)
return
}
func escape(s string) string {
ret := strings.Replace(s, "<", "<", -1)
return strings.Replace(ret, ">", ">", -1)
}
func indent(num int) string {
return strings.Repeat(" ", num)
}
func sortedKeys(in map[string]string) []string {
out := make([]string, 0, len(in))
for k := range in {
out = append(out, k)
}
sort.Strings(out)
return out
}
func clActions(typ string) []*Action {
listVersion := strings.TrimPrefix(strings.TrimPrefix(typ, "an "), "a ")
return []*Action{
{
Name: "create",
Description: fmt.Sprintf("Create %s", typ),
Examples: []string{
"type=;actions=create",
},
},
{
Name: "list",
Description: fmt.Sprintf("List %ss", listVersion),
Examples: []string{
"type=;actions=list",
},
},
}
}
func rudActions(typ string, pin bool) []*Action {
ret := []*Action{
{
Name: "read",
Description: fmt.Sprintf("Read %s", typ),
Examples: []string{
"id=;actions=read",
},
},
{
Name: "update",
Description: fmt.Sprintf("Update %s", typ),
Examples: []string{
"id=;actions=update",
},
},
{
Name: "delete",
Description: fmt.Sprintf("Delete %s", typ),
Examples: []string{
"id=;actions=delete",
},
},
}
if pin {
ret[0].Examples = append(ret[0].Examples, "id=;type=;actions=read")
ret[1].Examples = append(ret[1].Examples, "id=;type=;actions=update")
ret[2].Examples = append(ret[2].Examples, "id=;type=;actions=delete")
}
return ret
}
var account = &Resource{
Type: "Account",
Scopes: iamScopes,
Endpoints: []*Endpoint{
{
Path: "/accounts",
Params: map[string]string{
"Type": "accounts",
},
Actions: clActions("an account"),
},
{
Path: "/accounts/",
Params: map[string]string{
"ID": "",
"Type": "account",
"Pin": "",
},
Actions: append(
rudActions("an account", true),
&Action{
Name: "set-password",
Description: "Set a password on an account, without requring the current password",
Examples: []string{
"id=;actions=set-password",
"id=;type=;actions=set-password",
},
},
&Action{
Name: "change-password",
Description: "Change a password on an account given the current password",
Examples: []string{
"id=;actions=change-password",
"id=;type=;actions=change-password",
},
},
),
},
},
}
var authMethod = &Resource{
Type: "Auth Method",
Scopes: iamScopes,
Endpoints: []*Endpoint{
{
Path: "/auth-methods",
Params: map[string]string{
"Type": "auth-method",
},
Actions: clActions("an auth method"),
},
{
Path: "/auth-methods/",
Params: map[string]string{
"ID": "",
"Type": "auth-method",
},
Actions: append(
rudActions("an auth method", false),
&Action{
Name: "authenticate",
Description: "Authenticate to an auth method",
Examples: []string{
"id=;actions=authenticate",
},
},
),
},
},
}
var authToken = &Resource{
Type: "Auth Token",
Scopes: iamScopes,
Endpoints: []*Endpoint{
{
Path: "/auth-tokens",
Params: map[string]string{
"Type": "auth-token",
},
Actions: []*Action{
{
Name: "list",
Description: "List auth tokens",
Examples: []string{
"type=;actions=list",
},
},
},
},
{
Path: "/auth-tokens/",
Params: map[string]string{
"ID": "",
"Type": "auth-token",
},
Actions: []*Action{
{
Name: "read",
Description: "Read an auth token",
Examples: []string{
"id=;actions=read",
},
},
{
Name: "delete",
Description: "Delete an auth token",
Examples: []string{
"id=;actions=delete",
},
},
},
},
},
}
var group = &Resource{
Type: "Group",
Scopes: append(iamScopes, infraScope...),
Endpoints: []*Endpoint{
{
Path: "/groups",
Params: map[string]string{
"Type": "group",
},
Actions: clActions("a group"),
},
{
Path: "/groups/",
Params: map[string]string{
"ID": "",
"Type": "group",
},
Actions: append(
rudActions("a group", false),
&Action{
Name: "add-members",
Description: "Add members to a group",
Examples: []string{
"id=;actions=add-members",
},
},
&Action{
Name: "set-members",
Description: "Set the full set of members on a group",
Examples: []string{
"id=;actions=set-members",
},
},
&Action{
Name: "remove-members",
Description: "Remove members from a group",
Examples: []string{
"id=;actions=remove-members",
},
},
),
},
},
}
var host = &Resource{
Type: "Host",
Scopes: infraScope,
Endpoints: []*Endpoint{
{
Path: "/hosts",
Params: map[string]string{
"Type": "host",
},
Actions: clActions("a host"),
},
{
Path: "/hosts/",
Params: map[string]string{
"ID": "",
"Type": "host",
"Pin": "",
},
Actions: rudActions("a host", true),
},
},
}
var hostCatalog = &Resource{
Type: "Host Catalog",
Scopes: infraScope,
Endpoints: []*Endpoint{
{
Path: "/host-catalogs",
Params: map[string]string{
"Type": "host-catalog",
},
Actions: clActions("a host catalog"),
},
{
Path: "/host-catalogs/",
Params: map[string]string{
"ID": "",
"Type": "host-catalog",
},
Actions: rudActions("a host catalog", false),
},
},
}
var hostSet = &Resource{
Type: "Host Set",
Scopes: infraScope,
Endpoints: []*Endpoint{
{
Path: "/host-sets",
Params: map[string]string{
"Type": "host-set",
},
Actions: clActions("a host set"),
},
{
Path: "/targets/",
Params: map[string]string{
"ID": "",
"Type": "host-set",
"Pin": "",
},
Actions: append(
rudActions("a host set", true),
&Action{
Name: "add-hosts",
Description: "Add hosts to a host-set",
Examples: []string{
"id=;actions=add-hosts",
"id=;type=;actions=add-hosts",
},
},
&Action{
Name: "set-hosts",
Description: "Set the full set of hosts on a host set",
Examples: []string{
"id=;actions=set-hosts",
"id=;type=;actions=set-hosts",
},
},
&Action{
Name: "remove-hosts",
Description: "Remove hosts from a host set",
Examples: []string{
"id=;actions=remove-hosts",
"id=;type=;actions=remove-hosts",
},
},
),
},
},
}
var role = &Resource{
Type: "Role",
Scopes: append(iamScopes, infraScope...),
Endpoints: []*Endpoint{
{
Path: "/roles",
Params: map[string]string{
"Type": "role",
},
Actions: clActions("a role"),
},
{
Path: "/roles/",
Params: map[string]string{
"ID": "",
"Type": "role",
},
Actions: append(
rudActions("a role", false),
&Action{
Name: "add-principals",
Description: "Add principals to a role",
Examples: []string{
"id=;actions=add-principals",
},
},
&Action{
Name: "set-principals",
Description: "Set the full set of principals on a role",
Examples: []string{
"id=;actions=set-principals",
},
},
&Action{
Name: "remove-principals",
Description: "Remove principals from a role",
Examples: []string{
"id=;actions=remove-principals",
},
},
&Action{
Name: "add-grants",
Description: "Add grants to a role",
Examples: []string{
"id=;actions=add-grants",
},
},
&Action{
Name: "set-grants",
Description: "Set the full set of grants on a role",
Examples: []string{
"id=;actions=set-grants",
},
},
&Action{
Name: "remove-grants",
Description: "Remove grants from a role",
Examples: []string{
"id=;actions=remove-grants",
},
},
),
},
},
}
var scope = &Resource{
Type: "Scope",
Scopes: iamScopes,
Endpoints: []*Endpoint{
{
Path: "/scopes",
Params: map[string]string{
"Type": "scope",
},
Actions: clActions("a scope"),
},
{
Path: "/scopes/",
Params: map[string]string{
"ID": "",
"Type": "scope",
},
Actions: rudActions("a scope", false),
},
},
}
var session = &Resource{
Type: "Session",
Scopes: infraScope,
Endpoints: []*Endpoint{
{
Path: "/sessions",
Params: map[string]string{
"Type": "session",
},
Actions: []*Action{
{
Name: "list",
Description: "List sessions",
Examples: []string{
"type=;actions=list",
},
},
},
},
{
Path: "/session/",
Params: map[string]string{
"ID": "",
"Type": "session",
},
Actions: []*Action{
{
Name: "read",
Description: "Read a session",
Examples: []string{
"id=;actions=read",
},
},
{
Name: "cancel",
Description: "Cancel a session",
Examples: []string{
"id=;actions=cancel",
},
},
},
},
},
}
var target = &Resource{
Type: "Target",
Scopes: infraScope,
Endpoints: []*Endpoint{
{
Path: "/targets",
Params: map[string]string{
"Type": "target",
},
Actions: clActions("a target"),
},
{
Path: "/targets/",
Params: map[string]string{
"ID": "",
"Type": "target",
},
Actions: append(
rudActions("a target", false),
&Action{
Name: "add-host-sets",
Description: "Add host sets to a target",
Examples: []string{
"id=;actions=add-host-sets",
},
},
&Action{
Name: "set-host-sets",
Description: "Set the full set of host sets on a target",
Examples: []string{
"id=;actions=set-host-sets",
},
},
&Action{
Name: "remove-host-sets",
Description: "Remove host sets from a target",
Examples: []string{
"id=;actions=remove-host-sets",
},
},
&Action{
Name: "authorize-session",
Description: "Authorize a session via the target",
Examples: []string{
"id=;actions=authorize-session",
},
},
),
},
},
}
var user = &Resource{
Type: "User",
Scopes: iamScopes,
Endpoints: []*Endpoint{
{
Path: "/users",
Params: map[string]string{
"Type": "user",
},
Actions: clActions("a user"),
},
{
Path: "/users/",
Params: map[string]string{
"ID": "",
"Type": "user",
},
Actions: append(
rudActions("a user", false),
&Action{
Name: "add-accounts",
Description: "Add accounts to a user",
Examples: []string{
"id=;actions=add-accounts",
},
},
&Action{
Name: "set-accounts",
Description: "Set the full set of accounts on a user",
Examples: []string{
"id=;actions=set-accounts",
},
},
&Action{
Name: "remove-accounts",
Description: "Remove accounts from a user",
Examples: []string{
"id=;actions=remove-accounts",
},
},
),
},
},
}