mirror of
https://github.com/SecurityBrewery/catalyst.git
synced 2025-12-06 15:22:47 +01:00
152 lines
5.6 KiB
Go
152 lines
5.6 KiB
Go
package cmd
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/alecthomas/kong"
|
|
kongyaml "github.com/alecthomas/kong-yaml"
|
|
"github.com/coreos/go-oidc/v3/oidc"
|
|
"golang.org/x/oauth2"
|
|
|
|
"github.com/SecurityBrewery/catalyst"
|
|
"github.com/SecurityBrewery/catalyst/bus"
|
|
"github.com/SecurityBrewery/catalyst/database"
|
|
"github.com/SecurityBrewery/catalyst/generated/models"
|
|
"github.com/SecurityBrewery/catalyst/pointer"
|
|
"github.com/SecurityBrewery/catalyst/role"
|
|
"github.com/SecurityBrewery/catalyst/storage"
|
|
)
|
|
|
|
type CLI struct {
|
|
Secret string `env:"SECRET" required:"" help:"A random secret value (can be created with 'openssl rand -hex 32')"`
|
|
ExternalAddress string `env:"EXTERNAL_ADDRESS" required:""`
|
|
CatalystAddress string `env:"CATALYST_ADDRESS" default:"http://catalyst"`
|
|
|
|
OIDCIssuer string `env:"OIDC_ISSUER" required:""`
|
|
OIDCClientID string `env:"OIDC_CLIENT_ID" default:"catalyst"`
|
|
OIDCClientSecret string `env:"OIDC_CLIENT_SECRET" required:""`
|
|
OIDCScopes []string `env:"OIDC_SCOPES" help:"Additional scopes, ['oidc', 'profile', 'email'] are always added." placeholder:"customscopes"`
|
|
OIDCClaimUsername string `env:"OIDC_CLAIM_USERNAME" default:"preferred_username" help:"username field in the OIDC claim"`
|
|
OIDCClaimEmail string `env:"OIDC_CLAIM_EMAIL" default:"email" help:"email field in the OIDC claim"`
|
|
OIDCClaimName string `env:"OIDC_CLAIM_NAME" default:"name" help:"name field in the OIDC claim"`
|
|
AuthBlockNew bool `env:"AUTH_BLOCK_NEW" default:"true" help:"Block newly created users"`
|
|
AuthDefaultRoles []string `env:"AUTH_DEFAULT_ROLES" help:"Default roles for new users"`
|
|
|
|
IndexPath string `env:"INDEX_PATH" default:"index.bleve" help:"Path for the bleve index"`
|
|
|
|
ArangoDBHost string `env:"ARANGO_DB_HOST" default:"http://arangodb:8529"`
|
|
ArangoDBUser string `env:"ARANGO_DB_USER" default:"root"`
|
|
ArangoDBPassword string `env:"ARANGO_DB_PASSWORD" required:""`
|
|
|
|
S3Host string `env:"S3_HOST" default:"http://minio:9000" name:"s3-host"`
|
|
S3User string `env:"S3_USER" default:"minio" name:"s3-user"`
|
|
S3Password string `env:"S3_PASSWORD" required:"" name:"s3-password"`
|
|
|
|
EmitterIOHost string `env:"EMITTER_IO_HOST" default:"tcp://emitter:8080"`
|
|
EmitterIORKey string `env:"EMITTER_IO_KEY" required:""`
|
|
|
|
Timeformat string `env:"TIMEFORMAT" default:"yyyy-MM-dd HH:mm:ss" help:""`
|
|
ArtifactStates []map[string]string `env:"ARTIFACT_STATES"`
|
|
InitialAPIKey string `env:"INITIAL_API_KEY"`
|
|
}
|
|
|
|
func ParseCatalystConfig() (*catalyst.Config, error) {
|
|
var cli CLI
|
|
kong.Parse(
|
|
&cli,
|
|
kong.Configuration(kong.JSON, "/etc/catalyst.json", ".catalyst.json"),
|
|
kong.Configuration(kongyaml.Loader, "/etc/catalyst.yaml", ".catalyst.yaml"),
|
|
)
|
|
|
|
return MapConfig(cli)
|
|
}
|
|
|
|
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))
|
|
|
|
artifactStates, err := toTypes(cli.ArtifactStates)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if len(artifactStates) == 0 {
|
|
artifactStates = []*models.Type{
|
|
{Icon: "mdi-help-circle-outline", ID: "unknown", Name: "Unknown", Color: pointer.String(models.TypeColorInfo)},
|
|
{Icon: "mdi-skull", ID: "malicious", Name: "Malicious", Color: pointer.String(models.TypeColorError)},
|
|
{Icon: "mdi-check", ID: "clean", Name: "Clean", Color: pointer.String(models.TypeColorSuccess)},
|
|
}
|
|
}
|
|
|
|
scopes := unique(append([]string{oidc.ScopeOpenID, "profile", "email"}, cli.OIDCScopes...))
|
|
config := &catalyst.Config{
|
|
IndexPath: cli.IndexPath,
|
|
DB: &database.Config{Host: cli.ArangoDBHost, User: cli.ArangoDBUser, Password: cli.ArangoDBPassword},
|
|
Storage: &storage.Config{Host: cli.S3Host, User: cli.S3User, Password: cli.S3Password},
|
|
Secret: []byte(cli.Secret),
|
|
ExternalAddress: cli.ExternalAddress,
|
|
Auth: &catalyst.AuthConfig{
|
|
OIDCIssuer: cli.OIDCIssuer,
|
|
OAuth2: &oauth2.Config{ClientID: cli.OIDCClientID, ClientSecret: cli.OIDCClientSecret, RedirectURL: cli.ExternalAddress + "/callback", Scopes: scopes},
|
|
OIDCClaimUsername: cli.OIDCClaimUsername,
|
|
OIDCClaimEmail: cli.OIDCClaimEmail,
|
|
OIDCClaimName: cli.OIDCClaimName,
|
|
AuthBlockNew: cli.AuthBlockNew,
|
|
AuthDefaultRoles: roles,
|
|
},
|
|
Bus: &bus.Config{Host: cli.EmitterIOHost, Key: cli.EmitterIORKey, APIUrl: cli.CatalystAddress + "/api"},
|
|
UISettings: &models.Settings{
|
|
ArtifactStates: artifactStates,
|
|
Timeformat: cli.Timeformat,
|
|
Version: catalyst.GetVersion(),
|
|
Tier: models.SettingsTierCommunity,
|
|
},
|
|
InitialAPIKey: cli.InitialAPIKey,
|
|
}
|
|
return config, nil
|
|
}
|
|
|
|
func toTypes(params []map[string]string) ([]*models.Type, error) {
|
|
var types []*models.Type
|
|
for _, param := range params {
|
|
t := &models.Type{}
|
|
|
|
icon, iconOK := param["icon"]
|
|
if iconOK {
|
|
t.Icon = icon
|
|
}
|
|
id, idOK := param["id"]
|
|
if idOK {
|
|
t.ID = id
|
|
}
|
|
name, nameOK := param["name"]
|
|
if nameOK {
|
|
t.Name = name
|
|
}
|
|
color, ok := param["color"]
|
|
if ok {
|
|
t.Color = pointer.String(color)
|
|
}
|
|
|
|
if iconOK && idOK && nameOK {
|
|
types = append(types, t)
|
|
} else {
|
|
return nil, fmt.Errorf("incomplete type: icon, id and name need to be provided (%s)", params)
|
|
}
|
|
}
|
|
return types, nil
|
|
}
|
|
|
|
func unique(l []string) []string {
|
|
keys := make(map[string]bool)
|
|
var list []string
|
|
for _, entry := range l {
|
|
if _, value := keys[entry]; !value {
|
|
keys[entry] = true
|
|
list = append(list, entry)
|
|
}
|
|
}
|
|
return list
|
|
}
|