瀏覽代碼

Rename before_login_program to pre_login_program

and some documentation update
Mengsk 5 年之前
父節點
當前提交
637463a068
共有 5 個文件被更改,包括 36 次插入36 次删除
  1. 7 7
      README.md
  2. 1 1
      config/config.go
  3. 15 15
      dataprovider/dataprovider.go
  4. 12 12
      sftpd/sftpd_test.go
  5. 1 1
      sftpgo.json

+ 7 - 7
README.md

@@ -12,7 +12,7 @@ Full featured and highly configurable SFTP server
 - Keyboard interactive authentication. You can easily setup a customizable multi-factor authentication.
 - 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.
 - 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.
 - 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.
 - 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.
 - Bandwidth throttling is supported, with distinct settings for upload and download.
 - Per user maximum concurrent sessions.
 - 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_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
     - `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
     - `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
 - **"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_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"
     - `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_program": "",
     "external_auth_scope": 0,
     "external_auth_scope": 0,
     "credentials_path": "credentials",
     "credentials_path": "credentials",
-    "before_login_program": ""
+    "pre_login_program": ""
   },
   },
   "httpd": {
   "httpd": {
     "bind_port": 8080,
     "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.
 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:
 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.
 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.
 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.
 
 

+ 1 - 1
config/config.go

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

+ 15 - 15
dataprovider/dataprovider.go

@@ -214,10 +214,10 @@ type Config struct {
 	//
 	//
 	// The external program must finish within 60 seconds.
 	// 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.
 	// 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
 // BackupData defines the structure for the backup/restore files
@@ -316,11 +316,11 @@ func Initialize(cnf Config, basePath string) error {
 			return err
 			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 {
 		if err != nil {
 			providerLog(logger.LevelWarn, "invalid pre login program: %v", err)
 			providerLog(logger.LevelWarn, "invalid pre login program: %v", err)
 			return err
 			return err
@@ -366,8 +366,8 @@ func CheckUserAndPass(p Provider, username string, password string) (User, error
 		}
 		}
 		return checkUserAndPass(user, password)
 		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 {
 		if err != nil {
 			return user, err
 			return user, err
 		}
 		}
@@ -385,8 +385,8 @@ func CheckUserAndPubKey(p Provider, username string, pubKey string) (User, strin
 		}
 		}
 		return checkUserAndPubKey(user, pubKey)
 		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 {
 		if err != nil {
 			return user, "", err
 			return user, "", err
 		}
 		}
@@ -402,8 +402,8 @@ func CheckKeyboardInteractiveAuth(p Provider, username, authProgram string, clie
 	var err error
 	var err error
 	if len(config.ExternalAuthProgram) > 0 && (config.ExternalAuthScope == 0 || config.ExternalAuthScope&4 != 0) {
 	if len(config.ExternalAuthProgram) > 0 && (config.ExternalAuthScope == 0 || config.ExternalAuthScope&4 != 0) {
 		user, err = doExternalAuth(username, "", "", "1")
 		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 {
 	} else {
 		user, err = p.userExists(username)
 		user, err = p.userExists(username)
 	}
 	}
@@ -1143,7 +1143,7 @@ func doKeyboardInteractiveAuth(user User, authProgram string, client ssh.Keyboar
 	return user, nil
 	return user, nil
 }
 }
 
 
-func executeBeforeLoginProgram(username, loginMethod string) (User, error) {
+func executePreLoginProgram(username, loginMethod string) (User, error) {
 	u, err := provider.userExists(username)
 	u, err := provider.userExists(username)
 	if err != nil {
 	if err != nil {
 		return u, err
 		return u, err
@@ -1155,7 +1155,7 @@ func executeBeforeLoginProgram(username, loginMethod string) (User, error) {
 
 
 	ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
 	ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
 	defer cancel()
 	defer cancel()
-	cmd := exec.CommandContext(ctx, config.BeforeLoginProgram)
+	cmd := exec.CommandContext(ctx, config.PreLoginProgram)
 	cmd.Env = append(os.Environ(),
 	cmd.Env = append(os.Environ(),
 		fmt.Sprintf("SFTPGO_LOGIND_USER=%v", string(userAsJSON)),
 		fmt.Sprintf("SFTPGO_LOGIND_USER=%v", string(userAsJSON)),
 		fmt.Sprintf("SFTPGO_LOGIND_METHOD=%v", loginMethod))
 		fmt.Sprintf("SFTPGO_LOGIND_METHOD=%v", loginMethod))

+ 12 - 12
sftpd/sftpd_test.go

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

+ 1 - 1
sftpgo.json

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