2017-05-23 18:56:10 +00:00
|
|
|
package handler
|
2016-12-18 05:21:29 +00:00
|
|
|
|
|
|
|
import (
|
2017-06-01 08:14:55 +00:00
|
|
|
"encoding/json"
|
|
|
|
|
|
|
|
"github.com/asaskevich/govalidator"
|
2016-12-18 05:21:29 +00:00
|
|
|
"github.com/portainer/portainer"
|
2018-01-06 17:53:12 +00:00
|
|
|
"github.com/portainer/portainer/filesystem"
|
2017-05-23 18:56:10 +00:00
|
|
|
httperror "github.com/portainer/portainer/http/error"
|
|
|
|
"github.com/portainer/portainer/http/security"
|
2016-12-18 05:21:29 +00:00
|
|
|
|
|
|
|
"log"
|
|
|
|
"net/http"
|
|
|
|
"os"
|
2016-12-25 20:34:02 +00:00
|
|
|
|
|
|
|
"github.com/gorilla/mux"
|
2016-12-18 05:21:29 +00:00
|
|
|
)
|
|
|
|
|
2017-06-01 08:14:55 +00:00
|
|
|
// SettingsHandler represents an HTTP API handler for managing Settings.
|
2016-12-18 05:21:29 +00:00
|
|
|
type SettingsHandler struct {
|
|
|
|
*mux.Router
|
2017-06-01 08:14:55 +00:00
|
|
|
Logger *log.Logger
|
|
|
|
SettingsService portainer.SettingsService
|
2017-08-10 08:35:23 +00:00
|
|
|
LDAPService portainer.LDAPService
|
|
|
|
FileService portainer.FileService
|
2016-12-18 05:21:29 +00:00
|
|
|
}
|
|
|
|
|
2017-06-01 08:14:55 +00:00
|
|
|
// NewSettingsHandler returns a new instance of OldSettingsHandler.
|
|
|
|
func NewSettingsHandler(bouncer *security.RequestBouncer) *SettingsHandler {
|
2016-12-18 05:21:29 +00:00
|
|
|
h := &SettingsHandler{
|
2017-06-01 08:14:55 +00:00
|
|
|
Router: mux.NewRouter(),
|
|
|
|
Logger: log.New(os.Stderr, "", log.LstdFlags),
|
2016-12-18 05:21:29 +00:00
|
|
|
}
|
2017-03-12 16:24:15 +00:00
|
|
|
h.Handle("/settings",
|
2017-08-10 08:35:23 +00:00
|
|
|
bouncer.AdministratorAccess(http.HandlerFunc(h.handleGetSettings))).Methods(http.MethodGet)
|
2017-06-01 08:14:55 +00:00
|
|
|
h.Handle("/settings",
|
|
|
|
bouncer.AdministratorAccess(http.HandlerFunc(h.handlePutSettings))).Methods(http.MethodPut)
|
2017-08-10 08:35:23 +00:00
|
|
|
h.Handle("/settings/public",
|
|
|
|
bouncer.PublicAccess(http.HandlerFunc(h.handleGetPublicSettings))).Methods(http.MethodGet)
|
|
|
|
h.Handle("/settings/authentication/checkLDAP",
|
|
|
|
bouncer.AdministratorAccess(http.HandlerFunc(h.handlePutSettingsLDAPCheck))).Methods(http.MethodPut)
|
2017-03-12 16:24:15 +00:00
|
|
|
|
2016-12-18 05:21:29 +00:00
|
|
|
return h
|
|
|
|
}
|
|
|
|
|
2017-08-13 14:45:55 +00:00
|
|
|
type (
|
|
|
|
publicSettingsResponse struct {
|
2017-09-27 07:26:04 +00:00
|
|
|
LogoURL string `json:"LogoURL"`
|
2017-11-26 09:05:03 +00:00
|
|
|
DisplayDonationHeader bool `json:"DisplayDonationHeader"`
|
2017-09-27 07:26:04 +00:00
|
|
|
DisplayExternalContributors bool `json:"DisplayExternalContributors"`
|
|
|
|
AuthenticationMethod portainer.AuthenticationMethod `json:"AuthenticationMethod"`
|
|
|
|
AllowBindMountsForRegularUsers bool `json:"AllowBindMountsForRegularUsers"`
|
|
|
|
AllowPrivilegedModeForRegularUsers bool `json:"AllowPrivilegedModeForRegularUsers"`
|
2017-08-13 14:45:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
putSettingsRequest struct {
|
2017-09-27 07:26:04 +00:00
|
|
|
TemplatesURL string `valid:"required"`
|
|
|
|
LogoURL string `valid:""`
|
|
|
|
BlackListedLabels []portainer.Pair `valid:""`
|
2017-11-26 09:05:03 +00:00
|
|
|
DisplayDonationHeader bool `valid:""`
|
2017-09-27 07:26:04 +00:00
|
|
|
DisplayExternalContributors bool `valid:""`
|
|
|
|
AuthenticationMethod int `valid:"required"`
|
|
|
|
LDAPSettings portainer.LDAPSettings `valid:""`
|
|
|
|
AllowBindMountsForRegularUsers bool `valid:""`
|
|
|
|
AllowPrivilegedModeForRegularUsers bool `valid:""`
|
2017-08-13 14:45:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
putSettingsLDAPCheckRequest struct {
|
|
|
|
LDAPSettings portainer.LDAPSettings `valid:""`
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
2016-12-18 05:21:29 +00:00
|
|
|
// handleGetSettings handles GET requests on /settings
|
|
|
|
func (handler *SettingsHandler) handleGetSettings(w http.ResponseWriter, r *http.Request) {
|
2017-06-01 08:14:55 +00:00
|
|
|
settings, err := handler.SettingsService.Settings()
|
|
|
|
if err != nil {
|
|
|
|
httperror.WriteErrorResponse(w, err, http.StatusInternalServerError, handler.Logger)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
encodeJSON(w, settings, handler.Logger)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2017-08-10 08:35:23 +00:00
|
|
|
// handleGetPublicSettings handles GET requests on /settings/public
|
|
|
|
func (handler *SettingsHandler) handleGetPublicSettings(w http.ResponseWriter, r *http.Request) {
|
|
|
|
settings, err := handler.SettingsService.Settings()
|
|
|
|
if err != nil {
|
|
|
|
httperror.WriteErrorResponse(w, err, http.StatusInternalServerError, handler.Logger)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
publicSettings := &publicSettingsResponse{
|
2017-09-27 07:26:04 +00:00
|
|
|
LogoURL: settings.LogoURL,
|
2017-11-26 09:05:03 +00:00
|
|
|
DisplayDonationHeader: settings.DisplayDonationHeader,
|
2017-09-27 07:26:04 +00:00
|
|
|
DisplayExternalContributors: settings.DisplayExternalContributors,
|
|
|
|
AuthenticationMethod: settings.AuthenticationMethod,
|
|
|
|
AllowBindMountsForRegularUsers: settings.AllowBindMountsForRegularUsers,
|
|
|
|
AllowPrivilegedModeForRegularUsers: settings.AllowPrivilegedModeForRegularUsers,
|
2017-08-10 08:35:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
encodeJSON(w, publicSettings, handler.Logger)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2017-06-01 08:14:55 +00:00
|
|
|
// handlePutSettings handles PUT requests on /settings
|
|
|
|
func (handler *SettingsHandler) handlePutSettings(w http.ResponseWriter, r *http.Request) {
|
|
|
|
var req putSettingsRequest
|
|
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
|
|
httperror.WriteErrorResponse(w, ErrInvalidJSON, http.StatusBadRequest, handler.Logger)
|
2016-12-18 05:21:29 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2017-06-01 08:14:55 +00:00
|
|
|
_, err := govalidator.ValidateStruct(req)
|
|
|
|
if err != nil {
|
|
|
|
httperror.WriteErrorResponse(w, ErrInvalidRequestFormat, http.StatusBadRequest, handler.Logger)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
settings := &portainer.Settings{
|
2017-09-27 07:26:04 +00:00
|
|
|
TemplatesURL: req.TemplatesURL,
|
|
|
|
LogoURL: req.LogoURL,
|
|
|
|
BlackListedLabels: req.BlackListedLabels,
|
2017-11-26 09:05:03 +00:00
|
|
|
DisplayDonationHeader: req.DisplayDonationHeader,
|
2017-09-27 07:26:04 +00:00
|
|
|
DisplayExternalContributors: req.DisplayExternalContributors,
|
|
|
|
LDAPSettings: req.LDAPSettings,
|
|
|
|
AllowBindMountsForRegularUsers: req.AllowBindMountsForRegularUsers,
|
|
|
|
AllowPrivilegedModeForRegularUsers: req.AllowPrivilegedModeForRegularUsers,
|
2017-08-10 08:35:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if req.AuthenticationMethod == 1 {
|
|
|
|
settings.AuthenticationMethod = portainer.AuthenticationInternal
|
|
|
|
} else if req.AuthenticationMethod == 2 {
|
|
|
|
settings.AuthenticationMethod = portainer.AuthenticationLDAP
|
|
|
|
} else {
|
|
|
|
httperror.WriteErrorResponse(w, ErrInvalidRequestFormat, http.StatusBadRequest, handler.Logger)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if (settings.LDAPSettings.TLSConfig.TLS || settings.LDAPSettings.StartTLS) && !settings.LDAPSettings.TLSConfig.TLSSkipVerify {
|
2018-01-06 17:53:12 +00:00
|
|
|
caCertPath, _ := handler.FileService.GetPathForTLSFile(filesystem.LDAPStorePath, portainer.TLSFileCA)
|
2017-08-10 08:35:23 +00:00
|
|
|
settings.LDAPSettings.TLSConfig.TLSCACertPath = caCertPath
|
|
|
|
} else {
|
|
|
|
settings.LDAPSettings.TLSConfig.TLSCACertPath = ""
|
2018-01-06 17:53:12 +00:00
|
|
|
err := handler.FileService.DeleteTLSFiles(filesystem.LDAPStorePath)
|
2017-08-10 08:35:23 +00:00
|
|
|
if err != nil {
|
|
|
|
httperror.WriteErrorResponse(w, err, http.StatusInternalServerError, handler.Logger)
|
|
|
|
}
|
2017-06-01 08:14:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
err = handler.SettingsService.StoreSettings(settings)
|
|
|
|
if err != nil {
|
|
|
|
httperror.WriteErrorResponse(w, err, http.StatusInternalServerError, handler.Logger)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-10 08:35:23 +00:00
|
|
|
// handlePutSettingsLDAPCheck handles PUT requests on /settings/ldap/check
|
|
|
|
func (handler *SettingsHandler) handlePutSettingsLDAPCheck(w http.ResponseWriter, r *http.Request) {
|
|
|
|
var req putSettingsLDAPCheckRequest
|
|
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
|
|
httperror.WriteErrorResponse(w, ErrInvalidJSON, http.StatusBadRequest, handler.Logger)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err := govalidator.ValidateStruct(req)
|
|
|
|
if err != nil {
|
|
|
|
httperror.WriteErrorResponse(w, ErrInvalidRequestFormat, http.StatusBadRequest, handler.Logger)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if (req.LDAPSettings.TLSConfig.TLS || req.LDAPSettings.StartTLS) && !req.LDAPSettings.TLSConfig.TLSSkipVerify {
|
2018-01-06 17:53:12 +00:00
|
|
|
caCertPath, _ := handler.FileService.GetPathForTLSFile(filesystem.LDAPStorePath, portainer.TLSFileCA)
|
2017-08-10 08:35:23 +00:00
|
|
|
req.LDAPSettings.TLSConfig.TLSCACertPath = caCertPath
|
|
|
|
}
|
|
|
|
|
|
|
|
err = handler.LDAPService.TestConnectivity(&req.LDAPSettings)
|
|
|
|
if err != nil {
|
|
|
|
httperror.WriteErrorResponse(w, err, http.StatusInternalServerError, handler.Logger)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|