feat(config): password policy and gateway addr

This commit is contained in:
Michael Barz
2023-12-06 09:28:17 +01:00
parent 0b7162204a
commit 6755aef725
5 changed files with 97 additions and 17 deletions

View File

@@ -179,10 +179,10 @@ type ServiceAccount struct {
// PasswordPolicy configures reva password policy
type PasswordPolicy struct {
MinCharacters int `yaml:"min_characters,omitempty" env:"FRONTEND_PASSWORD_POLICY_MIN_CHARACTERS" desc:"Define the minimum password length. Defaults to 0 if not set."`
MinLowerCaseCharacters int `yaml:"min_lowercase_characters" env:"FRONTEND_PASSWORD_POLICY_MIN_LOWERCASE_CHARACTERS" desc:"Define the minimum number of uppercase letters. Defaults to 0 if not set."`
MinUpperCaseCharacters int `yaml:"min_uppercase_characters" env:"FRONTEND_PASSWORD_POLICY_MIN_UPPERCASE_CHARACTERS" desc:"Define the minimum number of lowercase letters. Defaults to 0 if not set."`
MinDigits int `yaml:"min_digits" env:"FRONTEND_PASSWORD_POLICY_MIN_DIGITS" desc:"Define the minimum number of digits. Defaults to 0 if not set."`
MinSpecialCharacters int `yaml:"min_special_characters" env:"FRONTEND_PASSWORD_POLICY_MIN_SPECIAL_CHARACTERS" desc:"Define the minimum number of characters from the special characters list to be present. Defaults to 0 if not set."`
BannedPasswordsList string `yaml:"banned_passwords_list" env:"FRONTEND_PASSWORD_POLICY_BANNED_PASSWORDS_LIST" desc:"Path to the 'banned passwords list' file. See the documentation for more details."`
MinCharacters int `yaml:"min_characters,omitempty" env:"OCIS_PASSWORD_POLICY_MIN_CHARACTERS;FRONTEND_PASSWORD_POLICY_MIN_CHARACTERS" desc:"Define the minimum password length. Defaults to 0 if not set."`
MinLowerCaseCharacters int `yaml:"min_lowercase_characters" env:"OCIS_PASSWORD_POLICY_MIN_LOWERCASE_CHARACTERS;FRONTEND_PASSWORD_POLICY_MIN_LOWERCASE_CHARACTERS" desc:"Define the minimum number of uppercase letters. Defaults to 0 if not set."`
MinUpperCaseCharacters int `yaml:"min_uppercase_characters" env:"OCIS_PASSWORD_POLICY_MIN_UPPERCASE_CHARACTERS;FRONTEND_PASSWORD_POLICY_MIN_UPPERCASE_CHARACTERS" desc:"Define the minimum number of lowercase letters. Defaults to 0 if not set."`
MinDigits int `yaml:"min_digits" env:"OCIS_PASSWORD_POLICY_MIN_DIGITS;FRONTEND_PASSWORD_POLICY_MIN_DIGITS" desc:"Define the minimum number of digits. Defaults to 0 if not set."`
MinSpecialCharacters int `yaml:"min_special_characters" env:"OCIS_PASSWORD_POLICY_MIN_SPECIAL_CHARACTERS;FRONTEND_PASSWORD_POLICY_MIN_SPECIAL_CHARACTERS" desc:"Define the minimum number of characters from the special characters list to be present. Defaults to 0 if not set."`
BannedPasswordsList string `yaml:"banned_passwords_list" env:"OCIS_PASSWORD_POLICY_BANNED_PASSWORDS_LIST;FRONTEND_PASSWORD_POLICY_BANNED_PASSWORDS_LIST" desc:"Path to the 'banned passwords list' file. See the documentation for more details."`
}

View File

@@ -57,7 +57,10 @@ func Server(cfg *config.Config) *cli.Command {
gr.Add(func() error {
pidFile := path.Join(os.TempDir(), "revad-"+cfg.Service.Name+"-"+uuid.Must(uuid.NewV4()).String()+".pid")
rCfg := revaconfig.SharingConfigFromStruct(cfg)
rCfg, err := revaconfig.SharingConfigFromStruct(cfg, logger)
if err != nil {
return err
}
reg := registry.GetRegistry()
runtime.RunWithOptions(rCfg, pidFile,

View File

@@ -26,9 +26,12 @@ type Config struct {
PublicSharingDriver string `yaml:"public_sharing_driver" env:"SHARING_PUBLIC_DRIVER" desc:"Driver to be used to persist public shares. Supported values are 'jsoncs3', 'json' and 'cs3'."`
PublicSharingDrivers PublicSharingDrivers `yaml:"public_sharing_drivers"`
WriteableShareMustHavePassword bool `yaml:"public_sharing_writeableshare_must_have_password" env:"OCIS_SHARING_PUBLIC_WRITEABLE_SHARE_MUST_HAVE_PASSWORD;SHARING_PUBLIC_WRITEABLE_SHARE_MUST_HAVE_PASSWORD" desc:"Set this to true if you want to enforce passwords on Uploader, Editor or Contributor shares. If not using the global OCIS_SHARING_PUBLIC_WRITEABLE_SHARE_MUST_HAVE_PASSWORD, you must define the FRONTEND_OCS_PUBLIC_WRITEABLE_SHARE_MUST_HAVE_PASSWORD in the frontend service."`
PublicShareMustHavePassword bool `yaml:"public_sharing_share_must_have_password" env:"OCIS_SHARING_PUBLIC_SHARE_MUST_HAVE_PASSWORD;SHARING_PUBLIC_SHARE_MUST_HAVE_PASSWORD" desc:"Set this to true if you want to enforce passwords on all public shares."`
EnableExpiredSharesCleanup bool `yaml:"enable_expired_shares_cleanup"`
Supervised bool `yaml:"-"`
Context context.Context `yaml:"-"`
PasswordPolicy PasswordPolicy `yaml:"password_policy"`
}
type Log struct {
@@ -151,3 +154,13 @@ type Events struct {
TLSRootCaCertPath string `yaml:"tls_root_ca_cert_path" env:"OCIS_EVENTS_TLS_ROOT_CA_CERTIFICATE;SHARING_EVENTS_TLS_ROOT_CA_CERTIFICATE;SHARING_EVENTS_TLS_ROOT_CA_CERT" desc:"The root CA certificate used to validate the server's TLS certificate. If provided SHARING_EVENTS_TLS_INSECURE will be seen as false." deprecationVersion:"4.0.3" removalVersion:"5.0.0" deprecationInfo:"SHARING_EVENTS_TLS_ROOT_CA_CERT changing name for consistency" deprecationReplacement:"SHARING_EVENTS_TLS_ROOT_CA_CERTIFICATE"`
EnableTLS bool `yaml:"enable_tls" env:"OCIS_EVENTS_ENABLE_TLS;SHARING_EVENTS_ENABLE_TLS" desc:"Enable TLS for the connection to the events broker. The events broker is the ocis service which receives and delivers events between the services.."`
}
// PasswordPolicy configures reva password policy
type PasswordPolicy struct {
MinCharacters int `yaml:"min_characters,omitempty" env:"OCIS_PASSWORD_POLICY_MIN_CHARACTERS;SHARING_PASSWORD_POLICY_MIN_CHARACTERS" desc:"Define the minimum password length. Defaults to 0 if not set."`
MinLowerCaseCharacters int `yaml:"min_lowercase_characters" env:"OCIS_PASSWORD_POLICY_MIN_LOWERCASE_CHARACTERS;SHARING_PASSWORD_POLICY_MIN_LOWERCASE_CHARACTERS" desc:"Define the minimum number of uppercase letters. Defaults to 0 if not set."`
MinUpperCaseCharacters int `yaml:"min_uppercase_characters" env:"OCIS_PASSWORD_POLICY_MIN_UPPERCASE_CHARACTERS;SHARING_PASSWORD_POLICY_MIN_UPPERCASE_CHARACTERS" desc:"Define the minimum number of lowercase letters. Defaults to 0 if not set."`
MinDigits int `yaml:"min_digits" env:"OCIS_PASSWORD_POLICY_MIN_DIGITS;SHARING_PASSWORD_POLICY_MIN_DIGITS" desc:"Define the minimum number of digits. Defaults to 0 if not set."`
MinSpecialCharacters int `yaml:"min_special_characters" env:"OCIS_PASSWORD_POLICY_MIN_SPECIAL_CHARACTERS;SHARING_PASSWORD_POLICY_MIN_SPECIAL_CHARACTERS" desc:"Define the minimum number of characters from the special characters list to be present. Defaults to 0 if not set."`
BannedPasswordsList string `yaml:"banned_passwords_list" env:"OCIS_PASSWORD_POLICY_BANNED_PASSWORDS_LIST;SHARING_PASSWORD_POLICY_BANNED_PASSWORDS_LIST" desc:"Path to the 'banned passwords list' file. See the documentation for more details."`
}

View File

@@ -75,7 +75,15 @@ func DefaultConfig() *config.Config {
ClusterID: "ocis-cluster",
EnableTLS: false,
},
EnableExpiredSharesCleanup: true,
EnableExpiredSharesCleanup: true,
PublicShareMustHavePassword: true,
PasswordPolicy: config.PasswordPolicy{
MinCharacters: 8,
MinLowerCaseCharacters: 1,
MinUpperCaseCharacters: 1,
MinDigits: 1,
MinSpecialCharacters: 1,
},
}
}

View File

@@ -1,11 +1,29 @@
package revaconfig
import (
"bufio"
"fmt"
"os"
"path/filepath"
"github.com/owncloud/ocis/v2/ocis-pkg/log"
"github.com/owncloud/ocis/v2/ocis-pkg/config/defaults"
"github.com/owncloud/ocis/v2/services/sharing/pkg/config"
)
// SharingConfigFromStruct will adapt an oCIS config struct into a reva mapstructure to start a reva service.
func SharingConfigFromStruct(cfg *config.Config) map[string]interface{} {
func SharingConfigFromStruct(cfg *config.Config, logger log.Logger) (map[string]interface{}, error) {
var bannedPasswordsList map[string]struct{}
var err error
if cfg.PasswordPolicy.BannedPasswordsList != "" {
bannedPasswordsList, err = readMultilineFile(cfg.PasswordPolicy.BannedPasswordsList)
if err != nil {
err = fmt.Errorf("failed to load the banned passwords from a file %s: %w", cfg.PasswordPolicy.BannedPasswordsList, err)
logger.Err(err).Send()
return nil, err
}
}
rcfg := map[string]interface{}{
"shared": map[string]interface{}{
"jwt_secret": cfg.TokenManager.JWTSecret,
@@ -73,6 +91,17 @@ func SharingConfigFromStruct(cfg *config.Config) map[string]interface{} {
},
},
"publicshareprovider": map[string]interface{}{
"gateway_addr": cfg.Reva.Address,
"writeable_share_must_have_password": cfg.WriteableShareMustHavePassword,
"public_share_must_have_password": cfg.PublicShareMustHavePassword,
"password_policy": map[string]interface{}{
"min_digits": cfg.PasswordPolicy.MinDigits,
"min_characters": cfg.PasswordPolicy.MinCharacters,
"min_lowercase_characters": cfg.PasswordPolicy.MinLowerCaseCharacters,
"min_uppercase_characters": cfg.PasswordPolicy.MinUpperCaseCharacters,
"min_special_characters": cfg.PasswordPolicy.MinSpecialCharacters,
"banned_passwords_list": bannedPasswordsList,
},
"driver": cfg.PublicSharingDriver,
"drivers": map[string]interface{}{
"json": map[string]interface{}{
@@ -97,13 +126,12 @@ func SharingConfigFromStruct(cfg *config.Config) map[string]interface{} {
"machine_auth_apikey": cfg.PublicSharingDrivers.CS3.SystemUserAPIKey,
},
"jsoncs3": map[string]interface{}{
"gateway_addr": cfg.Reva.Address,
"provider_addr": cfg.PublicSharingDrivers.JSONCS3.ProviderAddr,
"service_user_id": cfg.PublicSharingDrivers.JSONCS3.SystemUserID,
"service_user_idp": cfg.PublicSharingDrivers.JSONCS3.SystemUserIDP,
"machine_auth_apikey": cfg.PublicSharingDrivers.JSONCS3.SystemUserAPIKey,
"writeable_share_must_have_password": cfg.WriteableShareMustHavePassword,
"enable_expired_shares_cleanup": cfg.EnableExpiredSharesCleanup,
"gateway_addr": cfg.Reva.Address,
"provider_addr": cfg.PublicSharingDrivers.JSONCS3.ProviderAddr,
"service_user_id": cfg.PublicSharingDrivers.JSONCS3.SystemUserID,
"service_user_idp": cfg.PublicSharingDrivers.JSONCS3.SystemUserIDP,
"machine_auth_apikey": cfg.PublicSharingDrivers.JSONCS3.SystemUserAPIKey,
"enable_expired_shares_cleanup": cfg.EnableExpiredSharesCleanup,
},
},
},
@@ -126,5 +154,33 @@ func SharingConfigFromStruct(cfg *config.Config) map[string]interface{} {
},
},
}
return rcfg
return rcfg, nil
}
func readMultilineFile(path string) (map[string]struct{}, error) {
if !fileExists(path) {
path = filepath.Join(defaults.BaseConfigPath(), path)
}
file, err := os.Open(path)
if err != nil {
return nil, err
}
defer file.Close()
scanner := bufio.NewScanner(file)
data := make(map[string]struct{})
for scanner.Scan() {
line := scanner.Text()
if line != "" {
data[line] = struct{}{}
}
}
return data, err
}
func fileExists(path string) bool {
info, err := os.Stat(path)
if err != nil {
return false
}
return !info.IsDir()
}