Co-authored-by: Jonas Plum <git@jonasplum.de>
This commit is contained in:
Jonas Plum
2022-10-01 21:38:13 +02:00
committed by GitHub
parent 4eb0658888
commit f73e91d142
56 changed files with 402 additions and 1760 deletions

View File

@@ -78,21 +78,6 @@ jobs:
- run: go tool cover -func=cover.out
- uses: codecov/codecov-action@v3
gocap:
name: gocap
runs-on: ubuntu-latest
steps:
- uses: actions/setup-go@v3
with: { go-version: '1.18' }
- uses: actions/checkout@v3
- run: go mod download
- run: go install github.com/cugu/gocap@main
- run: |
mkdir -p ui/dist/img
touch ui/dist/index.html ui/dist/favicon.ico ui/dist/manifest.json ui/dist/img/fake.png
- run: go list --json ./cmd/catalyst
- run: gocap check ./cmd/catalyst
cypress:
strategy:
matrix:

View File

@@ -3,6 +3,7 @@ run:
timeout: 5m
skip-dirs:
- generated
- internal
linters:
enable:
- asciicheck

98
auth.go Normal file
View File

@@ -0,0 +1,98 @@
package catalyst
import (
"context"
"crypto/sha256"
"errors"
"fmt"
maut "github.com/jonas-plum/maut/auth"
"github.com/SecurityBrewery/catalyst/database"
"github.com/SecurityBrewery/catalyst/generated/model"
)
type catalystResolver struct {
database *database.Database
}
func newCatalystResolver(db *database.Database) *catalystResolver {
return &catalystResolver{
database: db,
}
}
func (c *catalystResolver) UserCreateIfNotExists(ctx context.Context, user *maut.User, password string) (err error) {
if user != nil {
if _, err := c.database.UserGet(ctx, user.ID); err == nil {
return nil
}
}
if user == nil || user.APIKey {
_, err = c.database.UserCreateSetupAPIKey(ctx, password)
} else {
_, err = c.database.UserCreate(ctx, &model.UserForm{
Apikey: user.APIKey,
Blocked: user.Blocked,
ID: user.ID,
Password: &password,
Roles: user.Roles,
})
}
return err
}
func (c *catalystResolver) User(ctx context.Context, userID string) (*maut.User, error) {
user, err := c.database.UserGet(ctx, userID)
if err != nil {
return nil, err
}
return mapMautUser(user), nil
}
func (c *catalystResolver) UserAPIKeyByHash(ctx context.Context, key string) (*maut.User, error) {
sha256Hash := fmt.Sprintf("%x", sha256.Sum256([]byte(key)))
user, err := c.database.UserAPIKeyByHash(ctx, sha256Hash)
if err != nil {
return nil, err
}
return mapMautUser(user), nil
}
func (c *catalystResolver) UserByIDAndPassword(ctx context.Context, username string, password string) (*maut.User, error) {
user, err := c.database.UserByIDAndPassword(ctx, username, password)
if err != nil {
return nil, err
}
return mapMautUser(user), nil
}
func (c *catalystResolver) Role(ctx context.Context, roleID string) (r *maut.Role, err error) {
switch roleID {
case "admin":
return Admin, nil
case "engineer":
return engineer, nil
case "analyst":
return analyst, nil
}
return nil, errors.New("role not found")
}
func mapMautUser(user *model.UserResponse) *maut.User {
return &maut.User{
ID: user.ID,
APIKey: user.Apikey,
Blocked: user.Blocked,
// Email: user.Email, // TODO
// Groups: user.Groups, // TODO
// Name: user.Name, // TODO
Roles: user.Roles,
}
}

View File

@@ -1,475 +0,0 @@
package auth
import (
"context"
"crypto/rand"
"crypto/sha256"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"log"
"net/http"
"strings"
"time"
"github.com/coreos/go-oidc/v3/oidc"
"golang.org/x/exp/slices"
"golang.org/x/oauth2"
"github.com/SecurityBrewery/catalyst/database"
"github.com/SecurityBrewery/catalyst/database/busdb"
"github.com/SecurityBrewery/catalyst/generated/api"
"github.com/SecurityBrewery/catalyst/generated/model"
"github.com/SecurityBrewery/catalyst/hooks"
"github.com/SecurityBrewery/catalyst/role"
)
type Config struct {
SimpleAuthEnable bool
APIKeyAuthEnable bool
OIDCAuthEnable bool
OIDCIssuer string
AuthURL string
OAuth2 *oauth2.Config
UserCreateConfig *UserCreateConfig
provider *oidc.Provider
}
type UserCreateConfig struct {
AuthBlockNew bool
AuthDefaultRoles []role.Role
AuthAdminUsers []string
OIDCClaimUsername string
OIDCClaimEmail string
OIDCClaimName string
// OIDCClaimGroups string
}
func (c *Config) Verifier(ctx context.Context) (*oidc.IDTokenVerifier, error) {
if c.provider == nil {
if err := c.Load(ctx); err != nil {
return nil, err
}
}
config := &oidc.Config{ClientID: c.OAuth2.ClientID}
if c.AuthURL != "" {
config.SkipIssuerCheck = true
}
return c.provider.Verifier(config), nil
}
func (c *Config) Load(ctx context.Context) error {
for {
provider, err := oidc.NewProvider(ctx, c.OIDCIssuer)
if err == nil {
c.provider = provider
c.OAuth2.Endpoint = provider.Endpoint()
if c.AuthURL != "" {
c.OAuth2.Endpoint.AuthURL = c.AuthURL
}
break
}
if errors.Is(err, context.DeadlineExceeded) {
return errors.New("could not load provider")
}
log.Printf("could not load oidc provider: %s, retrying in 10 seconds\n", err)
time.Sleep(time.Second * 10)
}
return nil
}
func Authenticate(db *database.Database, config *Config, jar *Jar) func(next http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
keyHeader := r.Header.Get("PRIVATE-TOKEN")
authHeader := r.Header.Get("Authorization")
switch {
case keyHeader != "":
if config.APIKeyAuthEnable {
keyAuth(db, keyHeader)(next).ServeHTTP(w, r)
} else {
api.JSONErrorStatus(w, http.StatusUnauthorized, errors.New("API Key authentication not enabled"))
}
case authHeader != "":
if config.OIDCAuthEnable {
iss := config.OIDCIssuer
bearerAuth(db, authHeader, iss, config, jar)(next).ServeHTTP(w, r)
} else {
api.JSONErrorStatus(w, http.StatusUnauthorized, errors.New("OIDC authentication not enabled"))
}
default:
sessionAuth(db, config, jar)(next).ServeHTTP(w, r)
}
})
}
}
func bearerAuth(db *database.Database, authHeader string, iss string, config *Config, jar *Jar) func(next http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if !strings.HasPrefix(authHeader, "Bearer ") {
api.JSONErrorStatus(w, http.StatusUnauthorized, errors.New("no bearer token"))
return
}
claims, apiError := verifyClaims(r, config, authHeader[7:])
if apiError != nil {
api.JSONErrorStatus(w, apiError.Status, apiError.Internal)
return
}
// if claims.Iss != iss {
// return &api.HTTPError{Status: http.StatusInternalServerError, Internal: "wrong issuer"})
// return
// }
jar.setClaimsCookie(w, claims)
r, err := setContextClaims(r, db, claims, config)
if err != nil {
api.JSONErrorStatus(w, http.StatusInternalServerError, fmt.Errorf("could not load user: %w", err))
return
}
next.ServeHTTP(w, r)
})
}
}
func keyAuth(db *database.Database, keyHeader string) func(next http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
h := fmt.Sprintf("%x", sha256.Sum256([]byte(keyHeader)))
key, err := db.UserAPIKeyByHash(r.Context(), h)
if err != nil {
api.JSONErrorStatus(w, http.StatusInternalServerError, fmt.Errorf("could not verify private token: %w", err))
return
}
r = setContextUser(r, key, db.Hooks)
next.ServeHTTP(w, r)
})
}
}
func sessionAuth(db *database.Database, config *Config, jar *Jar) func(next http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
claims, noCookie, err := jar.claimsCookie(r)
if err != nil {
deleteClaimsCookie(w)
api.JSONError(w, err)
return
}
if noCookie {
redirectToLogin(config, jar)(w, r)
return
}
r, err = setContextClaims(r, db, claims, config)
if err != nil {
api.JSONErrorStatus(w, http.StatusInternalServerError, fmt.Errorf("could not load user: %w", err))
return
}
next.ServeHTTP(w, r)
})
}
}
func setContextClaims(r *http.Request, db *database.Database, claims map[string]any, config *Config) (*http.Request, error) {
newUser, newSetting, err := mapUserAndSettings(claims, config.UserCreateConfig)
if err != nil {
return nil, err
}
if _, ok := busdb.UserFromContext(r.Context()); !ok {
r = busdb.SetContext(r, &model.UserResponse{ID: "auth", Roles: []string{role.Admin}, Apikey: false, Blocked: false})
}
user, err := db.UserGetOrCreate(r.Context(), newUser)
if err != nil {
return nil, err
}
if _, err = db.UserDataGetOrCreate(r.Context(), newUser.ID, newSetting); err != nil {
return nil, err
}
return setContextUser(r, user, db.Hooks), nil
}
func setContextUser(r *http.Request, user *model.UserResponse, hooks *hooks.Hooks) *http.Request {
groups, err := hooks.GetGroups(r.Context(), user.ID)
if err == nil {
r = busdb.SetGroupContext(r, groups)
}
return busdb.SetContext(r, user)
}
func mapUserAndSettings(claims map[string]any, config *UserCreateConfig) (*model.UserForm, *model.UserData, error) {
// handle Bearer tokens
// if typ, ok := claims["typ"]; ok && typ == "Bearer" {
// return &model.User{
// Username: "bot",
// Blocked: false,
// Email: pointer.String("bot@example.org"),
// Roles: []string{"user:read", "settings:read", "ticket", "backup:read", "backup:restore"},
// Name: pointer.String("Bot"),
// }, nil
// }
username, err := getString(claims, config.OIDCClaimUsername)
if err != nil {
return nil, nil, err
}
email, err := getString(claims, config.OIDCClaimEmail)
if err != nil {
email = ""
}
name, err := getString(claims, config.OIDCClaimName)
if err != nil {
name = ""
}
roles := role.Strings(config.AuthDefaultRoles)
if slices.Contains(config.AuthAdminUsers, username) {
roles = append(roles, role.Admin)
}
return &model.UserForm{
ID: username,
Blocked: config.AuthBlockNew,
Roles: roles,
}, &model.UserData{
Email: &email,
Name: &name,
}, nil
}
func getString(m map[string]any, key string) (string, error) {
if v, ok := m[key]; ok {
if s, ok := v.(string); ok {
return s, nil
}
return "", fmt.Errorf("mapping of %s failed, wrong type (%T)", key, v)
}
return "", fmt.Errorf("mapping of %s failed, missing value", key)
}
func redirectToLogin(config *Config, jar *Jar) func(http.ResponseWriter, *http.Request) {
if config.SimpleAuthEnable {
return func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "/", http.StatusFound)
}
}
if config.OIDCAuthEnable {
return redirectToOIDCLogin(config, jar)
}
return func(writer http.ResponseWriter, request *http.Request) {
api.JSONErrorStatus(writer, http.StatusForbidden, errors.New("unauthenticated"))
}
}
func redirectToOIDCLogin(config *Config, jar *Jar) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
state, err := state()
if err != nil {
api.JSONErrorStatus(w, http.StatusInternalServerError, errors.New("generating state failed"))
return
}
jar.setStateCookie(w, state)
http.Redirect(w, r, config.OAuth2.AuthCodeURL(state), http.StatusFound)
}
}
func AuthorizeBlockedUser() func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
user, ok := busdb.UserFromContext(r.Context())
if !ok {
api.JSONErrorStatus(w, http.StatusInternalServerError, errors.New("no user in context"))
return
}
if user.Blocked {
api.JSONErrorStatus(w, http.StatusForbidden, errors.New("user is blocked"))
return
}
next.ServeHTTP(w, r)
})
}
}
func AuthorizeRole(roles []string) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
user, ok := busdb.UserFromContext(r.Context())
if !ok {
api.JSONErrorStatus(w, http.StatusInternalServerError, errors.New("no user in context"))
return
}
if !role.UserHasRoles(user, role.FromStrings(roles)) {
api.JSONErrorStatus(w, http.StatusForbidden, fmt.Errorf("missing role %s has %s", roles, user.Roles))
return
}
next.ServeHTTP(w, r)
})
}
}
func login(db *database.Database, jar *Jar) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
type credentials struct {
Username string
Password string
}
cr := credentials{}
if err := json.NewDecoder(r.Body).Decode(&cr); err != nil {
api.JSONErrorStatus(w, http.StatusUnauthorized, errors.New("wrong username or password"))
return
}
user, err := db.UserByIDAndPassword(r.Context(), cr.Username, cr.Password)
if err != nil {
api.JSONErrorStatus(w, http.StatusUnauthorized, errors.New("wrong username or password"))
return
}
userdata, err := db.UserDataGet(r.Context(), user.ID)
if err != nil {
api.JSONErrorStatus(w, http.StatusUnauthorized, errors.New("no userdata"))
return
}
jar.setClaimsCookie(w, map[string]any{
"preferred_username": user.ID,
"name": userdata.Name,
"email": userdata.Email,
})
b, _ := json.Marshal(map[string]string{"login": "successful"})
_, _ = w.Write(b)
}
}
func logout() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
deleteClaimsCookie(w)
http.Redirect(w, r, "/", http.StatusFound)
}
}
func callback(config *Config, jar *Jar) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
state, err := jar.stateCookie(r)
if err != nil || state == "" {
api.JSONErrorStatus(w, http.StatusInternalServerError, errors.New("state missing"))
return
}
if state != r.URL.Query().Get("state") {
api.JSONErrorStatus(w, http.StatusInternalServerError, errors.New("state mismatch"))
return
}
oauth2Token, err := config.OAuth2.Exchange(r.Context(), r.URL.Query().Get("code"))
if err != nil {
api.JSONErrorStatus(w, http.StatusInternalServerError, fmt.Errorf("oauth2 exchange failed: %w", err))
return
}
// Extract the ID Token from OAuth2 token.
rawIDToken, ok := oauth2Token.Extra("id_token").(string)
if !ok {
api.JSONErrorStatus(w, http.StatusInternalServerError, errors.New("missing id token"))
return
}
claims, apiError := verifyClaims(r, config, rawIDToken)
if apiError != nil {
api.JSONErrorStatus(w, apiError.Status, apiError.Internal)
return
}
jar.setClaimsCookie(w, claims)
http.Redirect(w, r, "/ui/", http.StatusFound)
}
}
func state() (string, error) {
rnd := make([]byte, 32)
if _, err := rand.Read(rnd); err != nil {
return "", err
}
return base64.URLEncoding.EncodeToString(rnd), nil
}
func verifyClaims(r *http.Request, config *Config, rawIDToken string) (map[string]any, *api.HTTPError) {
verifier, err := config.Verifier(r.Context())
if err != nil {
return nil, &api.HTTPError{Status: http.StatusUnauthorized, Internal: fmt.Errorf("could not verify: %w", err)}
}
authToken, err := verifier.Verify(r.Context(), rawIDToken)
if err != nil {
return nil, &api.HTTPError{Status: http.StatusInternalServerError, Internal: fmt.Errorf("could not verify bearer token: %w", err)}
}
var claims map[string]any
if err := authToken.Claims(&claims); err != nil {
return nil, &api.HTTPError{Status: http.StatusInternalServerError, Internal: fmt.Errorf("failed to parse claims: %w", err)}
}
return claims, nil
}

View File

@@ -1,84 +0,0 @@
package auth
import (
"log"
"net/http"
"github.com/gorilla/securecookie"
"golang.org/x/crypto/argon2"
"github.com/SecurityBrewery/catalyst/generated/time"
)
const (
stateSessionCookie = "state"
userSessionCookie = "user"
)
type Jar struct {
store *securecookie.SecureCookie
}
func NewJar(secret []byte) *Jar {
hashSalt := securecookie.GenerateRandomKey(64)
blockSalt := securecookie.GenerateRandomKey(64)
return &Jar{
store: securecookie.New(
argon2.IDKey(secret, hashSalt, 1, 64*1024, 4, 64),
argon2.IDKey(secret, blockSalt, 1, 64*1024, 4, 32),
),
}
}
func (j *Jar) setStateCookie(w http.ResponseWriter, state string) {
encoded, err := j.store.Encode(userSessionCookie, state)
if err != nil {
log.Println(err)
return
}
tomorrow := time.Now().AddDate(0, 0, 1)
http.SetCookie(w, &http.Cookie{Name: stateSessionCookie, Value: encoded, Path: "/", Expires: tomorrow})
}
func (j *Jar) stateCookie(r *http.Request) (string, error) {
stateCookie, err := r.Cookie(stateSessionCookie)
if err != nil {
return "", err
}
var state string
err = j.store.Decode(userSessionCookie, stateCookie.Value, &state)
return state, err
}
func (j *Jar) setClaimsCookie(w http.ResponseWriter, claims map[string]any) {
encoded, err := j.store.Encode(userSessionCookie, claims)
if err != nil {
log.Println(err)
return
}
tomorrow := time.Now().AddDate(0, 0, 1)
http.SetCookie(w, &http.Cookie{Name: userSessionCookie, Value: encoded, Path: "/", Expires: tomorrow})
}
func deleteClaimsCookie(w http.ResponseWriter) {
http.SetCookie(w, &http.Cookie{Name: userSessionCookie, Value: "", MaxAge: -1})
}
func (j *Jar) claimsCookie(r *http.Request) (map[string]any, bool, error) {
userCookie, err := r.Cookie(userSessionCookie)
if err != nil {
return nil, true, nil
}
var claims map[string]any
err = j.store.Decode(userSessionCookie, userCookie.Value, &claims)
return claims, false, err
}

View File

@@ -1,43 +0,0 @@
package auth
import (
"encoding/json"
"net/http"
"github.com/go-chi/chi/v5"
"github.com/SecurityBrewery/catalyst/database"
)
func Server(config *Config, catalystDatabase *database.Database, jar *Jar) *chi.Mux {
server := chi.NewRouter()
server.Get("/config", hasOIDC(config))
if config.OIDCAuthEnable {
server.Get("/callback", callback(config, jar))
server.Get("/oidclogin", redirectToOIDCLogin(config, jar))
}
if config.SimpleAuthEnable {
server.Post("/login", login(catalystDatabase, jar))
}
server.Post("/logout", logout())
return server
}
func hasOIDC(config *Config) func(writer http.ResponseWriter, request *http.Request) {
return func(writer http.ResponseWriter, request *http.Request) {
b, err := json.Marshal(map[string]any{
"simple": config.SimpleAuthEnable,
"oidc": config.OIDCAuthEnable,
})
if err != nil {
writer.WriteHeader(http.StatusInternalServerError)
return
}
_, _ = writer.Write(b)
}
}

View File

@@ -4,12 +4,12 @@ import (
"context"
"log"
maut "github.com/jonas-plum/maut/auth"
"github.com/SecurityBrewery/catalyst/bus"
"github.com/SecurityBrewery/catalyst/database"
"github.com/SecurityBrewery/catalyst/database/busdb"
"github.com/SecurityBrewery/catalyst/generated/model"
"github.com/SecurityBrewery/catalyst/generated/time"
"github.com/SecurityBrewery/catalyst/role"
)
type busService struct {
@@ -30,9 +30,9 @@ func New(apiURL, apikey, network string, catalystBus *bus.Bus, db *database.Data
func busContext() context.Context {
// TODO: change roles?
bot := &model.UserResponse{ID: "bot", Roles: []string{role.Admin}}
bot := &maut.User{ID: "bot", Roles: []string{maut.AdminRole}}
return busdb.UserContext(context.Background(), bot)
return maut.UserContext(context.Background(), bot, nil) // TODO add permissions ?
}
func (h *busService) logRequest(msg *bus.RequestMsg) {

View File

@@ -8,15 +8,14 @@ import (
"time"
"github.com/arangodb/go-driver"
maut "github.com/jonas-plum/maut/auth"
"github.com/SecurityBrewery/catalyst"
"github.com/SecurityBrewery/catalyst/cmd"
"github.com/SecurityBrewery/catalyst/database/busdb"
"github.com/SecurityBrewery/catalyst/generated/api"
"github.com/SecurityBrewery/catalyst/generated/model"
"github.com/SecurityBrewery/catalyst/generated/pointer"
"github.com/SecurityBrewery/catalyst/hooks"
"github.com/SecurityBrewery/catalyst/role"
"github.com/SecurityBrewery/catalyst/test"
)
@@ -36,8 +35,8 @@ func main() {
log.Fatal(err)
}
demoUser := &model.UserResponse{ID: "demo", Roles: []string{role.Admin}}
ctx := busdb.UserContext(context.Background(), demoUser)
demoUser := &maut.User{ID: "demo", Roles: []string{maut.AdminRole}}
ctx := maut.UserContext(context.Background(), demoUser, catalyst.Admin.Permissions)
if err := test.SetupTestData(ctx, theCatalyst.DB); err != nil {
log.Fatal(err)
}

View File

@@ -6,13 +6,12 @@ import (
"github.com/alecthomas/kong"
kongyaml "github.com/alecthomas/kong-yaml"
"github.com/coreos/go-oidc/v3/oidc"
maut "github.com/jonas-plum/maut/auth"
"golang.org/x/exp/slices"
"golang.org/x/oauth2"
"github.com/SecurityBrewery/catalyst"
"github.com/SecurityBrewery/catalyst/auth"
"github.com/SecurityBrewery/catalyst/database"
"github.com/SecurityBrewery/catalyst/role"
"github.com/SecurityBrewery/catalyst/storage"
)
@@ -73,10 +72,6 @@ func ParseCatalystConfig() (*catalyst.Config, error) {
}
func MapConfig(cli CLI) (*catalyst.Config, error) {
roles := role.Explode(role.Analyst)
roles = append(roles, role.Explodes(cli.AuthDefaultRoles)...)
roles = role.Explodes(role.Strings(roles))
scopes := slices.Compact(append([]string{oidc.ScopeOpenID, "profile", "email"}, cli.OIDCScopes...))
config := &catalyst.Config{
IndexPath: cli.IndexPath,
@@ -87,32 +82,34 @@ func MapConfig(cli CLI) (*catalyst.Config, error) {
Password: cli.ArangoDBPassword,
},
Storage: &storage.Config{Host: cli.S3Host, User: cli.S3User, Password: cli.S3Password},
Secret: []byte(cli.Secret),
ExternalAddress: cli.ExternalAddress,
InternalAddress: cli.CatalystAddress,
Port: cli.Port,
Auth: &auth.Config{
Auth: &maut.Config{
CookieSecret: []byte(cli.Secret),
SimpleAuthEnable: false, // cli.SimpleAuthEnable,
APIKeyAuthEnable: cli.APIKeyAuthEnable,
OIDCAuthEnable: cli.OIDCEnable,
OIDCIssuer: cli.OIDCIssuer,
AuthURL: cli.AuthURL,
// InitialUser: "",
// InitialPassword: "",
InitialAPIKey: cli.InitialAPIKey,
OIDCIssuer: cli.OIDCIssuer,
AuthURL: cli.AuthURL,
OAuth2: &oauth2.Config{
ClientID: cli.OIDCClientID,
ClientSecret: cli.OIDCClientSecret,
RedirectURL: cli.ExternalAddress + "/auth/callback",
Scopes: scopes,
},
UserCreateConfig: &auth.UserCreateConfig{
UserCreateConfig: &maut.UserCreateConfig{
AuthBlockNew: cli.AuthBlockNew,
AuthDefaultRoles: roles,
AuthDefaultRoles: cli.AuthDefaultRoles,
AuthAdminUsers: cli.AuthAdminUsers,
OIDCClaimUsername: cli.OIDCClaimUsername,
OIDCClaimEmail: cli.OIDCClaimEmail,
OIDCClaimName: cli.OIDCClaimName,
},
},
InitialAPIKey: cli.InitialAPIKey,
}
return config, nil

View File

@@ -1,38 +0,0 @@
package busdb
import (
"context"
"net/http"
"github.com/SecurityBrewery/catalyst/generated/model"
"github.com/SecurityBrewery/catalyst/role"
)
type contextKey string
const (
userContextKey contextKey = "user"
groupContextKey contextKey = "groups"
)
func SetContext(r *http.Request, user *model.UserResponse) *http.Request {
user.Roles = role.Strings(role.Explodes(user.Roles))
return r.WithContext(context.WithValue(r.Context(), userContextKey, user))
}
func SetGroupContext(r *http.Request, groups []string) *http.Request {
return r.WithContext(context.WithValue(r.Context(), groupContextKey, groups))
}
func UserContext(ctx context.Context, user *model.UserResponse) context.Context {
user.Roles = role.Strings(role.Explodes(user.Roles))
return context.WithValue(ctx, userContextKey, user)
}
func UserFromContext(ctx context.Context) (*model.UserResponse, bool) {
u, ok := ctx.Value(userContextKey).(*model.UserResponse)
return u, ok
}

View File

@@ -6,6 +6,7 @@ import (
"strings"
"github.com/arangodb/go-driver"
maut "github.com/jonas-plum/maut/auth"
"github.com/SecurityBrewery/catalyst/bus"
"github.com/SecurityBrewery/catalyst/generated/model"
@@ -15,7 +16,7 @@ import (
const LogCollectionName = "logs"
func (db *BusDatabase) LogCreate(ctx context.Context, logType, reference, message string) (*model.LogEntry, error) {
user, ok := UserFromContext(ctx)
user, _, ok := maut.UserFromContext(ctx)
if !ok {
return nil, errors.New("no user in context")
}

View File

@@ -62,6 +62,8 @@ func generateMigrations() ([]Migration, error) {
&updateDocument[model.Settings]{ID: "update-settings-global-1", Collection: "settings", Key: "global", Document: &model.Settings{ArtifactStates: []*model.Type{{Icon: "mdi-help-circle-outline", ID: "unknown", Name: "Unknown", Color: pointer.String(model.TypeColorInfo)}, {Icon: "mdi-skull", ID: "malicious", Name: "Malicious", Color: pointer.String(model.TypeColorError)}, {Icon: "mdi-check", ID: "clean", Name: "Clean", Color: pointer.String(model.TypeColorSuccess)}}, ArtifactKinds: []*model.Type{{Icon: "mdi-server", ID: "asset", Name: "Asset"}, {Icon: "mdi-bullseye", ID: "ioc", Name: "IOC"}}, Timeformat: "yyyy-MM-dd hh:mm:ss"}},
&updateSchema{ID: "update-user-simple-login", Name: "users", DataType: "user", Schema: `{"type":"object","properties":{"apikey":{"type":"boolean"},"blocked":{"type":"boolean"},"roles":{"items":{"type":"string"},"type":"array"},"salt":{"type":"string"},"sha256":{"type":"string"},"sha512":{"type":"string"}},"required":["blocked","apikey","roles"],"$id":"#/definitions/User"}`},
&mapRoles{ID: "simplify-roles"},
}, nil
}
@@ -232,3 +234,17 @@ func (m *updateDocument[T]) Migrate(ctx context.Context, driver driver.Database)
return err
}
type mapRoles struct {
ID string
}
func (m mapRoles) MID() string {
return m.ID
}
func (m mapRoles) Migrate(ctx context.Context, driver driver.Database) error {
_, err := driver.Query(ctx, "FOR u IN users UPDATE u WITH {roles: u.roles[*].name} IN users", nil)
return err
}

View File

@@ -7,6 +7,7 @@ import (
"github.com/arangodb/go-driver"
"github.com/iancoleman/strcase"
maut "github.com/jonas-plum/maut/auth"
"github.com/mingrammer/commonregex"
"github.com/SecurityBrewery/catalyst/bus"
@@ -110,7 +111,7 @@ func (db *Database) AddComment(ctx context.Context, id int64, comment *model.Com
}
if comment.Creator == nil || *comment.Creator == "" {
user, exists := busdb.UserFromContext(ctx)
user, _, exists := maut.UserFromContext(ctx)
if !exists {
return nil, errors.New("no user in context")
}

View File

@@ -11,12 +11,12 @@ import (
"github.com/arangodb/go-driver"
"github.com/iancoleman/strcase"
maut "github.com/jonas-plum/maut/auth"
"github.com/SecurityBrewery/catalyst/database/busdb"
"github.com/SecurityBrewery/catalyst/generated/model"
"github.com/SecurityBrewery/catalyst/generated/pointer"
"github.com/SecurityBrewery/catalyst/generated/time"
"github.com/SecurityBrewery/catalyst/role"
)
var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_")
@@ -35,11 +35,9 @@ func generateKey() string {
}
func toUser(user *model.UserForm, salt, sha256, sha512 *string) *model.User {
roles := []string{}
roles = append(roles, role.Strings(role.Explodes(user.Roles))...)
u := &model.User{
Blocked: user.Blocked,
Roles: roles,
Roles: user.Roles,
Salt: salt,
Sha256: sha256,
Sha512: sha512,
@@ -94,7 +92,7 @@ func (db *Database) UserCreate(ctx context.Context, newUser *model.UserForm) (*m
var key, salt, sha256Hash, sha512Hash *string
if newUser.Apikey {
key, sha256Hash = generateAPIKey()
} else {
} else if newUser.Password != nil {
salt, sha512Hash = hashUserPassword(newUser)
}
@@ -111,7 +109,7 @@ func (db *Database) UserCreate(ctx context.Context, newUser *model.UserForm) (*m
func (db *Database) UserCreateSetupAPIKey(ctx context.Context, key string) (*model.UserResponse, error) {
newUser := &model.UserForm{
ID: "setup",
Roles: []string{role.Admin},
Roles: []string{maut.AdminRole},
Apikey: true,
Blocked: false,
}

View File

@@ -28,16 +28,6 @@ paths:
- { icon: "mdi-help-circle-outline", id: "unknown", name: "Unknown", color: "info" }
- { icon: "mdi-skull", id: "malicious", name: "Malicious", color: "error" }
- { icon: "mdi-check", id: "clean", name: "Clean", color: "success" }
roles: [
"admin:backup:read", "admin:backup:restore", "admin:dashboard:write", "admin:group:write", "admin:job:read", "admin:job:write",
"admin:log:read", "admin:settings:write", "admin:ticket:delete", "admin:user:write", "admin:userdata:read",
"admin:userdata:write", "analyst:automation:read",
"analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:dashboard:read",
"analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read",
"analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write",
"analyst:tickettype:read", "analyst:user:read", "engineer:automation:write",
"engineer:playbook:write", "engineer:rule:write", "engineer:template:write",
"engineer:tickettype:write" ]
security: [ { roles: [ "settings:read" ] } ]
post:
tags: [ "settings" ]
@@ -66,16 +56,6 @@ paths:
- { icon: "mdi-help-circle-outline", id: "unknown", name: "Unknown", color: "info" }
- { icon: "mdi-skull", id: "malicious", name: "Malicious", color: "error" }
- { icon: "mdi-check", id: "clean", name: "Clean", color: "success" }
roles: [
"admin:backup:read", "admin:backup:restore", "admin:dashboard:write", "admin:group:write", "admin:job:read", "admin:job:write",
"admin:log:read", "admin:settings:write", "admin:ticket:delete", "admin:user:write", "admin:userdata:read",
"admin:userdata:write", "analyst:automation:read",
"analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:dashboard:read",
"analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read",
"analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write",
"analyst:tickettype:read", "analyst:user:read", "engineer:automation:write",
"engineer:playbook:write", "engineer:rule:write", "engineer:template:write",
"engineer:tickettype:write" ]
security: [ { roles: [ "settings:write" ] } ]
definitions:

View File

@@ -12,7 +12,7 @@ paths:
description: "successful operation"
schema: { $ref: "#/definitions/UserResponse" }
examples:
test: { id: bob, roles: [ "admin:backup:read", "admin:backup:restore", "admin:dashboard:write", "admin:group:write", "admin:job:read", "admin:job:write", "admin:log:read", "admin:settings:write", "admin:ticket:delete", "admin:user:write", "admin:userdata:read", "admin:userdata:write", "analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:dashboard:read","analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read", "engineer:automation:write", "engineer:playbook:write", "engineer:rule:write", "engineer:template:write", "engineer:tickettype:write" ], blocked: false, apikey: false }
test: { id: bob, roles: [ "admin" ], blocked: false, apikey: false }
security: [ { roles: [ "currentuser:read" ] } ]
/users:
@@ -26,8 +26,8 @@ paths:
schema: { type: array, items: { $ref: "#/definitions/UserResponse" } }
examples:
test:
- { id: bob, blocked: false, roles: [ "admin:backup:read", "admin:backup:restore", "admin:dashboard:write", "admin:group:write", "admin:job:read", "admin:job:write", "admin:log:read", "admin:settings:write", "admin:ticket:delete", "admin:user:write", "admin:userdata:read", "admin:userdata:write", "analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:dashboard:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read", "engineer:automation:write", "engineer:playbook:write", "engineer:rule:write", "engineer:template:write", "engineer:tickettype:write" ], apikey: false }
- { id: script, roles: [ "analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:dashboard:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read", "engineer:automation:write", "engineer:playbook:write", "engineer:rule:write", "engineer:template:write", "engineer:tickettype:write" ], blocked: false, apikey: true }
- { id: bob, blocked: false, roles: [ "admin" ], apikey: false }
- { id: script, roles: [ "engineer" ], blocked: false, apikey: true }
security: [ { roles: [ "user:read" ] } ]
post:
tags: [ "users" ]
@@ -40,7 +40,7 @@ paths:
description: "successful operation"
schema: { $ref: "#/definitions/NewUserResponse" }
examples:
test: { id: "syncscript", roles: [ "analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:dashboard:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read" ], secret: "v39bOuobnlEljfWzjAgoKzhmnh1xSMxH", blocked: false }
test: { id: "syncscript", roles: [ "analyst" ], secret: "v39bOuobnlEljfWzjAgoKzhmnh1xSMxH", blocked: false }
security: [ { roles: [ "user:write" ] } ]
/users/{id}:
get:
@@ -54,7 +54,7 @@ paths:
description: "successful operation"
schema: { $ref: "#/definitions/UserResponse" }
examples:
test: { id: "script", roles: [ "analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:dashboard:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read", "engineer:automation:write", "engineer:playbook:write", "engineer:rule:write", "engineer:template:write", "engineer:tickettype:write" ], blocked: false, apikey: true }
test: { id: "script", roles: [ "engineer" ], blocked: false, apikey: true }
security: [ { roles: [ "user:read" ] } ]
put:
tags: [ "users" ]
@@ -70,7 +70,7 @@ paths:
examples:
test:
id: bob
roles: [ "admin:backup:read", "admin:backup:restore", "admin:dashboard:write", "admin:group:write", "admin:job:read", "admin:job:write", "admin:log:read", "admin:settings:write", "admin:ticket:delete", "admin:user:write", "admin:userdata:read", "admin:userdata:write", "analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:dashboard:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read", "engineer:automation:write", "engineer:playbook:write", "engineer:rule:write", "engineer:template:write", "engineer:tickettype:write" ]
roles: [ "analyst", "admin" ]
apikey: false
blocked: false
security: [ { roles: [ "user:write" ] } ]

View File

@@ -14,12 +14,12 @@ import (
"github.com/aws/aws-sdk-go/service/s3"
"github.com/aws/aws-sdk-go/service/s3/s3manager"
"github.com/go-chi/chi/v5"
maut "github.com/jonas-plum/maut/auth"
tusd "github.com/tus/tusd/pkg/handler"
"github.com/tus/tusd/pkg/s3store"
"github.com/SecurityBrewery/catalyst/bus"
"github.com/SecurityBrewery/catalyst/database"
"github.com/SecurityBrewery/catalyst/database/busdb"
"github.com/SecurityBrewery/catalyst/generated/api"
"github.com/SecurityBrewery/catalyst/generated/model"
"github.com/SecurityBrewery/catalyst/storage"
@@ -57,7 +57,7 @@ func tusdUpload(db *database.Database, catalystBus *bus.Bus, client *s3.S3, exte
}
userID := "unknown"
user, ok := busdb.UserFromContext(r.Context())
user, _, ok := maut.UserFromContext(r.Context())
if ok {
userID = user.ID
}

View File

@@ -23,6 +23,7 @@ mv generated/openapi.json generated/catalyst.json
echo generate server and tests
swagger-go-chi generated/community.yml generated
rm -rf generated/auth generated/cli
find generated -type f -name "*.go" -print0 | xargs -0 sed -i '' -e 's#"github.com/go-chi/chi"#"github.com/go-chi/chi/v5"#g'
echo generate typescript client
openapi-generator generate -i generated/catalyst.yml -o ui/src/client -g typescript-axios --artifact-version 1.0.0-SNAPSHOT
@@ -34,3 +35,6 @@ rm -rf ui/src/client/.openapi-generator ui/src/client/git_push.sh ui/src/client/
go mod tidy
gci write --Section Standard --Section Default --Section "Prefix(github.com/SecurityBrewery/catalyst)" .
cd internal/maut
gci write --Section Standard --Section Default --Section "Prefix(github.com/jonas-plum/maut)" .
cd ../..

View File

@@ -7,7 +7,6 @@ import (
"fmt"
"net/http"
"strconv"
"strings"
"github.com/go-chi/chi/v5"
"github.com/xeipuuv/gojsonschema"
@@ -59,12 +58,30 @@ func parseQueryBool(r *http.Request, s string) (bool, error) {
}
func parseQueryStringArray(r *http.Request, key string) ([]string, error) {
return parseQueryArray(r, key), nil
stringArray, ok := r.URL.Query()[key]
if !ok {
return nil, nil
}
return removeEmpty(stringArray), nil
}
func removeEmpty(l []string) []string {
var stringArray []string
for _, s := range l {
if s == "" {
continue
}
stringArray = append(stringArray, s)
}
return stringArray
}
func parseQueryBoolArray(r *http.Request, key string) ([]bool, error) {
stringArray := parseQueryArray(r, key)
stringArray, ok := r.URL.Query()[key]
if !ok {
return nil, nil
}
var boolArray []bool
for _, s := range stringArray {
if s == "" {
@@ -80,33 +97,6 @@ func parseQueryBoolArray(r *http.Request, key string) ([]bool, error) {
return boolArray, nil
}
func parseQueryArray(r *http.Request, key string) []string {
stringArray, ok := r.URL.Query()[key]
if !ok {
return nil
}
if len(stringArray) == 0 {
return nil
}
stringArray = strings.Split(stringArray[0], ",")
return removeEmpty(stringArray)
}
func removeEmpty(l []string) []string {
var stringArray []string
for _, s := range l {
if s == "" {
continue
}
stringArray = append(stringArray, s)
}
return stringArray
}
func parseQueryOptionalInt(r *http.Request, key string) (*int, error) {
s := r.URL.Query().Get(key)
if s == "" {

View File

@@ -1,86 +0,0 @@
package api
import (
"net/http"
"net/http/httptest"
"reflect"
"testing"
)
func Test_parseQueryOptionalBoolArray(t *testing.T) {
type args struct {
r *http.Request
key string
}
tests := []struct {
name string
args args
want []bool
wantErr bool
}{
{
name: "bool array",
args: args{
r: httptest.NewRequest(
http.MethodGet,
"https://try.catalyst-soar.com/api/tickets?type=alert&offset=0&count=10&sort=status%2Cowner%2Ccreated&desc=true%2Cfalse%2Cfalse&query=status+%3D%3D+%27open%27+AND+%28owner+%3D%3D+%27eve%27+OR+%21owner%29",
nil,
),
key: "desc",
},
want: []bool{true, false, false},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := parseQueryOptionalBoolArray(tt.args.r, tt.args.key)
if (err != nil) != tt.wantErr {
t.Errorf("parseQueryOptionalBoolArray() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("parseQueryOptionalBoolArray() got = %v, want %v", got, tt.want)
}
})
}
}
func Test_parseQueryOptionalStringArray(t *testing.T) {
type args struct {
r *http.Request
key string
}
tests := []struct {
name string
args args
want []string
wantErr bool
}{
{
name: "string array",
args: args{
r: httptest.NewRequest(
http.MethodGet,
"https://try.catalyst-soar.com/api/tickets?type=alert&offset=0&count=10&sort=status%2Cowner%2Ccreated&desc=true%2Cfalse%2Cfalse&query=status+%3D%3D+%27open%27+AND+%28owner+%3D%3D+%27eve%27+OR+%21owner%29",
nil,
),
key: "sort",
},
want: []string{"status", "owner", "created"},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := parseQueryOptionalStringArray(tt.args.r, tt.args.key)
if (err != nil) != tt.wantErr {
t.Errorf("parseQueryOptionalStringArray() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("parseQueryOptionalStringArray() got = %v, want %v", got, tt.want)
}
})
}
}

View File

@@ -68,7 +68,7 @@ var Tests = []struct {
Args: Args{Method: "Get", URL: "/currentuser"},
Want: Want{
Status: 200,
Body: map[string]interface{}{"apikey": false, "blocked": false, "id": "bob", "roles": []interface{}{"admin:backup:read", "admin:backup:restore", "admin:dashboard:write", "admin:group:write", "admin:job:read", "admin:job:write", "admin:log:read", "admin:settings:write", "admin:ticket:delete", "admin:user:write", "admin:userdata:read", "admin:userdata:write", "analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:dashboard:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read", "engineer:automation:write", "engineer:playbook:write", "engineer:rule:write", "engineer:template:write", "engineer:tickettype:write"}},
Body: map[string]interface{}{"apikey": false, "blocked": false, "id": "bob", "roles": []interface{}{"admin"}},
},
},
@@ -239,7 +239,7 @@ var Tests = []struct {
Args: Args{Method: "Get", URL: "/settings"},
Want: Want{
Status: 200,
Body: map[string]interface{}{"artifactKinds": []interface{}{map[string]interface{}{"icon": "mdi-server", "id": "asset", "name": "Asset"}, map[string]interface{}{"icon": "mdi-bullseye", "id": "ioc", "name": "IOC"}}, "artifactStates": []interface{}{map[string]interface{}{"color": "info", "icon": "mdi-help-circle-outline", "id": "unknown", "name": "Unknown"}, map[string]interface{}{"color": "error", "icon": "mdi-skull", "id": "malicious", "name": "Malicious"}, map[string]interface{}{"color": "success", "icon": "mdi-check", "id": "clean", "name": "Clean"}}, "roles": []interface{}{"admin:backup:read", "admin:backup:restore", "admin:dashboard:write", "admin:group:write", "admin:job:read", "admin:job:write", "admin:log:read", "admin:settings:write", "admin:ticket:delete", "admin:user:write", "admin:userdata:read", "admin:userdata:write", "analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:dashboard:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read", "engineer:automation:write", "engineer:playbook:write", "engineer:rule:write", "engineer:template:write", "engineer:tickettype:write"}, "ticketTypes": []interface{}{map[string]interface{}{"default_playbooks": []interface{}{}, "default_template": "default", "icon": "mdi-alert", "id": "alert", "name": "Alerts"}, map[string]interface{}{"default_playbooks": []interface{}{}, "default_template": "default", "icon": "mdi-radioactive", "id": "incident", "name": "Incidents"}, map[string]interface{}{"default_playbooks": []interface{}{}, "default_template": "default", "icon": "mdi-fingerprint", "id": "investigation", "name": "Forensic Investigations"}, map[string]interface{}{"default_playbooks": []interface{}{}, "default_template": "default", "icon": "mdi-target", "id": "hunt", "name": "Threat Hunting"}}, "tier": "community", "timeformat": "yyyy-MM-dd hh:mm:ss", "version": "0.0.0-test"},
Body: map[string]interface{}{"artifactKinds": []interface{}{map[string]interface{}{"icon": "mdi-server", "id": "asset", "name": "Asset"}, map[string]interface{}{"icon": "mdi-bullseye", "id": "ioc", "name": "IOC"}}, "artifactStates": []interface{}{map[string]interface{}{"color": "info", "icon": "mdi-help-circle-outline", "id": "unknown", "name": "Unknown"}, map[string]interface{}{"color": "error", "icon": "mdi-skull", "id": "malicious", "name": "Malicious"}, map[string]interface{}{"color": "success", "icon": "mdi-check", "id": "clean", "name": "Clean"}}, "ticketTypes": []interface{}{map[string]interface{}{"default_playbooks": []interface{}{}, "default_template": "default", "icon": "mdi-alert", "id": "alert", "name": "Alerts"}, map[string]interface{}{"default_playbooks": []interface{}{}, "default_template": "default", "icon": "mdi-radioactive", "id": "incident", "name": "Incidents"}, map[string]interface{}{"default_playbooks": []interface{}{}, "default_template": "default", "icon": "mdi-fingerprint", "id": "investigation", "name": "Forensic Investigations"}, map[string]interface{}{"default_playbooks": []interface{}{}, "default_template": "default", "icon": "mdi-target", "id": "hunt", "name": "Threat Hunting"}}, "tier": "community", "timeformat": "yyyy-MM-dd hh:mm:ss", "version": "0.0.0-test"},
},
},
@@ -248,7 +248,7 @@ var Tests = []struct {
Args: Args{Method: "Post", URL: "/settings", Data: map[string]interface{}{"artifactKinds": []interface{}{map[string]interface{}{"icon": "mdi-server", "id": "asset", "name": "Asset"}, map[string]interface{}{"icon": "mdi-bullseye", "id": "ioc", "name": "IOC"}}, "artifactStates": []interface{}{map[string]interface{}{"color": "info", "icon": "mdi-help-circle-outline", "id": "unknown", "name": "Unknown"}, map[string]interface{}{"color": "error", "icon": "mdi-skull", "id": "malicious", "name": "Malicious"}, map[string]interface{}{"color": "success", "icon": "mdi-check", "id": "clean", "name": "Clean"}}, "timeformat": "yyyy-MM-dd hh:mm:ss"}},
Want: Want{
Status: 200,
Body: map[string]interface{}{"artifactKinds": []interface{}{map[string]interface{}{"icon": "mdi-server", "id": "asset", "name": "Asset"}, map[string]interface{}{"icon": "mdi-bullseye", "id": "ioc", "name": "IOC"}}, "artifactStates": []interface{}{map[string]interface{}{"color": "info", "icon": "mdi-help-circle-outline", "id": "unknown", "name": "Unknown"}, map[string]interface{}{"color": "error", "icon": "mdi-skull", "id": "malicious", "name": "Malicious"}, map[string]interface{}{"color": "success", "icon": "mdi-check", "id": "clean", "name": "Clean"}}, "roles": []interface{}{"admin:backup:read", "admin:backup:restore", "admin:dashboard:write", "admin:group:write", "admin:job:read", "admin:job:write", "admin:log:read", "admin:settings:write", "admin:ticket:delete", "admin:user:write", "admin:userdata:read", "admin:userdata:write", "analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:dashboard:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read", "engineer:automation:write", "engineer:playbook:write", "engineer:rule:write", "engineer:template:write", "engineer:tickettype:write"}, "ticketTypes": []interface{}{map[string]interface{}{"default_playbooks": []interface{}{}, "default_template": "default", "icon": "mdi-alert", "id": "alert", "name": "Alerts"}, map[string]interface{}{"default_playbooks": []interface{}{}, "default_template": "default", "icon": "mdi-radioactive", "id": "incident", "name": "Incidents"}, map[string]interface{}{"default_playbooks": []interface{}{}, "default_template": "default", "icon": "mdi-fingerprint", "id": "investigation", "name": "Forensic Investigations"}, map[string]interface{}{"default_playbooks": []interface{}{}, "default_template": "default", "icon": "mdi-target", "id": "hunt", "name": "Threat Hunting"}}, "tier": "community", "timeformat": "yyyy-MM-dd hh:mm:ss", "version": "0.0.0-test"},
Body: map[string]interface{}{"artifactKinds": []interface{}{map[string]interface{}{"icon": "mdi-server", "id": "asset", "name": "Asset"}, map[string]interface{}{"icon": "mdi-bullseye", "id": "ioc", "name": "IOC"}}, "artifactStates": []interface{}{map[string]interface{}{"color": "info", "icon": "mdi-help-circle-outline", "id": "unknown", "name": "Unknown"}, map[string]interface{}{"color": "error", "icon": "mdi-skull", "id": "malicious", "name": "Malicious"}, map[string]interface{}{"color": "success", "icon": "mdi-check", "id": "clean", "name": "Clean"}}, "ticketTypes": []interface{}{map[string]interface{}{"default_playbooks": []interface{}{}, "default_template": "default", "icon": "mdi-alert", "id": "alert", "name": "Alerts"}, map[string]interface{}{"default_playbooks": []interface{}{}, "default_template": "default", "icon": "mdi-radioactive", "id": "incident", "name": "Incidents"}, map[string]interface{}{"default_playbooks": []interface{}{}, "default_template": "default", "icon": "mdi-fingerprint", "id": "investigation", "name": "Forensic Investigations"}, map[string]interface{}{"default_playbooks": []interface{}{}, "default_template": "default", "icon": "mdi-target", "id": "hunt", "name": "Threat Hunting"}}, "tier": "community", "timeformat": "yyyy-MM-dd hh:mm:ss", "version": "0.0.0-test"},
},
},
@@ -608,7 +608,7 @@ var Tests = []struct {
Args: Args{Method: "Get", URL: "/users"},
Want: Want{
Status: 200,
Body: []interface{}{map[string]interface{}{"apikey": false, "blocked": false, "id": "bob", "roles": []interface{}{"admin:backup:read", "admin:backup:restore", "admin:dashboard:write", "admin:group:write", "admin:job:read", "admin:job:write", "admin:log:read", "admin:settings:write", "admin:ticket:delete", "admin:user:write", "admin:userdata:read", "admin:userdata:write", "analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:dashboard:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read", "engineer:automation:write", "engineer:playbook:write", "engineer:rule:write", "engineer:template:write", "engineer:tickettype:write"}}, map[string]interface{}{"apikey": true, "blocked": false, "id": "script", "roles": []interface{}{"analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:dashboard:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read", "engineer:automation:write", "engineer:playbook:write", "engineer:rule:write", "engineer:template:write", "engineer:tickettype:write"}}},
Body: []interface{}{map[string]interface{}{"apikey": false, "blocked": false, "id": "bob", "roles": []interface{}{"admin"}}, map[string]interface{}{"apikey": true, "blocked": false, "id": "script", "roles": []interface{}{"engineer"}}},
},
},
@@ -617,7 +617,7 @@ var Tests = []struct {
Args: Args{Method: "Post", URL: "/users", Data: map[string]interface{}{"apikey": true, "blocked": false, "id": "syncscript", "roles": []interface{}{"analyst"}}},
Want: Want{
Status: 200,
Body: map[string]interface{}{"blocked": false, "id": "syncscript", "roles": []interface{}{"analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:dashboard:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read"}, "secret": "v39bOuobnlEljfWzjAgoKzhmnh1xSMxH"},
Body: map[string]interface{}{"blocked": false, "id": "syncscript", "roles": []interface{}{"analyst"}, "secret": "v39bOuobnlEljfWzjAgoKzhmnh1xSMxH"},
},
},
@@ -626,7 +626,7 @@ var Tests = []struct {
Args: Args{Method: "Get", URL: "/users/script"},
Want: Want{
Status: 200,
Body: map[string]interface{}{"apikey": true, "blocked": false, "id": "script", "roles": []interface{}{"analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:dashboard:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read", "engineer:automation:write", "engineer:playbook:write", "engineer:rule:write", "engineer:template:write", "engineer:tickettype:write"}},
Body: map[string]interface{}{"apikey": true, "blocked": false, "id": "script", "roles": []interface{}{"engineer"}},
},
},
@@ -635,7 +635,7 @@ var Tests = []struct {
Args: Args{Method: "Put", URL: "/users/bob", Data: map[string]interface{}{"apikey": false, "blocked": false, "id": "syncscript", "roles": []interface{}{"analyst", "admin"}}},
Want: Want{
Status: 200,
Body: map[string]interface{}{"apikey": false, "blocked": false, "id": "bob", "roles": []interface{}{"admin:backup:read", "admin:backup:restore", "admin:dashboard:write", "admin:group:write", "admin:job:read", "admin:job:write", "admin:log:read", "admin:settings:write", "admin:ticket:delete", "admin:user:write", "admin:userdata:read", "admin:userdata:write", "analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:dashboard:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read", "engineer:automation:write", "engineer:playbook:write", "engineer:rule:write", "engineer:template:write", "engineer:tickettype:write"}},
Body: map[string]interface{}{"apikey": false, "blocked": false, "id": "bob", "roles": []interface{}{"analyst", "admin"}},
},
},

View File

@@ -225,7 +225,7 @@
"apikey" : false,
"blocked" : false,
"id" : "bob",
"roles" : [ "admin:backup:read", "admin:backup:restore", "admin:dashboard:write", "admin:group:write", "admin:job:read", "admin:job:write", "admin:log:read", "admin:settings:write", "admin:ticket:delete", "admin:user:write", "admin:userdata:read", "admin:userdata:write", "analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:dashboard:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read", "engineer:automation:write", "engineer:playbook:write", "engineer:rule:write", "engineer:template:write", "engineer:tickettype:write" ]
"roles" : [ "admin" ]
}
}
},
@@ -1424,7 +1424,6 @@
"id" : "clean",
"name" : "Clean"
} ],
"roles" : [ "admin:backup:read", "admin:backup:restore", "admin:dashboard:write", "admin:group:write", "admin:job:read", "admin:job:write", "admin:log:read", "admin:settings:write", "admin:ticket:delete", "admin:user:write", "admin:userdata:read", "admin:userdata:write", "analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:dashboard:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read", "engineer:automation:write", "engineer:playbook:write", "engineer:rule:write", "engineer:template:write", "engineer:tickettype:write" ],
"ticketTypes" : [ {
"default_playbooks" : [ ],
"default_template" : "default",
@@ -1513,7 +1512,6 @@
"id" : "clean",
"name" : "Clean"
} ],
"roles" : [ "admin:backup:read", "admin:backup:restore", "admin:dashboard:write", "admin:group:write", "admin:job:read", "admin:job:write", "admin:log:read", "admin:settings:write", "admin:ticket:delete", "admin:user:write", "admin:userdata:read", "admin:userdata:write", "analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:dashboard:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read", "engineer:automation:write", "engineer:playbook:write", "engineer:rule:write", "engineer:template:write", "engineer:tickettype:write" ],
"ticketTypes" : [ {
"default_playbooks" : [ ],
"default_template" : "default",
@@ -5343,12 +5341,12 @@
"apikey" : false,
"blocked" : false,
"id" : "bob",
"roles" : [ "admin:backup:read", "admin:backup:restore", "admin:dashboard:write", "admin:group:write", "admin:job:read", "admin:job:write", "admin:log:read", "admin:settings:write", "admin:ticket:delete", "admin:user:write", "admin:userdata:read", "admin:userdata:write", "analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:dashboard:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read", "engineer:automation:write", "engineer:playbook:write", "engineer:rule:write", "engineer:template:write", "engineer:tickettype:write" ]
"roles" : [ "admin" ]
}, {
"apikey" : true,
"blocked" : false,
"id" : "script",
"roles" : [ "analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:dashboard:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read", "engineer:automation:write", "engineer:playbook:write", "engineer:rule:write", "engineer:template:write", "engineer:tickettype:write" ]
"roles" : [ "engineer" ]
} ]
}
},
@@ -5386,7 +5384,7 @@
"example" : {
"blocked" : false,
"id" : "syncscript",
"roles" : [ "analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:dashboard:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read" ],
"roles" : [ "analyst" ],
"secret" : "v39bOuobnlEljfWzjAgoKzhmnh1xSMxH"
}
}
@@ -5452,7 +5450,7 @@
"apikey" : true,
"blocked" : false,
"id" : "script",
"roles" : [ "analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:dashboard:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read", "engineer:automation:write", "engineer:playbook:write", "engineer:rule:write", "engineer:template:write", "engineer:tickettype:write" ]
"roles" : [ "engineer" ]
}
}
},
@@ -5501,7 +5499,7 @@
"apikey" : false,
"blocked" : false,
"id" : "bob",
"roles" : [ "admin:backup:read", "admin:backup:restore", "admin:dashboard:write", "admin:group:write", "admin:job:read", "admin:job:write", "admin:log:read", "admin:settings:write", "admin:ticket:delete", "admin:user:write", "admin:userdata:read", "admin:userdata:write", "analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:dashboard:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read", "engineer:automation:write", "engineer:playbook:write", "engineer:rule:write", "engineer:template:write", "engineer:tickettype:write" ]
"roles" : [ "analyst", "admin" ]
}
}
},

View File

@@ -1631,38 +1631,7 @@ paths:
blocked: false
id: bob
roles:
- admin:backup:read
- admin:backup:restore
- admin:dashboard:write
- admin:group:write
- admin:job:read
- admin:job:write
- admin:log:read
- admin:settings:write
- admin:ticket:delete
- admin:user:write
- admin:userdata:read
- admin:userdata:write
- analyst:automation:read
- analyst:currentsettings:write
- analyst:currentuser:read
- analyst:currentuserdata:read
- analyst:dashboard:read
- analyst:file
- analyst:group:read
- analyst:playbook:read
- analyst:rule:read
- analyst:settings:read
- analyst:template:read
- analyst:ticket:read
- analyst:ticket:write
- analyst:tickettype:read
- analyst:user:read
- engineer:automation:write
- engineer:playbook:write
- engineer:rule:write
- engineer:template:write
- engineer:tickettype:write
- admin
schema:
$ref: '#/definitions/UserResponse'
security:
@@ -2834,39 +2803,6 @@ paths:
icon: mdi-check
id: clean
name: Clean
roles:
- admin:backup:read
- admin:backup:restore
- admin:dashboard:write
- admin:group:write
- admin:job:read
- admin:job:write
- admin:log:read
- admin:settings:write
- admin:ticket:delete
- admin:user:write
- admin:userdata:read
- admin:userdata:write
- analyst:automation:read
- analyst:currentsettings:write
- analyst:currentuser:read
- analyst:currentuserdata:read
- analyst:dashboard:read
- analyst:file
- analyst:group:read
- analyst:playbook:read
- analyst:rule:read
- analyst:settings:read
- analyst:template:read
- analyst:ticket:read
- analyst:ticket:write
- analyst:tickettype:read
- analyst:user:read
- engineer:automation:write
- engineer:playbook:write
- engineer:rule:write
- engineer:template:write
- engineer:tickettype:write
ticketTypes:
- default_playbooks: []
default_template: default
@@ -2955,39 +2891,6 @@ paths:
icon: mdi-check
id: clean
name: Clean
roles:
- admin:backup:read
- admin:backup:restore
- admin:dashboard:write
- admin:group:write
- admin:job:read
- admin:job:write
- admin:log:read
- admin:settings:write
- admin:ticket:delete
- admin:user:write
- admin:userdata:read
- admin:userdata:write
- analyst:automation:read
- analyst:currentsettings:write
- analyst:currentuser:read
- analyst:currentuserdata:read
- analyst:dashboard:read
- analyst:file
- analyst:group:read
- analyst:playbook:read
- analyst:rule:read
- analyst:settings:read
- analyst:template:read
- analyst:ticket:read
- analyst:ticket:write
- analyst:tickettype:read
- analyst:user:read
- engineer:automation:write
- engineer:playbook:write
- engineer:rule:write
- engineer:template:write
- engineer:tickettype:write
ticketTypes:
- default_playbooks: []
default_template: default
@@ -7360,62 +7263,12 @@ paths:
blocked: false
id: bob
roles:
- admin:backup:read
- admin:backup:restore
- admin:dashboard:write
- admin:group:write
- admin:job:read
- admin:job:write
- admin:log:read
- admin:settings:write
- admin:ticket:delete
- admin:user:write
- admin:userdata:read
- admin:userdata:write
- analyst:automation:read
- analyst:currentsettings:write
- analyst:currentuser:read
- analyst:currentuserdata:read
- analyst:dashboard:read
- analyst:file
- analyst:group:read
- analyst:playbook:read
- analyst:rule:read
- analyst:settings:read
- analyst:template:read
- analyst:ticket:read
- analyst:ticket:write
- analyst:tickettype:read
- analyst:user:read
- engineer:automation:write
- engineer:playbook:write
- engineer:rule:write
- engineer:template:write
- engineer:tickettype:write
- admin
- apikey: true
blocked: false
id: script
roles:
- analyst:automation:read
- analyst:currentsettings:write
- analyst:currentuser:read
- analyst:currentuserdata:read
- analyst:dashboard:read
- analyst:file
- analyst:group:read
- analyst:playbook:read
- analyst:rule:read
- analyst:settings:read
- analyst:template:read
- analyst:ticket:read
- analyst:ticket:write
- analyst:tickettype:read
- analyst:user:read
- engineer:automation:write
- engineer:playbook:write
- engineer:rule:write
- engineer:template:write
- engineer:tickettype:write
- engineer
schema:
items:
$ref: '#/definitions/UserResponse'
@@ -7449,21 +7302,7 @@ paths:
blocked: false
id: syncscript
roles:
- analyst:automation:read
- analyst:currentsettings:write
- analyst:currentuser:read
- analyst:currentuserdata:read
- analyst:dashboard:read
- analyst:file
- analyst:group:read
- analyst:playbook:read
- analyst:rule:read
- analyst:settings:read
- analyst:template:read
- analyst:ticket:read
- analyst:ticket:write
- analyst:tickettype:read
- analyst:user:read
- analyst
secret: v39bOuobnlEljfWzjAgoKzhmnh1xSMxH
schema:
$ref: '#/definitions/NewUserResponse'
@@ -7510,26 +7349,7 @@ paths:
blocked: false
id: script
roles:
- analyst:automation:read
- analyst:currentsettings:write
- analyst:currentuser:read
- analyst:currentuserdata:read
- analyst:dashboard:read
- analyst:file
- analyst:group:read
- analyst:playbook:read
- analyst:rule:read
- analyst:settings:read
- analyst:template:read
- analyst:ticket:read
- analyst:ticket:write
- analyst:tickettype:read
- analyst:user:read
- engineer:automation:write
- engineer:playbook:write
- engineer:rule:write
- engineer:template:write
- engineer:tickettype:write
- engineer
schema:
$ref: '#/definitions/UserResponse'
security:
@@ -7569,38 +7389,8 @@ paths:
blocked: false
id: bob
roles:
- admin:backup:read
- admin:backup:restore
- admin:dashboard:write
- admin:group:write
- admin:job:read
- admin:job:write
- admin:log:read
- admin:settings:write
- admin:ticket:delete
- admin:user:write
- admin:userdata:read
- admin:userdata:write
- analyst:automation:read
- analyst:currentsettings:write
- analyst:currentuser:read
- analyst:currentuserdata:read
- analyst:dashboard:read
- analyst:file
- analyst:group:read
- analyst:playbook:read
- analyst:rule:read
- analyst:settings:read
- analyst:template:read
- analyst:ticket:read
- analyst:ticket:write
- analyst:tickettype:read
- analyst:user:read
- engineer:automation:write
- engineer:playbook:write
- engineer:rule:write
- engineer:template:write
- engineer:tickettype:write
- analyst
- admin
schema:
$ref: '#/definitions/UserResponse'
security:

View File

@@ -225,7 +225,7 @@
"apikey" : false,
"blocked" : false,
"id" : "bob",
"roles" : [ "admin:backup:read", "admin:backup:restore", "admin:dashboard:write", "admin:group:write", "admin:job:read", "admin:job:write", "admin:log:read", "admin:settings:write", "admin:ticket:delete", "admin:user:write", "admin:userdata:read", "admin:userdata:write", "analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:dashboard:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read", "engineer:automation:write", "engineer:playbook:write", "engineer:rule:write", "engineer:template:write", "engineer:tickettype:write" ]
"roles" : [ "admin" ]
}
}
},
@@ -994,7 +994,6 @@
"id" : "clean",
"name" : "Clean"
} ],
"roles" : [ "admin:backup:read", "admin:backup:restore", "admin:dashboard:write", "admin:group:write", "admin:job:read", "admin:job:write", "admin:log:read", "admin:settings:write", "admin:ticket:delete", "admin:user:write", "admin:userdata:read", "admin:userdata:write", "analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:dashboard:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read", "engineer:automation:write", "engineer:playbook:write", "engineer:rule:write", "engineer:template:write", "engineer:tickettype:write" ],
"ticketTypes" : [ {
"default_playbooks" : [ ],
"default_template" : "default",
@@ -1083,7 +1082,6 @@
"id" : "clean",
"name" : "Clean"
} ],
"roles" : [ "admin:backup:read", "admin:backup:restore", "admin:dashboard:write", "admin:group:write", "admin:job:read", "admin:job:write", "admin:log:read", "admin:settings:write", "admin:ticket:delete", "admin:user:write", "admin:userdata:read", "admin:userdata:write", "analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:dashboard:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read", "engineer:automation:write", "engineer:playbook:write", "engineer:rule:write", "engineer:template:write", "engineer:tickettype:write" ],
"ticketTypes" : [ {
"default_playbooks" : [ ],
"default_template" : "default",
@@ -4913,12 +4911,12 @@
"apikey" : false,
"blocked" : false,
"id" : "bob",
"roles" : [ "admin:backup:read", "admin:backup:restore", "admin:dashboard:write", "admin:group:write", "admin:job:read", "admin:job:write", "admin:log:read", "admin:settings:write", "admin:ticket:delete", "admin:user:write", "admin:userdata:read", "admin:userdata:write", "analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:dashboard:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read", "engineer:automation:write", "engineer:playbook:write", "engineer:rule:write", "engineer:template:write", "engineer:tickettype:write" ]
"roles" : [ "admin" ]
}, {
"apikey" : true,
"blocked" : false,
"id" : "script",
"roles" : [ "analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:dashboard:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read", "engineer:automation:write", "engineer:playbook:write", "engineer:rule:write", "engineer:template:write", "engineer:tickettype:write" ]
"roles" : [ "engineer" ]
} ]
}
},
@@ -4956,7 +4954,7 @@
"example" : {
"blocked" : false,
"id" : "syncscript",
"roles" : [ "analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:dashboard:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read" ],
"roles" : [ "analyst" ],
"secret" : "v39bOuobnlEljfWzjAgoKzhmnh1xSMxH"
}
}
@@ -5022,7 +5020,7 @@
"apikey" : true,
"blocked" : false,
"id" : "script",
"roles" : [ "analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:dashboard:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read", "engineer:automation:write", "engineer:playbook:write", "engineer:rule:write", "engineer:template:write", "engineer:tickettype:write" ]
"roles" : [ "engineer" ]
}
}
},
@@ -5071,7 +5069,7 @@
"apikey" : false,
"blocked" : false,
"id" : "bob",
"roles" : [ "admin:backup:read", "admin:backup:restore", "admin:dashboard:write", "admin:group:write", "admin:job:read", "admin:job:write", "admin:log:read", "admin:settings:write", "admin:ticket:delete", "admin:user:write", "admin:userdata:read", "admin:userdata:write", "analyst:automation:read", "analyst:currentsettings:write", "analyst:currentuser:read", "analyst:currentuserdata:read", "analyst:dashboard:read", "analyst:file", "analyst:group:read", "analyst:playbook:read", "analyst:rule:read", "analyst:settings:read", "analyst:template:read", "analyst:ticket:read", "analyst:ticket:write", "analyst:tickettype:read", "analyst:user:read", "engineer:automation:write", "engineer:playbook:write", "engineer:rule:write", "engineer:template:write", "engineer:tickettype:write" ]
"roles" : [ "analyst", "admin" ]
}
}
},

View File

@@ -1512,38 +1512,7 @@ paths:
blocked: false
id: bob
roles:
- admin:backup:read
- admin:backup:restore
- admin:dashboard:write
- admin:group:write
- admin:job:read
- admin:job:write
- admin:log:read
- admin:settings:write
- admin:ticket:delete
- admin:user:write
- admin:userdata:read
- admin:userdata:write
- analyst:automation:read
- analyst:currentsettings:write
- analyst:currentuser:read
- analyst:currentuserdata:read
- analyst:dashboard:read
- analyst:file
- analyst:group:read
- analyst:playbook:read
- analyst:rule:read
- analyst:settings:read
- analyst:template:read
- analyst:ticket:read
- analyst:ticket:write
- analyst:tickettype:read
- analyst:user:read
- engineer:automation:write
- engineer:playbook:write
- engineer:rule:write
- engineer:template:write
- engineer:tickettype:write
- admin
schema:
$ref: '#/definitions/UserResponse'
security:
@@ -2422,39 +2391,6 @@ paths:
icon: mdi-check
id: clean
name: Clean
roles:
- admin:backup:read
- admin:backup:restore
- admin:dashboard:write
- admin:group:write
- admin:job:read
- admin:job:write
- admin:log:read
- admin:settings:write
- admin:ticket:delete
- admin:user:write
- admin:userdata:read
- admin:userdata:write
- analyst:automation:read
- analyst:currentsettings:write
- analyst:currentuser:read
- analyst:currentuserdata:read
- analyst:dashboard:read
- analyst:file
- analyst:group:read
- analyst:playbook:read
- analyst:rule:read
- analyst:settings:read
- analyst:template:read
- analyst:ticket:read
- analyst:ticket:write
- analyst:tickettype:read
- analyst:user:read
- engineer:automation:write
- engineer:playbook:write
- engineer:rule:write
- engineer:template:write
- engineer:tickettype:write
ticketTypes:
- default_playbooks: []
default_template: default
@@ -2543,39 +2479,6 @@ paths:
icon: mdi-check
id: clean
name: Clean
roles:
- admin:backup:read
- admin:backup:restore
- admin:dashboard:write
- admin:group:write
- admin:job:read
- admin:job:write
- admin:log:read
- admin:settings:write
- admin:ticket:delete
- admin:user:write
- admin:userdata:read
- admin:userdata:write
- analyst:automation:read
- analyst:currentsettings:write
- analyst:currentuser:read
- analyst:currentuserdata:read
- analyst:dashboard:read
- analyst:file
- analyst:group:read
- analyst:playbook:read
- analyst:rule:read
- analyst:settings:read
- analyst:template:read
- analyst:ticket:read
- analyst:ticket:write
- analyst:tickettype:read
- analyst:user:read
- engineer:automation:write
- engineer:playbook:write
- engineer:rule:write
- engineer:template:write
- engineer:tickettype:write
ticketTypes:
- default_playbooks: []
default_template: default
@@ -6948,62 +6851,12 @@ paths:
blocked: false
id: bob
roles:
- admin:backup:read
- admin:backup:restore
- admin:dashboard:write
- admin:group:write
- admin:job:read
- admin:job:write
- admin:log:read
- admin:settings:write
- admin:ticket:delete
- admin:user:write
- admin:userdata:read
- admin:userdata:write
- analyst:automation:read
- analyst:currentsettings:write
- analyst:currentuser:read
- analyst:currentuserdata:read
- analyst:dashboard:read
- analyst:file
- analyst:group:read
- analyst:playbook:read
- analyst:rule:read
- analyst:settings:read
- analyst:template:read
- analyst:ticket:read
- analyst:ticket:write
- analyst:tickettype:read
- analyst:user:read
- engineer:automation:write
- engineer:playbook:write
- engineer:rule:write
- engineer:template:write
- engineer:tickettype:write
- admin
- apikey: true
blocked: false
id: script
roles:
- analyst:automation:read
- analyst:currentsettings:write
- analyst:currentuser:read
- analyst:currentuserdata:read
- analyst:dashboard:read
- analyst:file
- analyst:group:read
- analyst:playbook:read
- analyst:rule:read
- analyst:settings:read
- analyst:template:read
- analyst:ticket:read
- analyst:ticket:write
- analyst:tickettype:read
- analyst:user:read
- engineer:automation:write
- engineer:playbook:write
- engineer:rule:write
- engineer:template:write
- engineer:tickettype:write
- engineer
schema:
items:
$ref: '#/definitions/UserResponse'
@@ -7037,21 +6890,7 @@ paths:
blocked: false
id: syncscript
roles:
- analyst:automation:read
- analyst:currentsettings:write
- analyst:currentuser:read
- analyst:currentuserdata:read
- analyst:dashboard:read
- analyst:file
- analyst:group:read
- analyst:playbook:read
- analyst:rule:read
- analyst:settings:read
- analyst:template:read
- analyst:ticket:read
- analyst:ticket:write
- analyst:tickettype:read
- analyst:user:read
- analyst
secret: v39bOuobnlEljfWzjAgoKzhmnh1xSMxH
schema:
$ref: '#/definitions/NewUserResponse'
@@ -7098,26 +6937,7 @@ paths:
blocked: false
id: script
roles:
- analyst:automation:read
- analyst:currentsettings:write
- analyst:currentuser:read
- analyst:currentuserdata:read
- analyst:dashboard:read
- analyst:file
- analyst:group:read
- analyst:playbook:read
- analyst:rule:read
- analyst:settings:read
- analyst:template:read
- analyst:ticket:read
- analyst:ticket:write
- analyst:tickettype:read
- analyst:user:read
- engineer:automation:write
- engineer:playbook:write
- engineer:rule:write
- engineer:template:write
- engineer:tickettype:write
- engineer
schema:
$ref: '#/definitions/UserResponse'
security:
@@ -7157,38 +6977,8 @@ paths:
blocked: false
id: bob
roles:
- admin:backup:read
- admin:backup:restore
- admin:dashboard:write
- admin:group:write
- admin:job:read
- admin:job:write
- admin:log:read
- admin:settings:write
- admin:ticket:delete
- admin:user:write
- admin:userdata:read
- admin:userdata:write
- analyst:automation:read
- analyst:currentsettings:write
- analyst:currentuser:read
- analyst:currentuserdata:read
- analyst:dashboard:read
- analyst:file
- analyst:group:read
- analyst:playbook:read
- analyst:rule:read
- analyst:settings:read
- analyst:template:read
- analyst:ticket:read
- analyst:ticket:write
- analyst:tickettype:read
- analyst:user:read
- engineer:automation:write
- engineer:playbook:write
- engineer:rule:write
- engineer:template:write
- engineer:tickettype:write
- analyst
- admin
schema:
$ref: '#/definitions/UserResponse'
security:

122
go.cap
View File

@@ -1,122 +0,0 @@
github.com/SecurityBrewery/catalyst/cmd/catalyst (network)
github.com/RoaringBitmap/roaring (reflect, unsafe)
github.com/SecurityBrewery/catalyst (execute, file, network)
github.com/SecurityBrewery/catalyst/auth (network)
github.com/SecurityBrewery/catalyst/database/busdb (network)
github.com/SecurityBrewery/catalyst/generated/api (network)
github.com/SecurityBrewery/catalyst/index (file)
github.com/SecurityBrewery/catalyst/service (network)
github.com/alecthomas/kong (file, reflect, syscall, unsafe)
github.com/antlr/antlr4/runtime/Go/antlr (file, reflect)
github.com/arangodb/go-driver (file, network, reflect)
github.com/arangodb/go-driver/cluster (network)
github.com/arangodb/go-driver/http (file, network, reflect)
github.com/arangodb/go-velocypack (reflect)
github.com/aws/aws-sdk-go/aws (file, network)
github.com/aws/aws-sdk-go/aws/awsutil (reflect)
github.com/aws/aws-sdk-go/aws/client (file)
github.com/aws/aws-sdk-go/aws/corehandlers (file, network)
github.com/aws/aws-sdk-go/aws/credentials (file)
github.com/aws/aws-sdk-go/aws/credentials/processcreds (execute, file)
github.com/aws/aws-sdk-go/aws/credentials/ssocreds (file)
github.com/aws/aws-sdk-go/aws/credentials/stscreds (file)
github.com/aws/aws-sdk-go/aws/csm (network)
github.com/aws/aws-sdk-go/aws/defaults (file, network)
github.com/aws/aws-sdk-go/aws/ec2metadata (file, network)
github.com/aws/aws-sdk-go/aws/request (file, network, reflect)
github.com/aws/aws-sdk-go/aws/session (file, network)
github.com/aws/aws-sdk-go/aws/signer/v4 (file, network)
github.com/aws/aws-sdk-go/internal/ini (file)
github.com/aws/aws-sdk-go/internal/shareddefaults (file)
github.com/aws/aws-sdk-go/private/protocol (file, network, reflect)
github.com/aws/aws-sdk-go/private/protocol/json/jsonutil (reflect)
github.com/aws/aws-sdk-go/private/protocol/jsonrpc (file, network)
github.com/aws/aws-sdk-go/private/protocol/query/queryutil (reflect)
github.com/aws/aws-sdk-go/private/protocol/rest (file, network, reflect)
github.com/aws/aws-sdk-go/private/protocol/restjson (file, network)
github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil (reflect)
github.com/aws/aws-sdk-go/service/s3 (file, network)
github.com/aws/aws-sdk-go/service/s3/s3manager (network)
github.com/blevesearch/bleve/v2 (file, reflect)
github.com/blevesearch/bleve/v2/analysis (file)
github.com/blevesearch/bleve/v2/document (network, reflect)
github.com/blevesearch/bleve/v2/geo (reflect)
github.com/blevesearch/bleve/v2/index/scorch (file, reflect)
github.com/blevesearch/bleve/v2/index/upsidedown (reflect)
github.com/blevesearch/bleve/v2/index/upsidedown/store/boltdb (file)
github.com/blevesearch/bleve/v2/index/upsidedown/store/gtreap (file)
github.com/blevesearch/bleve/v2/mapping (file, network, reflect)
github.com/blevesearch/bleve/v2/search (reflect)
github.com/blevesearch/bleve/v2/search/collector (reflect)
github.com/blevesearch/bleve/v2/search/facet (reflect)
github.com/blevesearch/bleve/v2/search/highlight (reflect)
github.com/blevesearch/bleve/v2/search/query (file, network)
github.com/blevesearch/bleve/v2/search/scorer (reflect)
github.com/blevesearch/bleve/v2/search/searcher (network, reflect)
github.com/blevesearch/bleve/v2/size (reflect)
github.com/blevesearch/bleve_index_api (reflect)
github.com/blevesearch/mmap-go (file, reflect, unsafe)
github.com/blevesearch/vellum (file)
github.com/blevesearch/zapx/v11 (file, reflect, unsafe)
github.com/blevesearch/zapx/v12 (file, reflect, unsafe)
github.com/blevesearch/zapx/v13 (file, reflect, unsafe)
github.com/blevesearch/zapx/v14 (file, reflect, unsafe)
github.com/blevesearch/zapx/v15 (file, reflect, unsafe)
github.com/bmizerany/pat (network)
github.com/coreos/go-oidc/v3/oidc (file, network)
github.com/docker/distribution/registry/api/errcode (network)
github.com/docker/docker/api/types (file, network)
github.com/docker/docker/api/types/mount (file)
github.com/docker/docker/api/types/registry (network)
github.com/docker/docker/api/types/swarm (file)
github.com/docker/docker/client (file, network)
github.com/docker/docker/errdefs (network)
github.com/docker/go-connections/nat (network)
github.com/docker/go-connections/sockets (file, network, syscall)
github.com/docker/go-connections/tlsconfig (file)
github.com/go-chi/chi/v5 (network)
github.com/go-chi/chi/v5/middleware (file, network)
github.com/gobwas/ws (network, reflect, unsafe)
github.com/gobwas/ws/wsutil (file, network)
github.com/gogo/protobuf/proto (reflect, unsafe)
github.com/golang/protobuf/proto (file, reflect)
github.com/golang/protobuf/ptypes/any (reflect)
github.com/golang/protobuf/ptypes/duration (reflect)
github.com/golang/protobuf/ptypes/timestamp (reflect)
github.com/google/uuid (file, network)
github.com/imdario/mergo (reflect)
github.com/jmespath/go-jmespath (reflect)
github.com/sirupsen/logrus (file, reflect)
github.com/tus/tusd/pkg/handler (file, network)
github.com/tus/tusd/pkg/s3store (file, network)
github.com/xeipuuv/gojsonpointer (reflect)
github.com/xeipuuv/gojsonschema (file, network, reflect)
go.etcd.io/bbolt (file, reflect, syscall, unsafe)
golang.org/x/net/context/ctxhttp (network)
golang.org/x/net/internal/socks (network)
golang.org/x/net/proxy (file, network)
golang.org/x/oauth2 (network)
golang.org/x/oauth2/internal (file, network)
golang.org/x/sys/cpu (file)
golang.org/x/sys/internal/unsafeheader (unsafe)
golang.org/x/sys/unix (syscall, unsafe)
google.golang.org/genproto/googleapis/rpc/status (reflect)
google.golang.org/protobuf/internal/descfmt (reflect)
google.golang.org/protobuf/internal/detrand (file)
google.golang.org/protobuf/internal/encoding/tag (reflect)
google.golang.org/protobuf/internal/filedesc (reflect)
google.golang.org/protobuf/internal/filetype (reflect)
google.golang.org/protobuf/internal/impl (file, reflect, unsafe)
google.golang.org/protobuf/internal/strs (unsafe)
google.golang.org/protobuf/proto (reflect)
google.golang.org/protobuf/reflect/protoreflect (unsafe)
google.golang.org/protobuf/reflect/protoregistry (file)
google.golang.org/protobuf/types/descriptorpb (reflect)
google.golang.org/protobuf/types/known/anypb (reflect)
google.golang.org/protobuf/types/known/durationpb (reflect)
google.golang.org/protobuf/types/known/timestamppb (reflect)
gopkg.in/square/go-jose.v2 (reflect)
gopkg.in/square/go-jose.v2/json (reflect)
gopkg.in/yaml.v2 (reflect)
gopkg.in/yaml.v3 (reflect)

19
go.mod
View File

@@ -2,6 +2,8 @@ module github.com/SecurityBrewery/catalyst
go 1.19
replace github.com/xeipuuv/gojsonschema => github.com/warjiang/gojsonschema v1.2.1-0.20210329105853-aa9f9a8cfec7
require (
github.com/alecthomas/kong v0.6.1
github.com/alecthomas/kong-yaml v0.1.1
@@ -14,18 +16,17 @@ require (
github.com/go-chi/chi/v5 v5.0.7
github.com/gobwas/ws v1.1.0
github.com/google/uuid v1.3.0
github.com/gorilla/securecookie v1.1.1
github.com/iancoleman/strcase v0.2.0
github.com/icza/dyno v0.0.0-20220812133438-f0b6f8a18845
github.com/imdario/mergo v0.3.13
github.com/jonas-plum/maut v0.0.0-20221001191853-1856efe6da0b
github.com/mingrammer/commonregex v1.0.1
github.com/stretchr/testify v1.8.0
github.com/tidwall/gjson v1.14.3
github.com/tidwall/sjson v1.2.5
github.com/tus/tusd v1.9.2
github.com/xeipuuv/gojsonschema v1.2.0
golang.org/x/crypto v0.0.0-20220926161630-eccd6366d1be
golang.org/x/exp v0.0.0-20220930202632-ec3f01382ef9
golang.org/x/exp v0.0.0-20220929160808-de9c53c655b9
golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1
gopkg.in/yaml.v3 v3.0.1
)
@@ -61,24 +62,24 @@ require (
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/gorilla/mux v1.8.0 // indirect
github.com/gorilla/securecookie v1.1.1 // indirect
github.com/gorilla/sessions v1.2.1 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/kr/pretty v0.3.0 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/mschoch/smat v0.2.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rogpeppe/go-internal v1.8.0 // indirect
github.com/sirupsen/logrus v1.8.1 // indirect
github.com/sirupsen/logrus v1.9.0 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
go.etcd.io/bbolt v1.3.6 // indirect
golang.org/x/crypto v0.0.0-20220926161630-eccd6366d1be // indirect
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b // indirect
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 // indirect
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20220810155839-1856144b1d9c // indirect
google.golang.org/grpc v1.49.0 // indirect
@@ -87,5 +88,3 @@ require (
gopkg.in/yaml.v2 v2.4.0 // indirect
gotest.tools v2.2.0+incompatible // indirect
)
replace github.com/xeipuuv/gojsonschema => github.com/warjiang/gojsonschema v1.2.1-0.20210329105853-aa9f9a8cfec7

33
go.sum
View File

@@ -168,7 +168,6 @@ github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7
github.com/couchbase/ghistogram v0.1.0/go.mod h1:s1Jhy76zqfEecpNWJfWUiKZookAFaiGOEoyzgHt9i7k=
github.com/couchbase/moss v0.2.0/go.mod h1:9MaHIaRuy9pvLPUJxB8sh8OrLfyDczECVL37grCIubs=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -191,6 +190,7 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.m
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ=
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
@@ -305,10 +305,13 @@ github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/Oth
github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM=
github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c=
github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4=
github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/schema v1.2.0 h1:YufUaxZYCKGFuAq3c96BOhjgd5nmXiOY9NGzF247Tsc=
github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI=
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
@@ -329,6 +332,8 @@ github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9Y
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/jonas-plum/maut v0.0.0-20221001191853-1856efe6da0b h1:gJtcxg/ifOIf7eWXv0ETHYUCEYLxo29WK7RKF+vJ/a4=
github.com/jonas-plum/maut v0.0.0-20221001191853-1856efe6da0b/go.mod h1:GHi17CboIfEAzcLKyOforrRGpNsJkIahosnrlgfsOvM=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
@@ -344,13 +349,11 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mattn/go-ieproxy v0.0.1/go.mod h1:pYabZ6IHcRpFh7vIaLfK7rdcWgFEb3SFJ6/gNWuh88E=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
@@ -379,7 +382,6 @@ github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 h1:rc3
github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -406,9 +408,6 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
github.com/rs/zerolog v1.19.0/go.mod h1:IzD0RJ65iWH0w97OQQebJEvTZYvsCUm9WVLWBQrJRjo=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
@@ -417,8 +416,8 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
@@ -465,6 +464,8 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/zitadel/logging v0.3.4 h1:9hZsTjMMTE3X2LUi0xcF9Q9EdLo+FAezeu52ireBbHM=
github.com/zitadel/oidc v1.8.0 h1:FEUuAaZVgZv0dWGpCNcG1ov7COVDA5x2yzlYwqy8iTs=
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU=
go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
@@ -499,8 +500,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/exp v0.0.0-20220930202632-ec3f01382ef9 h1:RjggHMcaTVp0LOVZcW0bo8alwHrOaCrGUDgfWUHhnN4=
golang.org/x/exp v0.0.0-20220930202632-ec3f01382ef9/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
golang.org/x/exp v0.0.0-20220929160808-de9c53c655b9 h1:lNtcVz/3bOstm7Vebox+5m3nLh/BYWnhmc3AhXOW6oI=
golang.org/x/exp v0.0.0-20220929160808-de9c53c655b9/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -687,8 +688,10 @@ golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 h1:WIoqL4EROvwiPdUtaip4VcDdpZ4kha7wBWZrbVKCIZg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

View File

@@ -1,171 +0,0 @@
package role
import (
"errors"
"sort"
"strings"
"golang.org/x/exp/slices"
"github.com/SecurityBrewery/catalyst/generated/model"
)
type Role string
const (
Analyst string = "analyst"
Engineer string = "engineer"
Admin string = "admin"
AutomationRead Role = "analyst:automation:read"
CurrentuserRead Role = "analyst:currentuser:read"
CurrentuserdataRead Role = "analyst:currentuserdata:read"
CurrentuserdataWrite Role = "analyst:currentsettings:write"
DashboardRead Role = "analyst:dashboard:read"
FileReadWrite Role = "analyst:file"
GroupRead Role = "analyst:group:read"
PlaybookRead Role = "analyst:playbook:read"
RuleRead Role = "analyst:rule:read"
SettingsRead Role = "analyst:settings:read"
TemplateRead Role = "analyst:template:read"
TicketRead Role = "analyst:ticket:read"
TicketWrite Role = "analyst:ticket:write"
TickettypeRead Role = "analyst:tickettype:read"
UserRead Role = "analyst:user:read"
AutomationWrite Role = "engineer:automation:write"
PlaybookWrite Role = "engineer:playbook:write"
RuleWrite Role = "engineer:rule:write"
TemplateWrite Role = "engineer:template:write"
TickettypeWrite Role = "engineer:tickettype:write"
BackupRead Role = "admin:backup:read"
BackupRestore Role = "admin:backup:restore"
DashboardWrite Role = "admin:dashboard:write"
GroupWrite Role = "admin:group:write"
JobRead Role = "admin:job:read"
JobWrite Role = "admin:job:write"
LogRead Role = "admin:log:read"
SettingsWrite Role = "admin:settings:write"
TicketDelete Role = "admin:ticket:delete"
UserWrite Role = "admin:user:write"
UserdataRead Role = "admin:userdata:read"
UserdataWrite Role = "admin:userdata:write"
)
func (p Role) String() string {
return string(p)
}
func UserHasRoles(user *model.UserResponse, roles []Role) bool {
hasRoles := true
for _, role := range roles {
if !UserHasRole(user, role) {
hasRoles = false
break
}
}
return hasRoles
}
func UserHasRole(user *model.UserResponse, role Role) bool {
return slices.Contains(FromStrings(user.Roles), role)
}
func Explodes(s []string) []Role {
var roles []Role
for _, e := range s {
roles = append(roles, Explode(e)...)
}
sort.Slice(roles, func(i, j int) bool {
return roles[i].String() < roles[j].String()
})
roles = slices.Compact(roles)
return roles
}
func Explode(s string) []Role {
var roles []Role
switch s {
case Admin:
roles = append(roles, listPrefix(Admin)...)
fallthrough
case Engineer:
roles = append(roles, listPrefix(Engineer)...)
fallthrough
case Analyst:
roles = append(roles, listPrefix(Analyst)...)
return roles
}
for _, role := range List() {
if role.String() == s {
roles = append(roles, role)
}
}
return roles
}
func listPrefix(s string) []Role {
var roles []Role
for _, role := range List() {
if strings.HasPrefix(role.String(), s+":") {
roles = append(roles, role)
}
}
return roles
}
func List() []Role {
return []Role{
AutomationRead, CurrentuserdataRead, CurrentuserdataWrite,
CurrentuserRead, FileReadWrite, GroupRead, PlaybookRead, RuleRead,
UserdataRead, SettingsRead, TemplateRead, TicketRead, TickettypeRead,
TicketWrite, UserRead, AutomationWrite, PlaybookWrite, RuleWrite,
TemplateWrite, TickettypeWrite, BackupRead, BackupRestore, GroupWrite,
LogRead, UserdataWrite, TicketDelete, UserWrite, JobRead, JobWrite,
SettingsWrite, DashboardRead, DashboardWrite,
}
}
func fromString(s string) (Role, error) {
for _, role := range List() {
if role.String() == s {
return role, nil
}
}
return "", errors.New("unknown role")
}
func Strings(roles []Role) []string {
var s []string
for _, role := range roles {
s = append(s, role.String())
}
return s
}
func FromStrings(s []string) []Role {
var roles []Role
for _, e := range s {
role, err := fromString(e)
if err != nil {
continue
}
roles = append(roles, role)
}
return roles
}

50
roles.go Normal file
View File

@@ -0,0 +1,50 @@
package catalyst
import maut "github.com/jonas-plum/maut/auth"
var Admin = &maut.Role{
Name: "admin",
Permissions: append(engineer.Permissions,
"backup:create",
"backup:restore",
"dashboard:write",
"job:read",
"job:write",
"log:read",
"settings:write",
"ticket:delete",
"tickettype:read",
"user:write",
"userdata:read",
"userdata:write",
),
}
var engineer = &maut.Role{
Name: "engineer",
Permissions: append(analyst.Permissions,
"automation:write",
"playbook:write",
"template:write",
"tickettype:write",
),
}
var analyst = &maut.Role{
Name: "analyst",
Permissions: []string{
"automation:read",
"currentuser:read",
"currentuserdata:read",
"currentuserdata:write",
"dashboard:read",
"file:read",
"file:write",
"playbook:read",
"settings:read",
"template:read",
"ticket:read",
"ticket:write",
"user:read",
},
}

View File

@@ -7,17 +7,14 @@ import (
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
maut "github.com/jonas-plum/maut/auth"
"github.com/SecurityBrewery/catalyst/auth"
"github.com/SecurityBrewery/catalyst/bus"
"github.com/SecurityBrewery/catalyst/busservice"
"github.com/SecurityBrewery/catalyst/database"
"github.com/SecurityBrewery/catalyst/database/busdb"
"github.com/SecurityBrewery/catalyst/generated/api"
"github.com/SecurityBrewery/catalyst/generated/model"
"github.com/SecurityBrewery/catalyst/hooks"
"github.com/SecurityBrewery/catalyst/index"
"github.com/SecurityBrewery/catalyst/role"
"github.com/SecurityBrewery/catalyst/service"
"github.com/SecurityBrewery/catalyst/storage"
)
@@ -27,11 +24,9 @@ type Config struct {
DB *database.Config
Storage *storage.Config
Secret []byte
Auth *auth.Config
Auth *maut.Config
ExternalAddress string
InternalAddress string
InitialAPIKey string
Network string
Port int
}
@@ -49,12 +44,6 @@ func New(hooks *hooks.Hooks, config *Config) (*Server, error) {
ctx, cancel := context.WithTimeout(ctx, time.Minute*10)
defer cancel()
if config.Auth.OIDCAuthEnable {
if err := config.Auth.Load(ctx); err != nil {
return nil, err
}
}
catalystStorage, err := storage.New(config.Storage)
if err != nil {
return nil, err
@@ -72,29 +61,19 @@ func New(hooks *hooks.Hooks, config *Config) (*Server, error) {
return nil, err
}
busservice.New(config.InternalAddress+"/api", config.InitialAPIKey, config.Network, catalystBus, catalystDatabase)
busservice.New(config.InternalAddress+"/api", config.Auth.InitialAPIKey, config.Network, catalystBus, catalystDatabase)
catalystService, err := service.New(catalystBus, catalystDatabase, catalystStorage, GetVersion())
if err != nil {
return nil, err
}
if config.InitialAPIKey != "" {
_ = catalystDatabase.UserDelete(ctx, "setup")
ctx = busdb.UserContext(ctx, &model.UserResponse{
ID: "setup",
Roles: role.Strings(role.Explode(role.Admin)),
Apikey: false,
Blocked: false,
})
_, err = catalystDatabase.UserCreateSetupAPIKey(ctx, config.InitialAPIKey)
if err != nil {
return nil, err
}
authenticator, err := maut.NewAuthenticator(ctx, config.Auth, newCatalystResolver(catalystDatabase))
if err != nil {
return nil, err
}
apiServer, err := setupAPI(catalystService, catalystStorage, catalystDatabase, config.DB, catalystBus, config)
apiServer, err := setupAPI(authenticator, catalystService, catalystStorage, catalystDatabase, config.DB, catalystBus, config)
if err != nil {
return nil, err
}
@@ -108,32 +87,22 @@ func New(hooks *hooks.Hooks, config *Config) (*Server, error) {
}, nil
}
func setupAPI(catalystService *service.Service, catalystStorage *storage.Storage, catalystDatabase *database.Database, dbConfig *database.Config, bus *bus.Bus, config *Config) (chi.Router, error) {
secureJar := auth.NewJar(config.Secret)
func setupAPI(authenticator *maut.Authenticator, catalystService *service.Service, catalystStorage *storage.Storage, catalystDatabase *database.Database, dbConfig *database.Config, bus *bus.Bus, config *Config) (chi.Router, error) {
middlewares := []func(next http.Handler) http.Handler{
auth.Authenticate(catalystDatabase, config.Auth, secureJar),
auth.AuthorizeBlockedUser(),
authenticator.Authenticate(),
authenticator.AuthorizeBlockedUser(),
}
// create server
apiServer := api.NewServer(catalystService, auth.AuthorizeRole, middlewares...)
fileReadWrite := auth.AuthorizeRole([]string{role.FileReadWrite.String()})
tudHandler := tusdUpload(catalystDatabase, bus, catalystStorage.S3(), config.ExternalAddress)
apiServer.With(fileReadWrite).Head("/files/{ticketID}/tusd/{id}", tudHandler)
apiServer.With(fileReadWrite).Patch("/files/{ticketID}/tusd/{id}", tudHandler)
apiServer.With(fileReadWrite).Post("/files/{ticketID}/tusd", tudHandler)
apiServer.With(fileReadWrite).Post("/files/{ticketID}/upload", upload(catalystDatabase, catalystStorage.S3(), catalystStorage.Uploader()))
apiServer.With(fileReadWrite).Get("/files/{ticketID}/download/{key}", download(catalystStorage.Downloader()))
apiServer.With(auth.AuthorizeRole([]string{role.BackupRead.String()})).Get("/backup/create", backupHandler(catalystStorage, dbConfig))
apiServer.With(auth.AuthorizeRole([]string{role.BackupRestore.String()})).Post("/backup/restore", restoreHandler(catalystStorage, catalystDatabase, dbConfig))
apiServer := api.NewServer(catalystService, permissionAuth(authenticator), middlewares...)
apiServer.Mount("/files", fileServer(authenticator, catalystDatabase, bus, catalystStorage, config))
apiServer.Mount("/backup", backupServer(authenticator, catalystStorage, catalystDatabase, dbConfig))
server := chi.NewRouter()
server.Use(middleware.RequestID, middleware.RealIP, middleware.Logger, middleware.Recoverer)
server.Mount("/api", apiServer)
server.Mount("/auth", authenticator.Server())
server.With(middlewares...).Handle("/wss", handleWebSocket(bus))
server.Mount("/auth", auth.Server(config.Auth, catalystDatabase, secureJar))
server.Get("/", func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "/ui/", http.StatusFound)
@@ -141,3 +110,31 @@ func setupAPI(catalystService *service.Service, catalystStorage *storage.Storage
return server, nil
}
func permissionAuth(authenticator *maut.Authenticator) func([]string) func(http.Handler) http.Handler {
return func(strings []string) func(http.Handler) http.Handler {
return authenticator.AuthorizePermission(strings...)
}
}
func fileServer(authenticator *maut.Authenticator, catalystDatabase *database.Database, bus *bus.Bus, catalystStorage *storage.Storage, config *Config) *chi.Mux {
fileRW := authenticator.AuthorizePermission("file:read", "file:write") // TODO: add test
tudHandler := tusdUpload(catalystDatabase, bus, catalystStorage.S3(), config.ExternalAddress)
server := chi.NewRouter()
server.With(fileRW).Head("/{ticketID}/tusd/{id}", tudHandler)
server.With(fileRW).Patch("/{ticketID}/tusd/{id}", tudHandler)
server.With(fileRW).Post("/{ticketID}/tusd", tudHandler)
server.With(fileRW).Post("/{ticketID}/upload", upload(catalystDatabase, catalystStorage.S3(), catalystStorage.Uploader()))
server.With(fileRW).Get("/{ticketID}/download/{key}", download(catalystStorage.Downloader()))
return server
}
func backupServer(authenticator *maut.Authenticator, catalystStorage *storage.Storage, catalystDatabase *database.Database, dbConfig *database.Config) *chi.Mux {
server := chi.NewRouter()
// TODO: add test
server.With(authenticator.AuthorizePermission("backup:create")).Get("/create", backupHandler(catalystStorage, dbConfig))
server.With(authenticator.AuthorizePermission("backup:restore")).Post("/restore", restoreHandler(catalystStorage, catalystDatabase, dbConfig))
return server
}

View File

@@ -4,10 +4,10 @@ import (
"context"
"github.com/arangodb/go-driver"
maut "github.com/jonas-plum/maut/auth"
"github.com/SecurityBrewery/catalyst/bus"
"github.com/SecurityBrewery/catalyst/database"
"github.com/SecurityBrewery/catalyst/database/busdb"
"github.com/SecurityBrewery/catalyst/storage"
)
@@ -28,7 +28,7 @@ func (s *Service) publishRequest(ctx context.Context, err error, function string
}
if ids != nil {
userID := "unknown"
user, ok := busdb.UserFromContext(ctx)
user, _, ok := maut.UserFromContext(ctx)
if ok {
userID = user.ID
}

View File

@@ -3,11 +3,10 @@ package service
import (
"context"
"errors"
"sort"
"github.com/SecurityBrewery/catalyst/database/busdb"
maut "github.com/jonas-plum/maut/auth"
"github.com/SecurityBrewery/catalyst/generated/model"
"github.com/SecurityBrewery/catalyst/role"
)
func (s *Service) GetSettings(ctx context.Context) (*model.SettingsResponse, error) {
@@ -29,7 +28,7 @@ func (s *Service) SaveSettings(ctx context.Context, settings *model.Settings) (*
}
func (s *Service) settings(ctx context.Context, globalSettings *model.Settings) (*model.SettingsResponse, error) {
user, ok := busdb.UserFromContext(ctx)
user, permissions, ok := maut.UserFromContext(ctx)
if !ok {
return nil, errors.New("no user in context")
}
@@ -47,13 +46,11 @@ func (s *Service) settings(ctx context.Context, globalSettings *model.Settings)
if userData.Timeformat != nil {
globalSettings.Timeformat = *userData.Timeformat
}
roles := role.Strings(role.List())
sort.Strings(roles)
return &model.SettingsResponse{
Tier: model.SettingsResponseTierCommunity,
Version: s.version,
Roles: roles,
Roles: permissions,
TicketTypes: ticketTypeList,
ArtifactStates: globalSettings.ArtifactStates,
ArtifactKinds: globalSettings.ArtifactKinds,

View File

@@ -6,9 +6,9 @@ import (
"fmt"
"github.com/arangodb/go-driver"
maut "github.com/jonas-plum/maut/auth"
"github.com/SecurityBrewery/catalyst/database"
"github.com/SecurityBrewery/catalyst/database/busdb"
"github.com/SecurityBrewery/catalyst/generated/model"
)
@@ -59,11 +59,16 @@ func (s *Service) DeleteUser(ctx context.Context, s2 string) (err error) {
}
func (s *Service) CurrentUser(ctx context.Context) (*model.UserResponse, error) {
user, ok := busdb.UserFromContext(ctx)
user, _, ok := maut.UserFromContext(ctx)
if !ok {
return nil, errors.New("no user in context")
}
s.publishRequest(ctx, nil, "CurrentUser", userResponseID(user))
s.publishRequest(ctx, nil, "CurrentUser", userID(user.ID))
return user, nil
return &model.UserResponse{
ID: user.ID,
Apikey: user.APIKey,
Blocked: user.Blocked,
Roles: user.Roles,
}, nil
}

View File

@@ -6,9 +6,9 @@ import (
"fmt"
"github.com/arangodb/go-driver"
maut "github.com/jonas-plum/maut/auth"
"github.com/SecurityBrewery/catalyst/database"
"github.com/SecurityBrewery/catalyst/database/busdb"
"github.com/SecurityBrewery/catalyst/generated/model"
)
@@ -39,7 +39,7 @@ func (s *Service) UpdateUserData(ctx context.Context, id string, data *model.Use
}
func (s *Service) CurrentUserData(ctx context.Context) (doc *model.UserDataResponse, err error) {
user, ok := busdb.UserFromContext(ctx)
user, _, ok := maut.UserFromContext(ctx)
if !ok {
return nil, errors.New("no user in context")
}
@@ -48,7 +48,7 @@ func (s *Service) CurrentUserData(ctx context.Context) (doc *model.UserDataRespo
}
func (s *Service) UpdateCurrentUserData(ctx context.Context, data *model.UserData) (doc *model.UserDataResponse, err error) {
user, ok := busdb.UserFromContext(ctx)
user, _, ok := maut.UserFromContext(ctx)
if !ok {
return nil, errors.New("no user in context")
}

View File

@@ -4,6 +4,8 @@ import (
"context"
"time"
maut "github.com/jonas-plum/maut/auth"
"github.com/SecurityBrewery/catalyst/database"
"github.com/SecurityBrewery/catalyst/database/migrations"
"github.com/SecurityBrewery/catalyst/generated/model"
@@ -13,7 +15,7 @@ import (
var (
bobSetting = &model.UserData{Email: pointer.String("bob@example.org"), Name: pointer.String("Bob Bad")}
bobForm = &model.UserForm{ID: "bob", Blocked: false, Roles: []string{"admin"}}
Bob = &model.UserResponse{ID: "bob", Blocked: false, Roles: []string{"admin"}}
Bob = &maut.User{ID: "bob", Blocked: false, Roles: []string{"admin"}}
)
func SetupTestData(ctx context.Context, db *database.Database) error {

View File

@@ -12,13 +12,12 @@ import (
"github.com/arangodb/go-driver"
"github.com/coreos/go-oidc/v3/oidc"
"github.com/go-chi/chi/v5"
maut "github.com/jonas-plum/maut/auth"
"golang.org/x/oauth2"
"github.com/SecurityBrewery/catalyst"
"github.com/SecurityBrewery/catalyst/auth"
"github.com/SecurityBrewery/catalyst/bus"
"github.com/SecurityBrewery/catalyst/database"
"github.com/SecurityBrewery/catalyst/database/busdb"
"github.com/SecurityBrewery/catalyst/generated/api"
"github.com/SecurityBrewery/catalyst/generated/model"
"github.com/SecurityBrewery/catalyst/hooks"
@@ -28,14 +27,13 @@ import (
)
func Context() context.Context {
return busdb.UserContext(context.Background(), Bob)
return maut.UserContext(context.Background(), Bob, nil) // TODO add permissions ?
}
func Config(ctx context.Context) (*catalyst.Config, error) {
config := &catalyst.Config{
InitialAPIKey: "test",
IndexPath: "index.bleve",
Network: "catalyst",
IndexPath: "index.bleve",
Network: "catalyst",
DB: &database.Config{
Host: "http://localhost:8529",
User: "root",
@@ -46,8 +44,9 @@ func Config(ctx context.Context) (*catalyst.Config, error) {
User: "minio",
Password: "minio123",
},
Secret: []byte("4ef5b29539b70233dd40c02a1799d25079595565e05a193b09da2c3e60ada1cd"),
Auth: &auth.Config{
Auth: &maut.Config{
InitialAPIKey: "test",
CookieSecret: []byte("4ef5b29539b70233dd40c02a1799d25079595565e05a193b09da2c3e60ada1cd"),
SimpleAuthEnable: true,
APIKeyAuthEnable: true,
OIDCAuthEnable: true,
@@ -66,10 +65,6 @@ func Config(ctx context.Context) (*catalyst.Config, error) {
},
}
if err := config.Auth.Load(ctx); err != nil {
return nil, err
}
return config, nil
}
@@ -176,7 +171,7 @@ func Server(t *testing.T) (context.Context, *catalyst.Config, *bus.Bus, *index.I
catalystServer := api.NewServer(catalystService, func(s []string) func(http.Handler) http.Handler {
return func(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
handler.ServeHTTP(w, busdb.SetContext(r, Bob))
handler.ServeHTTP(w, r.WithContext(maut.UserContext(r.Context(), Bob, nil)))
})
}
})

View File

@@ -3,7 +3,7 @@ beforeEach(() => {
cy.login();
cy.getCookie('user').should('exist');
cy.getCookie('maut_user').should('exist');
cy.intercept('GET', '/api/userdata/demo', { fixture: 'userdata_demo.json' })
cy.intercept('GET', '/api/users/demo', { fixture: 'user_demo.json' })

View File

@@ -2,38 +2,5 @@
"apikey": false,
"blocked": false,
"id": "demo",
"roles": [
"admin:backup:read",
"admin:backup:restore",
"admin:dashboard:write",
"admin:group:write",
"admin:job:read",
"admin:job:write",
"admin:log:read",
"admin:settings:write",
"admin:ticket:delete",
"admin:user:write",
"admin:userdata:read",
"admin:userdata:write",
"analyst:automation:read",
"analyst:currentsettings:write",
"analyst:currentuser:read",
"analyst:currentuserdata:read",
"analyst:dashboard:read",
"analyst:file",
"analyst:group:read",
"analyst:playbook:read",
"analyst:rule:read",
"analyst:settings:read",
"analyst:template:read",
"analyst:ticket:read",
"analyst:ticket:write",
"analyst:tickettype:read",
"analyst:user:read",
"engineer:automation:write",
"engineer:playbook:write",
"engineer:rule:write",
"engineer:template:write",
"engineer:tickettype:write"
]
"roles": [ "admin" ]
}

View File

@@ -5,7 +5,7 @@
<v-form ref="form" v-model="valid" @submit.prevent="login">
<v-card class="pa-4">
<div class="d-flex justify-center">
<v-img src="/ui/flask.svg" height="100" width="100" class="flex-grow-0"></v-img>
<v-img src="/ui/static/flask.svg" height="100" width="100" class="flex-grow-0"></v-img>
</div>
<v-card-title class="text-center justify-center">
Catalyst Login
@@ -45,7 +45,7 @@
<v-list>
<v-list-item class="px-2" :to="{ name: 'Home' }">
<v-list-item-avatar rounded="0">
<v-img src="/ui/flask_white.svg" :width="40"></v-img>
<v-img src="/ui/static/flask_white.svg" :width="40"></v-img>
</v-list-item-avatar>
<v-list-item-content>
<v-list-item-title class="title">
@@ -208,16 +208,16 @@ export default Vue.extend({
valid: true,
authenticated: false,
settings: [
{ icon: "mdi-format-list-bulleted-type", name: "Ticket Types", to: "TicketTypeList", role: "engineer:tickettype:write" },
{ icon: "mdi-file-hidden", name: "Templates", to: "TemplateList", role: "analyst:template:read" },
{ icon: "mdi-file-cog-outline", name: "Playbooks", to: "PlaybookList", role: "analyst:playbook:read" },
{ icon: "mdi-flash", name: "Automations", to: "AutomationList", role: "analyst:automation:read" },
{ icon: "mdi-filter", name: "Ingestion Rules", to: "RuleList", role: "analyst:rule:read", tier: "enterprise" },
{ icon: "mdi-account", name: "Users & API Keys", to: "UserList", role: "admin:user:write" },
{ icon: "mdi-account-group", name: "Groups", to: "GroupList", role: "admin:group:write", tier: "enterprise" },
{ icon: "mdi-cogs", name: "User Data", to: "UserDataList", role: "admin:userdata:write" },
{ icon: "mdi-format-list-checks", name: "Jobs", to: "JobList", role: "admin:job:write" },
{ icon: "mdi-cog", name: "Settings", to: "Settings", role: "admin:settings:write" },
{ icon: "mdi-format-list-bulleted-type", name: "Ticket Types", to: "TicketTypeList", role: "tickettype:write" },
{ icon: "mdi-file-hidden", name: "Templates", to: "TemplateList", role: "template:read" },
{ icon: "mdi-file-cog-outline", name: "Playbooks", to: "PlaybookList", role: "playbook:read" },
{ icon: "mdi-flash", name: "Automations", to: "AutomationList", role: "automation:read" },
{ icon: "mdi-filter", name: "Ingestion Rules", to: "RuleList", role: "rule:read", tier: "enterprise" },
{ icon: "mdi-account", name: "Users & API Keys", to: "UserList", role: "user:write" },
{ icon: "mdi-account-group", name: "Groups", to: "GroupList", role: "group:write", tier: "enterprise" },
{ icon: "mdi-cogs", name: "User Data", to: "UserDataList", role: "userdata:write" },
{ icon: "mdi-format-list-checks", name: "Jobs", to: "JobList", role: "job:write" },
{ icon: "mdi-cog", name: "Settings", to: "Settings", role: "settings:write" },
],
mini: true,
goto: "",
@@ -235,7 +235,7 @@ export default Vue.extend({
},
internal: function (): Array<any> {
return [
{ icon: "mdi-view-dashboard", name: "Dashboards", to: "DashboardList", role: "analyst:dashboard:read" },
{ icon: "mdi-view-dashboard", name: "Dashboards", to: "DashboardList", role: "dashboard:read" },
{ icon: "mdi-check-bold", name: "Open Tasks", to: "TaskList", count: this.$store.state.task_count },
]
},
@@ -280,8 +280,8 @@ export default Vue.extend({
this.$router.push({ name: "TicketList", params: { type: type } });
},
hasRole: function (s: string) {
if (this.$store.state.user.roles) {
return this.lodash.includes(this.$store.state.user.roles, s);
if (this.$store.state.settings.roles) {
return this.lodash.includes(this.$store.state.settings.roles, s);
}
return false;
},

View File

@@ -151,8 +151,8 @@ export default Vue.extend({
return DateTime.fromISO(s).toFormat(format);
},
hasRole: function (s: string): boolean {
if (this.$store.state.user.roles) {
return this.lodash.includes(this.$store.state.user.roles, s);
if (this.$store.state.settings.roles) {
return this.lodash.includes(this.$store.state.settings.roles, s);
}
return false;
}

View File

@@ -41,8 +41,8 @@ export default Vue.extend({
return true;
}
let has = false;
if (this.$store.state.user.roles) {
this.lodash.forEach(this.$store.state.user.roles, (userRole) => {
if (this.$store.state.settings.roles) {
this.lodash.forEach(this.$store.state.settings.roles, (userRole) => {
if (link.role === userRole || this.lodash.startsWith(link.role, userRole + ":")) {
has = true;
}

View File

@@ -119,8 +119,8 @@ export default Vue.extend({
this.dialog = false;
},
hasRole: function (s: string): boolean {
if (this.$store.state.user.roles) {
return this.lodash.includes(this.$store.state.user.roles, s);
if (this.$store.state.settings.roles) {
return this.lodash.includes(this.$store.state.settings.roles, s);
}
return false;
}

View File

@@ -72,7 +72,7 @@ export default Vue.extend({
},
computed: {
readonly: function (): boolean {
return !this.hasRole("engineer:automation:write");
return !this.hasRole("automation:write");
},
types: function (): Array<string> {
return [ AutomationResponseTypeEnum.Global, AutomationResponseTypeEnum.Playbook, AutomationResponseTypeEnum.Artifact ]
@@ -104,8 +104,8 @@ export default Vue.extend({
}
},
hasRole: function (s: string): boolean {
if (this.$store.state.user.roles) {
return this.lodash.includes(this.$store.state.user.roles, s);
if (this.$store.state.settings.roles) {
return this.lodash.includes(this.$store.state.settings.roles, s);
}
return false;
},

View File

@@ -7,7 +7,7 @@
itemname="id"
singular="Automation"
plural="Automations"
writepermission="engineer:automation:write"
writepermission="automation:write"
@delete="deleteAutomation"
></List>
</v-main>

View File

@@ -7,7 +7,7 @@
itemname="name"
singular="Dashboard"
plural="Dashboards"
writepermission="admin:dashboard:write"
writepermission="dashboard:write"
@delete="deleteDashboard"
></List>
</v-main>

View File

@@ -94,7 +94,7 @@ export default Vue.extend({
},
computed: {
readonly: function (): boolean {
return !this.hasRole("admin:job:write");
return !this.hasRole("job:write");
},
globalautomations: function (): Array<AutomationResponse> {
if (!this.automations) {
@@ -157,8 +157,8 @@ export default Vue.extend({
});
},
hasRole: function (s: string): boolean {
if (this.$store.state.user.roles) {
return this.lodash.includes(this.$store.state.user.roles, s);
if (this.$store.state.settings.roles) {
return this.lodash.includes(this.$store.state.settings.roles, s);
}
return false;
}

View File

@@ -68,7 +68,7 @@ export default Vue.extend({
}),
computed: {
canWrite: function (): boolean {
return this.hasRole("admin:job:write");
return this.hasRole("job:write");
},
},
methods: {
@@ -80,8 +80,8 @@ export default Vue.extend({
});
},
hasRole: function (s: string): boolean {
if (this.$store.state.user.roles) {
return this.lodash.includes(this.$store.state.user.roles, s);
if (this.$store.state.settings.roles) {
return this.lodash.includes(this.$store.state.settings.roles, s);
}
return false;
}

View File

@@ -174,7 +174,7 @@ export default Vue.extend({
}
},
readonly: function (): boolean {
return !this.hasRole("engineer:playbook:write");
return !this.hasRole("playbook:write");
},
},
methods: {
@@ -286,8 +286,8 @@ export default Vue.extend({
}
},
hasRole: function (s: string): boolean {
if (this.$store.state.user.roles) {
return this.lodash.includes(this.$store.state.user.roles, s);
if (this.$store.state.settings.roles) {
return this.lodash.includes(this.$store.state.settings.roles, s);
}
return false;
}

View File

@@ -8,7 +8,7 @@
singular="Playbook"
plural="Playbooks"
@delete="deletePlaybook"
writepermission="engineer:playbook:write"
writepermission="playbook:write"
></List>
</v-main>
</template>

View File

@@ -47,7 +47,7 @@ export default Vue.extend({
},
computed: {
readonly: function (): boolean {
return !this.hasRole("engineer:template:write");
return !this.hasRole("template:write");
},
},
methods: {
@@ -81,8 +81,8 @@ export default Vue.extend({
}
},
hasRole: function (s: string): boolean {
if (this.$store.state.user.roles) {
return this.lodash.includes(this.$store.state.user.roles, s);
if (this.$store.state.settings.roles) {
return this.lodash.includes(this.$store.state.settings.roles, s);
}
return false;
}

View File

@@ -7,7 +7,7 @@
itemname="name"
singular="Template"
plural="Templates"
writepermission="engineer:template:write"
writepermission="template:write"
@delete="deleteTemplate"
></List>
</v-main>

View File

@@ -761,7 +761,7 @@
<div style="display: flex; align-items: center" class="pb-1">
<span class="text--disabled">Files</span>
<v-spacer></v-spacer>
<v-btn v-if="hasRole('analyst:file')" small icon @click="fileDialog = true">
<v-btn v-if="hasRole('file')" small icon @click="fileDialog = true">
<v-icon>mdi-plus</v-icon>
</v-btn>
</div>
@@ -1017,8 +1017,8 @@ export default Vue.extend({
},
methods: {
hasRole: function (s: string) {
if (this.$store.state.user.roles) {
return this.lodash.includes(this.$store.state.user.roles, s);
if (this.$store.state.settings.roles) {
return this.lodash.includes(this.$store.state.settings.roles, s);
}
return false;
},

View File

@@ -8,7 +8,7 @@
singular="Ticket Type"
plural="Ticket Types"
@delete="deleteTicketType"
writepermission="engineer:tickettype:write"
writepermission="tickettype:write"
></List>
</v-main>
</template>

View File

@@ -9,7 +9,7 @@
plural="User Data"
:show-new="false"
:deletable="false"
writepermission="admin:userdata:write"
writepermission="userdata:write"
></List>
</v-main>
</template>

View File

@@ -8,7 +8,7 @@
singular="User / API Key"
plural="Users / API Keys"
@delete="deleteUser"
writepermission="admin:user:write"
writepermission="user:write"
></List>
</v-main>
</template>