Compare commits
1 Commits
dependabot
...
server-aut
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0717578b06 |
@@ -175,7 +175,7 @@ func _main(ctx context.Context, buildInfo models.BuildInformation,
|
|||||||
Version: buildInfo.Version,
|
Version: buildInfo.Version,
|
||||||
Commit: buildInfo.Commit,
|
Commit: buildInfo.Commit,
|
||||||
Created: buildInfo.Created,
|
Created: buildInfo.Created,
|
||||||
Announcement: "All control server routes will become private by default after the v3.41.0 release",
|
Announcement: "All control server routes are now private by default",
|
||||||
AnnounceExp: announcementExp,
|
AnnounceExp: announcementExp,
|
||||||
// Sponsor information
|
// Sponsor information
|
||||||
PaypalUser: "qmcgaw",
|
PaypalUser: "qmcgaw",
|
||||||
|
|||||||
@@ -18,37 +18,15 @@ func New(settings Settings, debugLogger DebugLogger) (
|
|||||||
return &authHandler{
|
return &authHandler{
|
||||||
childHandler: handler,
|
childHandler: handler,
|
||||||
routeToRoles: routeToRoles,
|
routeToRoles: routeToRoles,
|
||||||
unprotectedRoutes: map[string]struct{}{
|
logger: debugLogger,
|
||||||
http.MethodGet + " /openvpn/actions/restart": {},
|
|
||||||
http.MethodGet + " /openvpn/portforwarded": {},
|
|
||||||
http.MethodGet + " /unbound/actions/restart": {},
|
|
||||||
http.MethodGet + " /updater/restart": {},
|
|
||||||
http.MethodGet + " /v1/version": {},
|
|
||||||
http.MethodGet + " /v1/vpn/status": {},
|
|
||||||
http.MethodPut + " /v1/vpn/status": {},
|
|
||||||
// GET /v1/vpn/settings is protected by default
|
|
||||||
// PUT /v1/vpn/settings is protected by default
|
|
||||||
http.MethodGet + " /v1/openvpn/status": {},
|
|
||||||
http.MethodPut + " /v1/openvpn/status": {},
|
|
||||||
http.MethodGet + " /v1/openvpn/portforwarded": {},
|
|
||||||
// GET /v1/openvpn/settings is protected by default
|
|
||||||
http.MethodGet + " /v1/dns/status": {},
|
|
||||||
http.MethodPut + " /v1/dns/status": {},
|
|
||||||
http.MethodGet + " /v1/updater/status": {},
|
|
||||||
http.MethodPut + " /v1/updater/status": {},
|
|
||||||
http.MethodGet + " /v1/publicip/ip": {},
|
|
||||||
http.MethodGet + " /v1/portforward": {},
|
|
||||||
},
|
|
||||||
logger: debugLogger,
|
|
||||||
}
|
}
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type authHandler struct {
|
type authHandler struct {
|
||||||
childHandler http.Handler
|
childHandler http.Handler
|
||||||
routeToRoles map[string][]internalRole
|
routeToRoles map[string][]internalRole
|
||||||
unprotectedRoutes map[string]struct{} // TODO v3.41.0 remove
|
logger DebugLogger
|
||||||
logger DebugLogger
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *authHandler) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
|
func (h *authHandler) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
|
||||||
@@ -66,8 +44,6 @@ func (h *authHandler) ServeHTTP(writer http.ResponseWriter, request *http.Reques
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
h.warnIfUnprotectedByDefault(role, route) // TODO v3.41.0 remove
|
|
||||||
|
|
||||||
h.logger.Debugf("access to route %s authorized for role %s", route, role.name)
|
h.logger.Debugf("access to route %s authorized for role %s", route, role.name)
|
||||||
h.childHandler.ServeHTTP(writer, request)
|
h.childHandler.ServeHTTP(writer, request)
|
||||||
return
|
return
|
||||||
@@ -88,26 +64,3 @@ func (h *authHandler) ServeHTTP(writer http.ResponseWriter, request *http.Reques
|
|||||||
route, andStrings(allRoleNames))
|
route, andStrings(allRoleNames))
|
||||||
http.Error(writer, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
|
http.Error(writer, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *authHandler) warnIfUnprotectedByDefault(role internalRole, route string) {
|
|
||||||
// TODO v3.41.0 remove
|
|
||||||
if role.name != "public" {
|
|
||||||
// custom role name, allow none authentication to be specified
|
|
||||||
return
|
|
||||||
}
|
|
||||||
_, isNoneChecker := role.checker.(*noneMethod)
|
|
||||||
if !isNoneChecker {
|
|
||||||
// not the none authentication method
|
|
||||||
return
|
|
||||||
}
|
|
||||||
_, isUnprotectedByDefault := h.unprotectedRoutes[route]
|
|
||||||
if !isUnprotectedByDefault {
|
|
||||||
// route is not unprotected by default, so this is a user decision
|
|
||||||
return
|
|
||||||
}
|
|
||||||
h.logger.Warnf("route %s is unprotected by default, "+
|
|
||||||
"please set up authentication following the documentation at "+
|
|
||||||
"https://github.com/qdm12/gluetun-wiki/blob/main/setup/advanced/control-server.md#authentication "+
|
|
||||||
"since this will become no longer publicly accessible after release v3.40.",
|
|
||||||
route)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -40,27 +40,6 @@ func Test_authHandler_ServeHTTP(t *testing.T) {
|
|||||||
statusCode: http.StatusUnauthorized,
|
statusCode: http.StatusUnauthorized,
|
||||||
responseBody: "Unauthorized\n",
|
responseBody: "Unauthorized\n",
|
||||||
},
|
},
|
||||||
"authorized_unprotected_by_default": {
|
|
||||||
settings: Settings{
|
|
||||||
Roles: []Role{
|
|
||||||
{Name: "public", Auth: AuthNone, Routes: []string{"GET /v1/vpn/status"}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
makeLogger: func(ctrl *gomock.Controller) *MockDebugLogger {
|
|
||||||
logger := NewMockDebugLogger(ctrl)
|
|
||||||
logger.EXPECT().Warnf("route %s is unprotected by default, "+
|
|
||||||
"please set up authentication following the documentation at "+
|
|
||||||
"https://github.com/qdm12/gluetun-wiki/blob/main/setup/advanced/control-server.md#authentication "+
|
|
||||||
"since this will become no longer publicly accessible after release v3.40.",
|
|
||||||
"GET /v1/vpn/status")
|
|
||||||
logger.EXPECT().Debugf("access to route %s authorized for role %s",
|
|
||||||
"GET /v1/vpn/status", "public")
|
|
||||||
return logger
|
|
||||||
},
|
|
||||||
requestMethod: http.MethodGet,
|
|
||||||
requestPath: "/v1/vpn/status",
|
|
||||||
statusCode: http.StatusOK,
|
|
||||||
},
|
|
||||||
"authorized_none": {
|
"authorized_none": {
|
||||||
settings: Settings{
|
settings: Settings{
|
||||||
Roles: []Role{
|
Roles: []Role{
|
||||||
|
|||||||
@@ -63,31 +63,6 @@ func (s *Settings) SetDefaultRole(jsonRole string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Settings) SetDefaults() {
|
|
||||||
s.Roles = gosettings.DefaultSlice(s.Roles, []Role{{ // TODO v3.41.0 leave empty
|
|
||||||
Name: "public",
|
|
||||||
Auth: "none",
|
|
||||||
Routes: []string{
|
|
||||||
http.MethodGet + " /openvpn/actions/restart",
|
|
||||||
http.MethodGet + " /unbound/actions/restart",
|
|
||||||
http.MethodGet + " /openvpn/portforwarded",
|
|
||||||
http.MethodGet + " /updater/restart",
|
|
||||||
http.MethodGet + " /v1/version",
|
|
||||||
http.MethodGet + " /v1/vpn/status",
|
|
||||||
http.MethodPut + " /v1/vpn/status",
|
|
||||||
http.MethodGet + " /v1/openvpn/status",
|
|
||||||
http.MethodPut + " /v1/openvpn/status",
|
|
||||||
http.MethodGet + " /v1/openvpn/portforwarded",
|
|
||||||
http.MethodGet + " /v1/dns/status",
|
|
||||||
http.MethodPut + " /v1/dns/status",
|
|
||||||
http.MethodGet + " /v1/updater/status",
|
|
||||||
http.MethodPut + " /v1/updater/status",
|
|
||||||
http.MethodGet + " /v1/publicip/ip",
|
|
||||||
http.MethodGet + " /v1/portforward",
|
|
||||||
},
|
|
||||||
}})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s Settings) Validate() (err error) {
|
func (s Settings) Validate() (err error) {
|
||||||
for i, role := range s.Roles {
|
for i, role := range s.Roles {
|
||||||
err = role.Validate()
|
err = role.Validate()
|
||||||
|
|||||||
@@ -60,7 +60,6 @@ func setupAuthMiddleware(authPath, jsonDefaultRole string, logger Logger) (
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return auth.Settings{}, fmt.Errorf("setting default role: %w", err)
|
return auth.Settings{}, fmt.Errorf("setting default role: %w", err)
|
||||||
}
|
}
|
||||||
authSettings.SetDefaults()
|
|
||||||
err = authSettings.Validate()
|
err = authSettings.Validate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return auth.Settings{}, fmt.Errorf("validating auth settings: %w", err)
|
return auth.Settings{}, fmt.Errorf("validating auth settings: %w", err)
|
||||||
|
|||||||
Reference in New Issue
Block a user