Rename before_login_program to pre_login_program

and some documentation update
This commit is contained in:
Mengsk 2020-02-25 16:07:38 +01:00 committed by drakkan
parent e69536f540
commit 637463a068
5 changed files with 36 additions and 36 deletions

View file

@ -12,7 +12,7 @@ Full featured and highly configurable SFTP server
- Keyboard interactive authentication. You can easily setup a customizable multi-factor authentication.
- Per user authentication methods. You can, for example, deny one or more authentication methods to one or more users.
- Custom authentication via external programs is supported.
- Dynamic users modifications before login via external programs are supported.
- Dynamic user modification before login via external programs is supported.
- Quota support: accounts can have individual quota expressed as max total size and/or max number of files.
- Bandwidth throttling is supported, with distinct settings for upload and download.
- Per user maximum concurrent sessions.
@ -183,7 +183,7 @@ The `sftpgo` configuration file contains the following sections:
- `external_auth_program`, string. Absolute path to an external program to use for users authentication. See the "External Authentication" paragraph for more details. Leave empty to disable.
- `external_auth_scope`, integer. 0 means all supported authetication scopes (passwords, public keys and keyboard interactive). 1 means passwords only. 2 means public keys only. 4 means key keyboard interactive only. The flags can be combined, for example 6 means public keys and keyboard interactive
- `credentials_path`, string. It defines the directory for storing user provided credential files such as Google Cloud Storage credentials. This can be an absolute path or a path relative to the config dir
- `before_login_program`, string. Absolute path to an external program to use to modify user details just before the login. See the "Dynamic users modifications" paragraph for more details. Leave empty to disable.
- `pre_login_program`, string. Absolute path to an external program to use to modify user details just before the login. See the "Dynamic user modification" paragraph for more details. Leave empty to disable.
- **"httpd"**, the configuration for the HTTP server used to serve REST API
- `bind_port`, integer. The port used for serving HTTP requests. Set to 0 to disable HTTP server. Default: 8080
- `bind_address`, string. Leave blank to listen on all available network interfaces. Default: "127.0.0.1"
@ -243,7 +243,7 @@ Here is a full example showing the default config in JSON format:
"external_auth_program": "",
"external_auth_scope": 0,
"credentials_path": "credentials",
"before_login_program": ""
"pre_login_program": ""
},
"httpd": {
"bind_port": 8080,
@ -400,10 +400,10 @@ fi
If you have an external authentication program that could be useful for others too, please let us know and/or send a pull request.
## Dynamic users modifications
## Dynamic user modification
Dynamic users modifications are supported via an external program that can be executed just before the user login.
To enable dynamic users modifications you must set the absolute path of your program using the `before_login_program` key in your configuration file.
Dynamic user modification is supported via an external program that can be executed just before the user login.
To enable dynamic user modification you must set the absolute path of your program using the `pre_login_program` key in your configuration file.
The external program can read the following environment variables to get info about the user trying to login:
@ -418,7 +418,7 @@ The JSON response can include only the fields that need to the updated instead o
```
The external program must finish within 60 seconds.
If an error happens while executing your program then login will be denied. "Dynamic users modifications" and "External Authentication" are mutally exclusive.
If an error happens while executing your program then login will be denied. "Dynamic user modification" and "External Authentication" are mutally exclusive.
Let's see a very basic example. Our sample program will grant access to the user `test_user` only in the time range 10:00-18:00. Other users will not be modified since the program will terminate with no output.

View file

@ -85,7 +85,7 @@ func init() {
ExternalAuthProgram: "",
ExternalAuthScope: 0,
CredentialsPath: "credentials",
BeforeLoginProgram: "",
PreLoginProgram: "",
},
HTTPDConfig: httpd.Conf{
BindPort: 8080,

View file

@ -214,10 +214,10 @@ type Config struct {
//
// The external program must finish within 60 seconds.
//
// If an error happen while executing the "BeforeLoginProgram" then login will be denied.
// BeforeLoginProgram and ExternalAuthProgram are mutally exclusive.
// If an error happens while executing the "PreLoginProgram" then login will be denied.
// PreLoginProgram and ExternalAuthProgram are mutally exclusive.
// Leave empty to disable.
BeforeLoginProgram string `json:"before_login_program" mapstructure:"before_login_program"`
PreLoginProgram string `json:"pre_login_program" mapstructure:"pre_login_program"`
}
// BackupData defines the structure for the backup/restore files
@ -316,11 +316,11 @@ func Initialize(cnf Config, basePath string) error {
return err
}
}
if len(config.BeforeLoginProgram) > 0 {
if !filepath.IsAbs(config.BeforeLoginProgram) {
return fmt.Errorf("invalid pre login program: %#v must be an absolute path", config.BeforeLoginProgram)
if len(config.PreLoginProgram) > 0 {
if !filepath.IsAbs(config.PreLoginProgram) {
return fmt.Errorf("invalid pre login program: %#v must be an absolute path", config.PreLoginProgram)
}
_, err := os.Stat(config.BeforeLoginProgram)
_, err := os.Stat(config.PreLoginProgram)
if err != nil {
providerLog(logger.LevelWarn, "invalid pre login program: %v", err)
return err
@ -366,8 +366,8 @@ func CheckUserAndPass(p Provider, username string, password string) (User, error
}
return checkUserAndPass(user, password)
}
if len(config.BeforeLoginProgram) > 0 {
user, err := executeBeforeLoginProgram(username, SSHLoginMethodPassword)
if len(config.PreLoginProgram) > 0 {
user, err := executePreLoginProgram(username, SSHLoginMethodPassword)
if err != nil {
return user, err
}
@ -385,8 +385,8 @@ func CheckUserAndPubKey(p Provider, username string, pubKey string) (User, strin
}
return checkUserAndPubKey(user, pubKey)
}
if len(config.BeforeLoginProgram) > 0 {
user, err := executeBeforeLoginProgram(username, SSHLoginMethodPublicKey)
if len(config.PreLoginProgram) > 0 {
user, err := executePreLoginProgram(username, SSHLoginMethodPublicKey)
if err != nil {
return user, "", err
}
@ -402,8 +402,8 @@ func CheckKeyboardInteractiveAuth(p Provider, username, authProgram string, clie
var err error
if len(config.ExternalAuthProgram) > 0 && (config.ExternalAuthScope == 0 || config.ExternalAuthScope&4 != 0) {
user, err = doExternalAuth(username, "", "", "1")
} else if len(config.BeforeLoginProgram) > 0 {
user, err = executeBeforeLoginProgram(username, SSHLoginMethodKeyboardInteractive)
} else if len(config.PreLoginProgram) > 0 {
user, err = executePreLoginProgram(username, SSHLoginMethodKeyboardInteractive)
} else {
user, err = p.userExists(username)
}
@ -1143,7 +1143,7 @@ func doKeyboardInteractiveAuth(user User, authProgram string, client ssh.Keyboar
return user, nil
}
func executeBeforeLoginProgram(username, loginMethod string) (User, error) {
func executePreLoginProgram(username, loginMethod string) (User, error) {
u, err := provider.userExists(username)
if err != nil {
return u, err
@ -1155,7 +1155,7 @@ func executeBeforeLoginProgram(username, loginMethod string) (User, error) {
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
defer cancel()
cmd := exec.CommandContext(ctx, config.BeforeLoginProgram)
cmd := exec.CommandContext(ctx, config.PreLoginProgram)
cmd.Env = append(os.Environ(),
fmt.Sprintf("SFTPGO_LOGIND_USER=%v", string(userAsJSON)),
fmt.Sprintf("SFTPGO_LOGIND_METHOD=%v", loginMethod))

View file

@ -99,7 +99,7 @@ var (
gitWrapPath string
extAuthPath string
keyIntAuthPath string
beforeLoginPath string
preLoginPath string
logFilePath string
)
@ -172,7 +172,7 @@ func TestMain(m *testing.M) {
privateKeyPath = filepath.Join(homeBasePath, "ssh_key")
gitWrapPath = filepath.Join(homeBasePath, "gitwrap.sh")
extAuthPath = filepath.Join(homeBasePath, "extauth.sh")
beforeLoginPath = filepath.Join(homeBasePath, "beforelogin.sh")
preLoginPath = filepath.Join(homeBasePath, "prelogin.sh")
err = ioutil.WriteFile(pubKeyPath, []byte(testPubKey+"\n"), 0600)
if err != nil {
logger.WarnToConsole("unable to save public key to file: %v", err)
@ -212,7 +212,7 @@ func TestMain(m *testing.M) {
os.Remove(privateKeyPath)
os.Remove(gitWrapPath)
os.Remove(extAuthPath)
os.Remove(beforeLoginPath)
os.Remove(preLoginPath)
os.Remove(keyIntAuthPath)
os.Exit(exitCode)
}
@ -1305,7 +1305,7 @@ func TestLoginKeyboardInteractiveAuth(t *testing.T) {
os.RemoveAll(user.GetHomeDir())
}
func TestBeforeLoginScript(t *testing.T) {
func TestPreLoginScript(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("this test is not available on Windows")
}
@ -1315,8 +1315,8 @@ func TestBeforeLoginScript(t *testing.T) {
dataprovider.Close(dataProvider)
config.LoadConfig(configDir, "")
providerConf := config.GetProviderConf()
ioutil.WriteFile(beforeLoginPath, getBeforeLoginScriptContent(u, false), 0755)
providerConf.BeforeLoginProgram = beforeLoginPath
ioutil.WriteFile(preLoginPath, getPreLoginScriptContent(u, false), 0755)
providerConf.PreLoginProgram = preLoginPath
err := dataprovider.Initialize(providerConf, configDir)
if err != nil {
t.Errorf("error initializing data provider")
@ -1338,16 +1338,16 @@ func TestBeforeLoginScript(t *testing.T) {
t.Errorf("unable to get working dir: %v", err)
}
}
ioutil.WriteFile(beforeLoginPath, getBeforeLoginScriptContent(user, true), 0755)
ioutil.WriteFile(preLoginPath, getPreLoginScriptContent(user, true), 0755)
_, err = getSftpClient(u, usePubKey)
if err == nil {
t.Error("before login script returned a non json response, login must fail")
t.Error("pre login script returned a non json response, login must fail")
}
user.Status = 0
ioutil.WriteFile(beforeLoginPath, getBeforeLoginScriptContent(user, false), 0755)
ioutil.WriteFile(preLoginPath, getPreLoginScriptContent(user, false), 0755)
_, err = getSftpClient(u, usePubKey)
if err == nil {
t.Error("before login script returned a disabled user, login must fail")
t.Error("pre login script returned a disabled user, login must fail")
}
_, err = httpd.RemoveUser(user, http.StatusOK)
if err != nil {
@ -1364,7 +1364,7 @@ func TestBeforeLoginScript(t *testing.T) {
}
httpd.SetDataProvider(dataprovider.GetProvider())
sftpd.SetDataProvider(dataprovider.GetProvider())
os.Remove(beforeLoginPath)
os.Remove(preLoginPath)
}
func TestLoginExternalAuthPwdAndPubKey(t *testing.T) {
@ -5042,7 +5042,7 @@ func getExtAuthScriptContent(user dataprovider.User, sleepTime int, nonJsonRespo
return extAuthContent
}
func getBeforeLoginScriptContent(user dataprovider.User, nonJsonResponse bool) []byte {
func getPreLoginScriptContent(user dataprovider.User, nonJsonResponse bool) []byte {
content := []byte("#!/bin/sh\n\n")
if nonJsonResponse {
content = append(content, []byte("echo 'text response'\n")...)

View file

@ -44,7 +44,7 @@
"external_auth_program": "",
"external_auth_scope": 0,
"credentials_path": "credentials",
"before_login_program": ""
"pre_login_program": ""
},
"httpd": {
"bind_port": 8080,