Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
services:
ctfd:
image: ctfd/ctfd:3.7.7@sha256:9847758cdafc5ab86bdc121353dcf5a27a29ce313587270ee90a71bfbda2b910
image: ctfd/ctfd:3.8.0@sha256:61712c4af6e9cddccfafc4503484c8091f6325be286d407595b922dc9552b5ae
ports:
- 8000:8000
steps:
Expand Down
22 changes: 22 additions & 0 deletions action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ inputs:
description: 'Whether to allow team creation by players or not.'
accounts_team_size:
description: 'Maximum size (number of players) in a team.'
accounts_password_min_length:
description: 'Minimal length of password.'
accounts_num_teams:
description: 'The total number of teams allowed.'
accounts_num_users:
Expand All @@ -58,6 +60,17 @@ inputs:
description: 'Maximum number of invalid submissions per minute (per user/team). We suggest you use it as part of an anti-brute-force strategy (rate limiting).'
accounts_name_changes:
description: 'Whether a user can change its name or not.'
# Challenges
challenges_view_self_submissions:
description: 'Whether a player can see itw own previous submissions.'
challenges_max_attempts_behavior:
description: 'The behavior to adopt in case a player reached the submission rate limiting.'
challenges_max_attempts_timeout:
description: 'The duration of the submission rate limit for further submissions.'
challenges_hints_free_public_access:
description: 'Control whether users must be logged in to see free hints.'
challenges_challenge_ratings:
description: 'Who can see and submit challenge ratings.'
# Pages
pages_robots_txt:
description: 'Define the /robots.txt file content, for web crawlers indexing.'
Expand Down Expand Up @@ -133,6 +146,8 @@ inputs:
# Social
social_shares:
description: 'Whether to enable users share they solved a challenge or not.'
social_template:
description: 'A template for social shares. Provide a path to a locally-accessible file.'
# Legal
legal_tos_url:
description: 'The Terms of Services URL.'
Expand Down Expand Up @@ -175,11 +190,17 @@ runs:
ACCOUNTS_VERIFY_EMAILS: ${{ inputs.accounts_verify_emails }}
ACCOUNTS_TEAM_CREATION: ${{ inputs.accounts_team_creation }}
ACCOUNTS_TEAM_SIZE: ${{ inputs.accounts_team_size }}
ACCOUNTS_PASSWORD_MIN_LENGTH: ${{ inputs.accounts_password_min_length }}
ACCOUNTS_NUM_TEAMS: ${{ inputs.accounts_num_teams }}
ACCOUNTS_NUM_USERS: ${{ inputs.accounts_num_users }}
ACCOUNTS_TEAM_DISBANDING: ${{ inputs.accounts_team_disbanding }}
ACCOUNTS_INCORRECT_SUBMISSIONS_PER_MINUTE: ${{ inputs.accounts_incorrect_submissions_per_minute }}
ACCOUNTS_NAME_CHANGES: ${{ inputs.accounts_name_changes }}
CHALLENGES_VIEW_SELF_SUBMISSIONS: ${{ inputs.challenges_view_self_submissions }}
CHALLENGES_MAX_ATTEMPTS_BEHAVIOR: ${{ inputs.challenges_max_attempts_behavior }}
CHALLENGES_MAX_ATTEMPTS_TIMEOUT: ${{ inputs.challenges_max_attempts_timeout }}
CHALLENGES_HINTS_FREE_PUBLIC_ACCESS: ${{ inputs.challenges_hints_free_public_access }}
CHALLENGES_CHALLENGE_RATINGS: ${{ inputs.challenges_challenge_ratings }}
PAGES_ROBOTS_TXT: ${{ inputs.pages_robots_txt }}
MAJOR_LEAGUE_CYBER_CLIENT_ID: ${{ inputs.major_league_cyber_client_id }}
MAJOR_LEAGUE_CYBER_CLIENT_SECRET: ${{ inputs.major_league_cyber_client_secret }}
Expand Down Expand Up @@ -212,6 +233,7 @@ runs:
TIME_FREEZE: ${{ inputs.time_freeze }}
TIME_VIEW_AFTER: ${{ inputs.time_view_after }}
SOCIAL_SHARES: ${{ inputs.social_shares }}
SOCIAL_TEMPLATE: ${{ inputs.social_template }}
LEGAL_TOS_URL: ${{ inputs.legal_tos_url }}
LEGAL_TOS_CONTENT: ${{ inputs.legal_tos_content }}
LEGAL_PRIVACY_POLICY_URL: ${{ inputs.legal_privacy_policy_url }}
Expand Down
61 changes: 60 additions & 1 deletion cmd/ctfd-setup/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,12 @@ func main() {
Sources: cli.EnvVars("ACCOUNTS_TEAM_SIZE", "PLUGIN_ACCOUNTS_TEAM_SIZE"),
Category: configuration,
},
&cli.IntFlag{
Name: "accounts.password_min_length",
Usage: "Minimal length of password.",
Sources: cli.EnvVars("ACCOUNTS_PASSWORD_MIN_LENGTH", "PLUGIN_ACCOUNTS_PASSWORD_MIN_LENGTH"),
Category: configuration,
},
&cli.IntFlag{
Name: "accounts.num_teams",
Usage: "The total number of teams allowed.",
Expand Down Expand Up @@ -185,6 +191,39 @@ func main() {
Sources: cli.EnvVars("ACCOUNTS_NAME_CHANGES", "PLUGIN_ACCOUNTS_NAME_CHANGES"),
Category: configuration,
},
// => Challenges
&cli.BoolFlag{
Name: "challenges.view_self_submissions",
Usage: "Whether a player can see itw own previous submissions.",
Sources: cli.EnvVars("CHALLENGES_VIEW_SELF_SUBMISSIONS", "PLUGIN_CHALLENGES_VIEW_SELF_SUBMISSIONS"),
Category: configuration,
},
&cli.StringFlag{
Name: "challenges.max_attempts_behavior",
Usage: "The behavior to adopt in case a player reached the submission rate limiting.",
Value: "lockout",
Sources: cli.EnvVars("CHALLENGES_MAX_ATTEMPTS_BEHAVIOR", "PLUGIN_CHALLENGES_MAX_ATTEMPTS_BEHAVIOR"),
Category: configuration,
},
&cli.IntFlag{
Name: "challenges.max_attempts_timeout",
Usage: "The duration of the submission rate limit for further submissions.",
Sources: cli.EnvVars("CHALLENGES_MAX_ATTEMPTS_TIMEOUT", "PLUGIN_CHALLENGES_MAX_ATTEMPTS_TIMEOUT"),
Category: configuration,
},
&cli.BoolFlag{
Name: "challenges.hints_free_public_access",
Usage: "Control whether users must be logged in to see free hints.",
Sources: cli.EnvVars("CHALLENGES_HINTS_FREE_PUBLIC_ACCESS", "PUBLIC_CHALLENGES_HINTS_FREE_PUBLIC_ACCESS"),
Category: configuration,
},
&cli.StringFlag{
Name: "challenges.challenge_ratings",
Usage: "Who can see and submit challenge ratings.",
Value: "public",
Sources: cli.EnvVars("CHALLENGES_CHALLENGE_RATINGS", "PUBLIC_CHALLENGES_CHALLENGE_RATINGS"),
Category: configuration,
},
// => Pages
&cli.StringFlag{
Name: "pages.robots_txt",
Expand Down Expand Up @@ -388,6 +427,12 @@ func main() {
Sources: cli.EnvVars("SOCIAL_SHARES", "PLUGIN_SOCIAL_SHARES"),
Category: configuration,
},
&cli.StringFlag{
Name: "social.template",
Usage: "A template for social shares. Provide a path to a locally-accessible file.",
Sources: cli.EnvVars("SOCIAL_TEMPLATE", "PUBLIC_SOCIAL_TEMPLATE"),
Category: configuration,
},
// => Legal
&cli.StringFlag{
Name: "legal.tos.url",
Expand Down Expand Up @@ -516,6 +561,11 @@ func run(ctx context.Context, cmd *cli.Command) error {
if err != nil {
return err
}
socialTpl, err := filePtr(cmd, "social.template")
if err != nil {
return err
}

tos, err := filePtr(cmd, "legal.tos.content")
if err != nil {
return err
Expand Down Expand Up @@ -545,12 +595,20 @@ func run(ctx context.Context, cmd *cli.Command) error {
VerifyEmails: cmd.Bool("accounts.verify_emails"),
TeamCreation: boolPtr(cmd, "accounts.team_creation"),
TeamSize: intPtr(cmd, "accounts.team_size"),
PasswordMinLength: intPtr(cmd, "accounts.password_min_length"),
NumTeams: intPtr(cmd, "accounts.num_teams"),
NumUsers: intPtr(cmd, "accounts.num_users"),
TeamDisbanding: stringPtr(cmd, "accounts.team_disbanding"),
IncorrectSubmissionsPerMinute: intPtr(cmd, "accounts.incorrect_submissions_per_minute"),
NameChanges: boolPtr(cmd, "accounts.name_changes"),
},
Challenges: &ctfdsetup.Challenges{
ViewSelfSubmission: cmd.Bool("challenges.view_self_submissions"),
MaxAttemptsBehavior: cmd.String("challenges.max_attempts_behavior"),
MaxAttemptsTimeout: cmd.Int("challenges.max_attempts_timeout"),
HintsFreePublicAccess: cmd.Bool("challenges.hints_free_public_access"),
ChallengeRatings: cmd.String("challenges.challenge_ratings"),
},
Pages: &ctfdsetup.Pages{
RobotsTxt: robotsTxt,
},
Expand Down Expand Up @@ -603,7 +661,8 @@ func run(ctx context.Context, cmd *cli.Command) error {
ViewAfter: boolPtr(cmd, "time.view_after"),
},
Social: &ctfdsetup.Social{
Shares: boolPtr(cmd, "social.shares"),
Shares: boolPtr(cmd, "social.shares"),
Template: socialTpl,
},
Legal: &ctfdsetup.Legal{
TOS: ctfdsetup.ExternalReference{
Expand Down
29 changes: 29 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ type (
Appearance Appearance `yaml:"appearance" json:"appearance" jsonschema:"required"`
Theme *Theme `yaml:"theme,omitempty" json:"theme,omitempty"`
Accounts *Accounts `yaml:"accounts,omitempty" json:"accounts,omitempty"`
Challenges *Challenges `yaml:"challenges,omitempty" json:"challenges,omitempty"`
Pages *Pages `yaml:"pages,omitempty" json:"pages,omitempty"`
MajorLeagueCyber *MajorLeagueCyber `yaml:"major_league_cyber,omitempty" json:"major_league_cyber,omitempty"`
Settings *Settings `yaml:"settings,omitempty" json:"settings,omitempty"`
Expand Down Expand Up @@ -88,6 +89,9 @@ type (
// Maximum size (number of players) in a team.
TeamSize *int `yaml:"team_size,omitempty" json:"team_size,omitempty"`

// Minimal length of passwords.
PasswordMinLength *int `yaml:"password_min_length,omitempty" json:"password_min_length,omitempty"`

// The total number of teams allowed.
NumTeams *int `yaml:"num_teams,omitempty" json:"num_teams,omitempty"`

Expand All @@ -104,6 +108,24 @@ type (
NameChanges *bool `yaml:"name_changes,omitempty" json:"name_changes,omitempty"`
}

// Challenge-related configurations.
Challenges struct {
// Whether a player can see itw own previous submissions.
ViewSelfSubmission bool `yaml:"view_self_submissions" json:"view_self_submissions"`

// The behavior to adopt in case a player reached the submission rate limiting.
MaxAttemptsBehavior string `yaml:"max_attempts_behavior" json:"max_attempts_behavior" jsonschema:"enum=lockout,enum=timeout,default=lockout"`

// The duration of the submission rate limit for further submissions.
MaxAttemptsTimeout int `yaml:"max_attempts_timeout" json:"max_attempts_timeout"`

// Control whether users must be logged in to see free hints.
HintsFreePublicAccess bool `yaml:"hints_free_public_access" json:"hints_free_public_access"`

// Who can see and submit challenge ratings.
ChallengeRatings string `yaml:"challenge_ratings" json:"challenge_ratings" jsonschema:"enum=public,enum=private,enum=disabled,default=public"`
}

// Pages global configuration.
Pages struct {
// Define the /robots.txt file content, for web crawlers indexing.
Expand Down Expand Up @@ -238,6 +260,9 @@ type (
Social struct {
// Whether to enable users share they solved a challenge or not.
Shares *bool `yaml:"shares,omitempty" json:"shares,omitempty"`

// A template for social shares.
Template *File `yaml:"template,omitempty" json:"template,omitempty"`
}

// Legal contents for players.
Expand Down Expand Up @@ -293,6 +318,10 @@ func NewConfig() *Config {
Settings: &File{},
},
Accounts: &Accounts{},
Challenges: &Challenges{
MaxAttemptsBehavior: "lockout",
ChallengeRatings: "public",
},
Pages: &Pages{
RobotsTxt: &File{},
},
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/ctfer-io/ctfd-setup
go 1.22.2

require (
github.com/ctfer-io/go-ctfd v0.14.0
github.com/ctfer-io/go-ctfd v0.15.0
github.com/invopop/jsonschema v0.13.0
github.com/pkg/errors v0.9.1
github.com/stretchr/testify v1.11.1
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPn
github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg=
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
github.com/ctfer-io/go-ctfd v0.14.0 h1:yEETB4oMWzvEJjyWwQPt/rUrNKyLBFx7NB6e2/IcgII=
github.com/ctfer-io/go-ctfd v0.14.0/go.mod h1:ebgSW8LdP/qtRCpglK4djBp+g6kU5YM98XBZKowiCeY=
github.com/ctfer-io/go-ctfd v0.15.0 h1:gdZK83cOIWassyW+PsyMqlSBFxHhsKh+yjU+fsc5A58=
github.com/ctfer-io/go-ctfd v0.15.0/go.mod h1:cUAbm6dv5OhjR3E3/QaJBGTJ/GJ7vsXdL92SmyN/aQo=
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=
Expand Down
7 changes: 7 additions & 0 deletions setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,13 @@ func updateSetup(ctx context.Context, client *api.Client, conf *Config) error {
TeamCreation: conf.Accounts.TeamCreation,
TeamDisbanding: conf.Accounts.TeamDisbanding,
TeamSize: conf.Accounts.TeamSize,
PasswordMinLength: conf.Accounts.PasswordMinLength,
VerifyEmails: &conf.Accounts.VerifyEmails,
ViewSelfSubmission: conf.Challenges.ViewSelfSubmission,
MaxAttemptsBehavior: conf.Challenges.MaxAttemptsBehavior,
MaxAttemptsTimeout: conf.Challenges.MaxAttemptsTimeout,
HintsFreePublicAccess: conf.Challenges.HintsFreePublicAccess,
ChallengeRatings: conf.Challenges.ChallengeRatings,
RobotsTxt: ptr(string(conf.Pages.RobotsTxt.Content)),
OauthClientID: conf.MajorLeagueCyber.ClientID,
OauthClientSecret: conf.MajorLeagueCyber.ClientSecret,
Expand Down Expand Up @@ -180,6 +186,7 @@ func updateSetup(ctx context.Context, client *api.Client, conf *Config) error {
Freeze: conf.Time.Freeze,
ViewAfterCTF: conf.Time.ViewAfter,
SocialShares: conf.Social.Shares,
SocialSharesTemplate: string(conf.Social.Template.Content),
PrivacyURL: conf.Legal.PrivacyPolicy.URL,
PrivacyText: ptr(string(conf.Legal.PrivacyPolicy.Content.Content)),
TOSURL: conf.Legal.TOS.URL,
Expand Down
Loading