Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 68 additions & 4 deletions agent/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import (
"net"
"net/http"
"os"
"syscall"

"github.com/gin-gonic/gin"

"github.com/1Panel-dev/1Panel/agent/app/repo"
"github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/cron"
"github.com/1Panel-dev/1Panel/agent/global"
"github.com/1Panel-dev/1Panel/agent/i18n"
Expand All @@ -32,6 +32,64 @@ import (
"github.com/1Panel-dev/1Panel/agent/utils/re"
)

const (
masterSocketDir = "/etc/1panel"
masterSocketPath = masterSocketDir + "/agent.sock"
masterSocketDirPerm = 0o700
masterSocketFilePerm = 0o600
masterSocketDirPermMask = 0o077
masterSocketFilePermMask = 0o077
)

func prepareMasterSocketDir(dir string) error {
if err := os.MkdirAll(dir, masterSocketDirPerm); err != nil {
return fmt.Errorf("create master socket dir %s failed: %w", dir, err)
}
if err := os.Chmod(dir, masterSocketDirPerm); err != nil {
return fmt.Errorf("chmod master socket dir %s failed: %w", dir, err)
}
info, err := os.Stat(dir)
if err != nil {
return fmt.Errorf("stat master socket dir %s failed: %w", dir, err)
}
if info.Mode().Perm()&masterSocketDirPermMask != 0 {
return fmt.Errorf("master socket dir %s permission %#o is too permissive", dir, info.Mode().Perm())
}
if stat, ok := info.Sys().(*syscall.Stat_t); ok {
if int(stat.Uid) != os.Geteuid() {
return fmt.Errorf(
"master socket dir %s owner uid %d does not match current process uid %d",
dir, stat.Uid, os.Geteuid(),
)
}
}
return nil
}

func secureMasterSocket(sockPath string) error {
if err := os.Chmod(sockPath, masterSocketFilePerm); err != nil {
return fmt.Errorf("chmod master socket %s failed: %w", sockPath, err)
}
info, err := os.Stat(sockPath)
if err != nil {
return fmt.Errorf("stat master socket %s failed: %w", sockPath, err)
}
if info.Mode().Perm()&masterSocketFilePermMask != 0 {
return fmt.Errorf("master socket %s permission %#o is too permissive", sockPath, info.Mode().Perm())
}
stat, ok := info.Sys().(*syscall.Stat_t)
if !ok {
return nil
}
if int(stat.Uid) != os.Geteuid() {
return fmt.Errorf(
"master socket %s owner uid %d does not match current process uid %d",
sockPath, stat.Uid, os.Geteuid(),
)
}
return nil
}

func Start() {
re.Init()
viper.Init()
Expand Down Expand Up @@ -62,12 +120,18 @@ func Start() {
}

if global.IsMaster {
_ = os.Remove("/etc/1panel/agent.sock")
_ = os.Mkdir("/etc/1panel", constant.DirPerm)
listener, err := net.Listen("unix", "/etc/1panel/agent.sock")
if err := prepareMasterSocketDir(masterSocketDir); err != nil {
panic(err)
}
_ = os.Remove(masterSocketPath)
listener, err := net.Listen("unix", masterSocketPath)
if err != nil {
panic(err)
}
if err := secureMasterSocket(masterSocketPath); err != nil {
_ = listener.Close()
panic(err)
}
business.Init()
_ = server.Serve(listener)
return
Expand Down
13 changes: 5 additions & 8 deletions core/init/router/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,15 @@ import (
"github.com/1Panel-dev/1Panel/core/global"
"github.com/1Panel-dev/1Panel/core/init/proxy"
psessionUtils "github.com/1Panel-dev/1Panel/core/init/session/psession"
"github.com/1Panel-dev/1Panel/core/middleware"
"github.com/1Panel-dev/1Panel/core/utils/xpack"
"github.com/gin-gonic/gin"
)

func Proxy() gin.HandlerFunc {
return func(c *gin.Context) {
reqPath := c.Request.URL.Path
if strings.HasPrefix(reqPath, "/1panel/swagger") || !strings.HasPrefix(c.Request.URL.Path, "/api/v2") {
c.Next()
return
}
if strings.HasPrefix(reqPath, "/api/v2/core") && !strings.HasPrefix(c.Request.URL.Path, "/api/v2/core/xpack") {
if !middleware.ShouldProxyToAgent(reqPath) {
c.Next()
return
}
Expand All @@ -41,19 +38,19 @@ func Proxy() gin.HandlerFunc {

apiReq := c.GetBool("API_AUTH")

if !apiReq && strings.HasPrefix(c.Request.URL.Path, "/api/v2/") && !isLocalAPI(c.Request.URL.Path) && !isPublicFileShareAPI(c.Request.URL.Path) && !checkSession(c) {
if !apiReq && !isLocalAPI(reqPath) && !isPublicFileShareAPI(reqPath) && !checkSession(c) {
data, _ := res.ErrorMsg.ReadFile("html/401.html")
c.Data(401, "text/html; charset=utf-8", data)
c.Abort()
return
}

if c.Request.URL.Path == "/api/v2/hosts/terminal" && (currentNode == "local" || len(currentNode) == 0) {
if reqPath == "/api/v2/hosts/terminal" && (currentNode == "local" || len(currentNode) == 0) {
proxyLocalAgent(c)
return
}

if !strings.HasPrefix(c.Request.URL.Path, "/api/v2/core") && (currentNode == "local" || len(currentNode) == 0) {
if !strings.HasPrefix(reqPath, "/api/v2/core") && (currentNode == "local" || len(currentNode) == 0) {
proxyLocalAgent(c)
return
}
Expand Down
2 changes: 0 additions & 2 deletions core/middleware/demo_handle.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,13 @@ var whiteUrlList = map[string]struct{}{
"/api/v2/dashboard/app/launcher/option": {},
"/api/v2/websites/config": {},
"/api/v2/websites/waf/config": {},
"/api/v2/files/loadfile": {},
"/api/v2/files/size": {},
"/api/v2/runtimes/sync": {},
"/api/v2/toolbox/device/base": {},
"/api/v2/files/user/group": {},
"/api/v2/files/mount": {},
"/api/v2/hosts/ssh/log": {},
"/api/v2/toolbox/clam/base": {},
"/api/v2/hosts/too": {},
"/api/v2/backups/record/size": {},

"/api/v2/core/auth/login": {},
Expand Down
13 changes: 13 additions & 0 deletions core/middleware/helper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package middleware

import "strings"

func ShouldProxyToAgent(reqPath string) bool {
if strings.HasPrefix(reqPath, "/1panel/swagger") || !strings.HasPrefix(reqPath, "/api/v2") {
return false
}
if strings.HasPrefix(reqPath, "/api/v2/core") && !strings.HasPrefix(reqPath, "/api/v2/core/xpack") {
return false
}
return true
}
15 changes: 1 addition & 14 deletions core/middleware/operation.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ func OperationLog() gin.HandlerFunc {
}
}
needAgentResolve := len(operationDic.BeforeFunctions) != 0 && len(currentNode) != 0 && currentNode != "local" && !strings.HasPrefix(record.Path, "/core")
allowCoreFallback := strings.HasPrefix(record.Path, "/core/xpack") || !willProxy(c.Request.URL.Path, currentNode) || len(currentNode) == 0 || currentNode == "local"
allowCoreFallback := strings.HasPrefix(record.Path, "/core/xpack") || !ShouldProxyToAgent(c.Request.URL.Path) || len(currentNode) == 0 || currentNode == "local"
if needAgentResolve {
c.Request.Header.Set(headerNeedOperationResolve, "1")
defer func() {
Expand Down Expand Up @@ -403,16 +403,3 @@ func hasAllResolvedData(values map[string]interface{}, beforeFunctions []functio
}
return true
}

func willProxy(reqPath, currentNode string) bool {
if strings.HasPrefix(reqPath, "/1panel/swagger") || !strings.HasPrefix(reqPath, "/api/v2") {
return false
}
if strings.HasPrefix(reqPath, "/api/v2/core") && !strings.HasPrefix(reqPath, "/api/v2/core/xpack") {
return false
}
if !strings.HasPrefix(reqPath, "/api/v2/core") && (currentNode == "local" || len(currentNode) == 0) {
return true
}
return true
}
22 changes: 12 additions & 10 deletions core/router/ro_setting.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,18 @@ import (
type SettingRouter struct{}

func (s *SettingRouter) InitRouter(Router *gin.RouterGroup) {
router := Router.Group("settings").
baseApi := v2.ApiGroupApp.BaseApi

authRouter := Router.Group("settings").
Use(middleware.SessionAuth())
{
authRouter.POST("/search/base", baseApi.GetSettingBaseInfo)
}

settingRouter := Router.Group("settings").
Use(middleware.SessionAuth()).
Use(middleware.PasswordExpired())

noAuthRouter := Router.Group("settings")
baseApi := v2.ApiGroupApp.BaseApi
{
router.POST("/search/base", baseApi.GetSettingBaseInfo)

settingRouter.POST("/search", baseApi.GetSettingInfo)
settingRouter.POST("/terminal/search", baseApi.GetTerminalSettingInfo)
settingRouter.GET("/search/available", baseApi.GetSystemAvailable)
Expand All @@ -38,13 +39,14 @@ func (s *SettingRouter) InitRouter(Router *gin.RouterGroup) {
settingRouter.POST("/upgrade/notes", baseApi.GetNotesByVersion)
settingRouter.GET("/upgrade/releases", baseApi.LoadRelease)
settingRouter.GET("/upgrade", baseApi.GetUpgradeInfo)

noAuthRouter.POST("/ssl/reload", baseApi.ReloadSSL)

settingRouter.POST("/apps/store/update", baseApi.UpdateAppstoreConfig)
settingRouter.GET("/apps/store/config", baseApi.GetAppstoreConfig)

settingRouter.GET("/memo", baseApi.GetMemo)
settingRouter.POST("/memo", baseApi.UpdateMemo)
}

internalRouter := Router.Group("settings")
{
internalRouter.POST("/ssl/reload", baseApi.ReloadSSL)
}
}
10 changes: 2 additions & 8 deletions frontend/src/store/modules/global.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import piniaPersistConfig from '@/config/pinia-persist';
import { GlobalState } from '../interface';
import { DeviceType } from '@/enums/app';
import i18n, { setActiveLocale } from '@/lang';
import { toManageCode } from '@/utils/permission-codes';

const CN_DOCS_URL = 'https://1panel.cn/docs/v2';
const INTL_DOCS_URL = 'https://docs.1panel.pro/v2';
Expand Down Expand Up @@ -130,7 +131,7 @@ const GlobalStore = defineStore({
if (this.permissions.includes(normalizedPermission)) {
return true;
}
const managePermission = getManagePermission(normalizedPermission);
const managePermission = toManageCode(normalizedPermission);
return managePermission ? this.permissions.includes(managePermission) : false;
},
async updateLanguage(language: string) {
Expand All @@ -149,10 +150,3 @@ const GlobalStore = defineStore({
});

export default GlobalStore;

function getManagePermission(permission: string) {
if (permission.endsWith('_view')) {
return permission.replace(/_view$/, '_manage');
}
return '';
}
13 changes: 13 additions & 0 deletions frontend/src/utils/permission-codes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export const toManageCode = (permission: string): string => {
if (!permission) {
return '';
}
return permission.endsWith('_view') ? permission.replace(/_view$/, '_manage') : '';
};

export const normalizeToManageCode = (permission: string): string => {
if (!permission) {
return '';
}
return toManageCode(permission) || permission;
};
8 changes: 2 additions & 6 deletions frontend/src/utils/permission.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import router from '@/routers';
import { GlobalStore } from '@/store';
import { normalizeToManageCode } from '@/utils/permission-codes';

export type PermissionBindingValue = string | string[] | undefined;
export type PermissionMode = 'manage' | 'view';
Expand Down Expand Up @@ -27,12 +28,7 @@ const getRoutePermission = (): PermissionBindingValue => {
return '';
};

export const toManagePermission = (permission: string) => {
if (!permission) {
return '';
}
return permission.endsWith('_view') ? permission.replace(/_view$/, '_manage') : permission;
};
export const toManagePermission = normalizeToManageCode;

export const toPermissionList = (value: PermissionBindingValue) => {
if (Array.isArray(value)) {
Expand Down
Loading