mirror of
https://github.com/drakkan/sftpgo.git
synced 2025-12-09 16:25:15 +03:00
Web UIs: add OpenID Connect support
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
This commit is contained in:
@@ -70,7 +70,7 @@ var (
|
||||
ProxyAllowed: nil,
|
||||
}
|
||||
defaultHTTPDBinding = httpd.Binding{
|
||||
Address: "127.0.0.1",
|
||||
Address: "",
|
||||
Port: 8080,
|
||||
EnableWebAdmin: true,
|
||||
EnableWebClient: true,
|
||||
@@ -81,6 +81,14 @@ var (
|
||||
HideLoginURL: 0,
|
||||
RenderOpenAPI: true,
|
||||
WebClientIntegrations: nil,
|
||||
OIDC: httpd.OIDC{
|
||||
ClientID: "",
|
||||
ClientSecret: "",
|
||||
ConfigURL: "",
|
||||
RedirectBaseURL: "",
|
||||
UsernameField: "",
|
||||
RoleField: "",
|
||||
},
|
||||
}
|
||||
defaultRateLimiter = common.RateLimiterConfig{
|
||||
Average: 0,
|
||||
@@ -490,6 +498,16 @@ func getRedactedGlobalConf() globalConfig {
|
||||
conf.ProviderConf.PostLoginHook = util.GetRedactedURL(conf.ProviderConf.PostLoginHook)
|
||||
conf.ProviderConf.CheckPasswordHook = util.GetRedactedURL(conf.ProviderConf.CheckPasswordHook)
|
||||
conf.SMTPConfig.Password = getRedactedPassword()
|
||||
conf.HTTPDConfig.Bindings = nil
|
||||
for _, binding := range globalConf.HTTPDConfig.Bindings {
|
||||
if binding.OIDC.ClientID != "" {
|
||||
binding.OIDC.ClientID = getRedactedPassword()
|
||||
}
|
||||
if binding.OIDC.ClientSecret != "" {
|
||||
binding.OIDC.ClientSecret = getRedactedPassword()
|
||||
}
|
||||
conf.HTTPDConfig.Bindings = append(conf.HTTPDConfig.Bindings, binding)
|
||||
}
|
||||
return conf
|
||||
}
|
||||
|
||||
@@ -1042,6 +1060,49 @@ func getWebDAVDBindingFromEnv(idx int) {
|
||||
}
|
||||
}
|
||||
|
||||
func getHTTPDOIDCFromEnv(idx int) (httpd.OIDC, bool) {
|
||||
var result httpd.OIDC
|
||||
isSet := false
|
||||
|
||||
clientID, ok := os.LookupEnv(fmt.Sprintf("SFTPGO_HTTPD__BINDINGS__%v__OIDC__CLIENT_ID", idx))
|
||||
if ok {
|
||||
result.ClientID = clientID
|
||||
isSet = true
|
||||
}
|
||||
|
||||
clientSecret, ok := os.LookupEnv(fmt.Sprintf("SFTPGO_HTTPD__BINDINGS__%v__OIDC__CLIENT_SECRET", idx))
|
||||
if ok {
|
||||
result.ClientSecret = clientSecret
|
||||
isSet = true
|
||||
}
|
||||
|
||||
configURL, ok := os.LookupEnv(fmt.Sprintf("SFTPGO_HTTPD__BINDINGS__%v__OIDC__CONFIG_URL", idx))
|
||||
if ok {
|
||||
result.ConfigURL = configURL
|
||||
isSet = true
|
||||
}
|
||||
|
||||
redirectBaseURL, ok := os.LookupEnv(fmt.Sprintf("SFTPGO_HTTPD__BINDINGS__%v__OIDC__REDIRECT_BASE_URL", idx))
|
||||
if ok {
|
||||
result.RedirectBaseURL = redirectBaseURL
|
||||
isSet = true
|
||||
}
|
||||
|
||||
usernameField, ok := os.LookupEnv(fmt.Sprintf("SFTPGO_HTTPD__BINDINGS__%v__OIDC__USERNAME_FIELD", idx))
|
||||
if ok {
|
||||
result.UsernameField = usernameField
|
||||
isSet = true
|
||||
}
|
||||
|
||||
roleField, ok := os.LookupEnv(fmt.Sprintf("SFTPGO_HTTPD__BINDINGS__%v__OIDC__ROLE_FIELD", idx))
|
||||
if ok {
|
||||
result.RoleField = roleField
|
||||
isSet = true
|
||||
}
|
||||
|
||||
return result, isSet
|
||||
}
|
||||
|
||||
func getHTTPDWebClientIntegrationsFromEnv(idx int) []httpd.WebClientIntegration {
|
||||
var integrations []httpd.WebClientIntegration
|
||||
|
||||
@@ -1067,7 +1128,7 @@ func getHTTPDWebClientIntegrationsFromEnv(idx int) []httpd.WebClientIntegration
|
||||
return integrations
|
||||
}
|
||||
|
||||
func getHTTPDBindingFromEnv(idx int) {
|
||||
func getDefaultHTTPBinding(idx int) httpd.Binding {
|
||||
binding := httpd.Binding{
|
||||
EnableWebAdmin: true,
|
||||
EnableWebClient: true,
|
||||
@@ -1076,6 +1137,11 @@ func getHTTPDBindingFromEnv(idx int) {
|
||||
if len(globalConf.HTTPDConfig.Bindings) > idx {
|
||||
binding = globalConf.HTTPDConfig.Bindings[idx]
|
||||
}
|
||||
return binding
|
||||
}
|
||||
|
||||
func getHTTPDBindingFromEnv(idx int) {
|
||||
binding := getDefaultHTTPBinding(idx)
|
||||
|
||||
isSet := false
|
||||
|
||||
@@ -1145,6 +1211,12 @@ func getHTTPDBindingFromEnv(idx int) {
|
||||
isSet = true
|
||||
}
|
||||
|
||||
oidc, ok := getHTTPDOIDCFromEnv(idx)
|
||||
if ok {
|
||||
binding.OIDC = oidc
|
||||
isSet = true
|
||||
}
|
||||
|
||||
if isSet {
|
||||
if len(globalConf.HTTPDConfig.Bindings) > idx {
|
||||
globalConf.HTTPDConfig.Bindings[idx] = binding
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
sdkkms "github.com/sftpgo/sdk/kms"
|
||||
"github.com/sftpgo/sdk/kms"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -467,8 +467,8 @@ func TestPluginsFromEnv(t *testing.T) {
|
||||
os.Setenv("SFTPGO_PLUGINS__0__ARGS", "arg1,arg2")
|
||||
os.Setenv("SFTPGO_PLUGINS__0__SHA256SUM", "0a71ded61fccd59c4f3695b51c1b3d180da8d2d77ea09ccee20dac242675c193")
|
||||
os.Setenv("SFTPGO_PLUGINS__0__AUTO_MTLS", "1")
|
||||
os.Setenv("SFTPGO_PLUGINS__0__KMS_OPTIONS__SCHEME", sdkkms.SchemeAWS)
|
||||
os.Setenv("SFTPGO_PLUGINS__0__KMS_OPTIONS__ENCRYPTED_STATUS", sdkkms.SecretStatusAWS)
|
||||
os.Setenv("SFTPGO_PLUGINS__0__KMS_OPTIONS__SCHEME", kms.SchemeAWS)
|
||||
os.Setenv("SFTPGO_PLUGINS__0__KMS_OPTIONS__ENCRYPTED_STATUS", kms.SecretStatusAWS)
|
||||
os.Setenv("SFTPGO_PLUGINS__0__AUTH_OPTIONS__SCOPE", "14")
|
||||
t.Cleanup(func() {
|
||||
os.Unsetenv("SFTPGO_PLUGINS__0__TYPE")
|
||||
@@ -510,8 +510,8 @@ func TestPluginsFromEnv(t *testing.T) {
|
||||
require.Equal(t, "arg2", pluginConf.Args[1])
|
||||
require.Equal(t, "0a71ded61fccd59c4f3695b51c1b3d180da8d2d77ea09ccee20dac242675c193", pluginConf.SHA256Sum)
|
||||
require.True(t, pluginConf.AutoMTLS)
|
||||
require.Equal(t, sdkkms.SchemeAWS, pluginConf.KMSOptions.Scheme)
|
||||
require.Equal(t, sdkkms.SecretStatusAWS, pluginConf.KMSOptions.EncryptedStatus)
|
||||
require.Equal(t, kms.SchemeAWS, pluginConf.KMSOptions.Scheme)
|
||||
require.Equal(t, kms.SecretStatusAWS, pluginConf.KMSOptions.EncryptedStatus)
|
||||
require.Equal(t, 14, pluginConf.AuthOptions.Scope)
|
||||
|
||||
configAsJSON, err := json.Marshal(pluginsConf)
|
||||
@@ -524,8 +524,8 @@ func TestPluginsFromEnv(t *testing.T) {
|
||||
os.Setenv("SFTPGO_PLUGINS__0__CMD", "plugin_start_cmd1")
|
||||
os.Setenv("SFTPGO_PLUGINS__0__ARGS", "")
|
||||
os.Setenv("SFTPGO_PLUGINS__0__AUTO_MTLS", "0")
|
||||
os.Setenv("SFTPGO_PLUGINS__0__KMS_OPTIONS__SCHEME", sdkkms.SchemeVaultTransit)
|
||||
os.Setenv("SFTPGO_PLUGINS__0__KMS_OPTIONS__ENCRYPTED_STATUS", sdkkms.SecretStatusVaultTransit)
|
||||
os.Setenv("SFTPGO_PLUGINS__0__KMS_OPTIONS__SCHEME", kms.SchemeVaultTransit)
|
||||
os.Setenv("SFTPGO_PLUGINS__0__KMS_OPTIONS__ENCRYPTED_STATUS", kms.SecretStatusVaultTransit)
|
||||
err = config.LoadConfig(configDir, confName)
|
||||
assert.NoError(t, err)
|
||||
pluginsConf = config.GetPluginsConfig()
|
||||
@@ -547,8 +547,8 @@ func TestPluginsFromEnv(t *testing.T) {
|
||||
require.Len(t, pluginConf.Args, 0)
|
||||
require.Equal(t, "0a71ded61fccd59c4f3695b51c1b3d180da8d2d77ea09ccee20dac242675c193", pluginConf.SHA256Sum)
|
||||
require.False(t, pluginConf.AutoMTLS)
|
||||
require.Equal(t, sdkkms.SchemeVaultTransit, pluginConf.KMSOptions.Scheme)
|
||||
require.Equal(t, sdkkms.SecretStatusVaultTransit, pluginConf.KMSOptions.EncryptedStatus)
|
||||
require.Equal(t, kms.SchemeVaultTransit, pluginConf.KMSOptions.Scheme)
|
||||
require.Equal(t, kms.SecretStatusVaultTransit, pluginConf.KMSOptions.EncryptedStatus)
|
||||
require.Equal(t, 14, pluginConf.AuthOptions.Scope)
|
||||
|
||||
err = os.Remove(configFilePath)
|
||||
@@ -803,6 +803,12 @@ func TestHTTPDBindingsFromEnv(t *testing.T) {
|
||||
os.Setenv("SFTPGO_HTTPD__BINDINGS__2__WEB_CLIENT_INTEGRATIONS__1__FILE_EXTENSIONS", ".pdf, .txt")
|
||||
os.Setenv("SFTPGO_HTTPD__BINDINGS__2__WEB_CLIENT_INTEGRATIONS__2__URL", "http://127.0.1.1/")
|
||||
os.Setenv("SFTPGO_HTTPD__BINDINGS__2__WEB_CLIENT_INTEGRATIONS__3__FILE_EXTENSIONS", ".jpg, .txt")
|
||||
os.Setenv("SFTPGO_HTTPD__BINDINGS__2__OIDC__CLIENT_ID", "client id")
|
||||
os.Setenv("SFTPGO_HTTPD__BINDINGS__2__OIDC__CLIENT_SECRET", "client secret")
|
||||
os.Setenv("SFTPGO_HTTPD__BINDINGS__2__OIDC__CONFIG_URL", "config url")
|
||||
os.Setenv("SFTPGO_HTTPD__BINDINGS__2__OIDC__REDIRECT_BASE_URL", "redirect base url")
|
||||
os.Setenv("SFTPGO_HTTPD__BINDINGS__2__OIDC__USERNAME_FIELD", "preferred_username")
|
||||
os.Setenv("SFTPGO_HTTPD__BINDINGS__2__OIDC__ROLE_FIELD", "sftpgo_role")
|
||||
t.Cleanup(func() {
|
||||
os.Unsetenv("SFTPGO_HTTPD__BINDINGS__0__ADDRESS")
|
||||
os.Unsetenv("SFTPGO_HTTPD__BINDINGS__0__PORT")
|
||||
@@ -825,6 +831,12 @@ func TestHTTPDBindingsFromEnv(t *testing.T) {
|
||||
os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__WEB_CLIENT_INTEGRATIONS__1__FILE_EXTENSIONS")
|
||||
os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__WEB_CLIENT_INTEGRATIONS__2__URL")
|
||||
os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__WEB_CLIENT_INTEGRATIONS__3__FILE_EXTENSIONS")
|
||||
os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__OIDC__CLIENT_ID")
|
||||
os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__OIDC__CLIENT_SECRET")
|
||||
os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__OIDC__CONFIG_URL")
|
||||
os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__OIDC__REDIRECT_BASE_URL")
|
||||
os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__OIDC__USERNAME_FIELD")
|
||||
os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__OIDC__ROLE_FIELD")
|
||||
})
|
||||
|
||||
configDir := ".."
|
||||
@@ -839,6 +851,7 @@ func TestHTTPDBindingsFromEnv(t *testing.T) {
|
||||
require.True(t, bindings[0].EnableWebClient)
|
||||
require.True(t, bindings[0].RenderOpenAPI)
|
||||
require.Len(t, bindings[0].TLSCipherSuites, 1)
|
||||
require.Empty(t, bindings[0].OIDC.ConfigURL)
|
||||
require.Equal(t, "TLS_AES_128_GCM_SHA256", bindings[0].TLSCipherSuites[0])
|
||||
require.Equal(t, 0, bindings[0].HideLoginURL)
|
||||
require.Equal(t, 8000, bindings[1].Port)
|
||||
@@ -849,7 +862,7 @@ func TestHTTPDBindingsFromEnv(t *testing.T) {
|
||||
require.True(t, bindings[1].RenderOpenAPI)
|
||||
require.Nil(t, bindings[1].TLSCipherSuites)
|
||||
require.Equal(t, 1, bindings[1].HideLoginURL)
|
||||
|
||||
require.Empty(t, bindings[1].OIDC.ClientID)
|
||||
require.Equal(t, 9000, bindings[2].Port)
|
||||
require.Equal(t, "127.0.1.1", bindings[2].Address)
|
||||
require.True(t, bindings[2].EnableHTTPS)
|
||||
@@ -867,6 +880,12 @@ func TestHTTPDBindingsFromEnv(t *testing.T) {
|
||||
require.Len(t, bindings[2].WebClientIntegrations, 1)
|
||||
require.Equal(t, "http://127.0.0.1/", bindings[2].WebClientIntegrations[0].URL)
|
||||
require.Equal(t, []string{".pdf", ".txt"}, bindings[2].WebClientIntegrations[0].FileExtensions)
|
||||
require.Equal(t, "client id", bindings[2].OIDC.ClientID)
|
||||
require.Equal(t, "client secret", bindings[2].OIDC.ClientSecret)
|
||||
require.Equal(t, "config url", bindings[2].OIDC.ConfigURL)
|
||||
require.Equal(t, "redirect base url", bindings[2].OIDC.RedirectBaseURL)
|
||||
require.Equal(t, "preferred_username", bindings[2].OIDC.UsernameField)
|
||||
require.Equal(t, "sftpgo_role", bindings[2].OIDC.RoleField)
|
||||
}
|
||||
|
||||
func TestHTTPClientCertificatesFromEnv(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user