Skip to content

Commit 6d09ff5

Browse files
committed
feat: add LogDirWhiteList option
1 parent 27f7516 commit 6d09ff5

File tree

10 files changed

+185
-63
lines changed

10 files changed

+185
-63
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ nginx-ui
1111
resources/development/nginx
1212
app/.env
1313
app/.status_hash
14+
casdoor.pub

api/nginx/nginx_log.go

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@ package nginx
22

33
import (
44
"encoding/json"
5+
"fmt"
56
"github.com/0xJacky/Nginx-UI/api"
7+
"github.com/0xJacky/Nginx-UI/internal/cache"
8+
"github.com/0xJacky/Nginx-UI/internal/helper"
69
"github.com/0xJacky/Nginx-UI/internal/logger"
710
"github.com/0xJacky/Nginx-UI/internal/nginx"
11+
"github.com/0xJacky/Nginx-UI/settings"
812
"github.com/gin-gonic/gin"
913
"github.com/gorilla/websocket"
1014
"github.com/hpcloud/tail"
@@ -30,6 +34,7 @@ type controlStruct struct {
3034
type nginxLogPageResp struct {
3135
Content string `json:"content"`
3236
Page int64 `json:"page"`
37+
Error string `json:"error,omitempty"`
3338
}
3439

3540
func GetNginxLogPage(c *gin.Context) {
@@ -46,28 +51,37 @@ func GetNginxLogPage(c *gin.Context) {
4651
logPath, err := getLogPath(&control)
4752

4853
if err != nil {
54+
c.JSON(http.StatusInternalServerError, nginxLogPageResp{
55+
Error: err.Error(),
56+
})
4957
logger.Error(err)
5058
return
5159
}
5260

5361
logFileStat, err := os.Stat(logPath)
5462

5563
if err != nil {
56-
c.JSON(http.StatusOK, nginxLogPageResp{})
64+
c.JSON(http.StatusInternalServerError, nginxLogPageResp{
65+
Error: err.Error(),
66+
})
5767
logger.Error(err)
5868
return
5969
}
6070

6171
if !logFileStat.Mode().IsRegular() {
62-
c.JSON(http.StatusOK, nginxLogPageResp{})
72+
c.JSON(http.StatusInternalServerError, nginxLogPageResp{
73+
Error: "log file is not regular file",
74+
})
6375
logger.Error("log file is not regular file:", logPath)
6476
return
6577
}
6678

6779
f, err := os.Open(logPath)
6880

6981
if err != nil {
70-
c.JSON(http.StatusOK, nginxLogPageResp{})
82+
c.JSON(http.StatusInternalServerError, nginxLogPageResp{
83+
Error: err.Error(),
84+
})
7185
logger.Error(err)
7286
return
7387
}
@@ -90,15 +104,19 @@ func GetNginxLogPage(c *gin.Context) {
90104
// seek
91105
_, err = f.Seek(offset, io.SeekStart)
92106
if err != nil && err != io.EOF {
93-
c.JSON(http.StatusOK, nginxLogPageResp{})
107+
c.JSON(http.StatusInternalServerError, nginxLogPageResp{
108+
Error: err.Error(),
109+
})
94110
logger.Error(err)
95111
return
96112
}
97113

98114
n, err := f.Read(buf)
99115

100116
if err != nil && err != io.EOF {
101-
c.JSON(http.StatusOK, nginxLogPageResp{})
117+
c.JSON(http.StatusInternalServerError, nginxLogPageResp{
118+
Error: err.Error(),
119+
})
102120
logger.Error(err)
103121
return
104122
}
@@ -109,7 +127,30 @@ func GetNginxLogPage(c *gin.Context) {
109127
})
110128
}
111129

130+
// isLogPathUnderWhiteList checks if the log path is under one of the paths in LogDirWhiteList
131+
func isLogPathUnderWhiteList(path string) bool {
132+
cacheKey := fmt.Sprintf("isLogPathUnderWhiteList:%s", path)
133+
res, ok := cache.Get(cacheKey)
134+
// no cache, check it
135+
if !ok {
136+
for _, whitePath := range settings.NginxSettings.LogDirWhiteList {
137+
if helper.IsUnderDirectory(path, whitePath) {
138+
cache.Set(cacheKey, true, 0)
139+
return true
140+
}
141+
}
142+
return false
143+
}
144+
return res.(bool)
145+
}
146+
112147
func getLogPath(control *controlStruct) (logPath string, err error) {
148+
if len(settings.NginxSettings.LogDirWhiteList) == 0 {
149+
err = errors.New("The settings.NginxSettings.LogDirWhiteList has not been configured. " +
150+
"For security reasons, please configure a whitelist of log directories. " +
151+
"Please visit https://nginxui.com/guide/config-nginx.html for more information.")
152+
return
153+
}
113154
switch control.Type {
114155
case "site":
115156
var config *nginx.NgxConfig
@@ -172,6 +213,11 @@ func getLogPath(control *controlStruct) (logPath string, err error) {
172213
logPath = path
173214
}
174215

216+
// check if logPath is under one of the paths in LogDirWhiteList
217+
if !isLogPathUnderWhiteList(logPath) {
218+
err = errors.New("The log path is not under the paths in LogDirWhiteList.")
219+
return "", err
220+
}
175221
return
176222
}
177223

app/src/views/nginx_log/NginxLog.vue

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ function init() {
5959
nginx_log.page(0, control).then(r => {
6060
page.value = r.page - 1
6161
addLog(r.content)
62+
openWs()
63+
}).catch(e => {
64+
addLog(e.error)
6265
})
6366
}
6467
@@ -68,11 +71,10 @@ function clearLog() {
6871
6972
onMounted(() => {
7073
init()
71-
openWs()
7274
})
7375
7476
onUnmounted(() => {
75-
websocket.close()
77+
websocket?.close()
7678
})
7779
7880
watch(auto_refresh, value => {

casdoor.pub

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIE3TCCAsWgAwIBAgIDAeJAMA0GCSqGSIb3DQEBCwUAMCgxDjAMBgNVBAoTBWFk
3+
bWluMRYwFAYDVQQDEw1jZXJ0LWJ1aWx0LWluMB4XDTI0MDcyOTAzMDUzM1oXDTQ0
4+
MDcyOTAzMDUzM1owKDEOMAwGA1UEChMFYWRtaW4xFjAUBgNVBAMTDWNlcnQtYnVp
5+
bHQtaW4wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDh0c2zvM21NDNi
6+
xZmSQVPOtckiH/K80mHQ99e+xzdGrZugaw00tyTOMVRot+Bv1cggcJXmFcVaa9Da
7+
siIcIQ6jT3w7mINsrErYu4nz9tELd4BZUM6tytN+khVqo73p/NbRsnmX8ykMyrgx
8+
YCBknNoSxh7glLSmKcj4uQ12dYakRPr0QNnDwU7fpPfB7N4O88yXWpbqWaABwqBx
9+
S6+tYUp9Wx74mH8c917w5xXx8EI5eC+dJOAeVXrbzqD7OdC+uo8m7f06HAX1vRE/
10+
MQS0BDx8tDGtqOvdJbVxdnS6MQ2E3vmuusFseDcKVgqTF/7b76y5uNyBBux5zfpt
11+
G1O3bquMlQ8mSedK8BBcbI79gXYJRWazMBXvAdacaV93dF1s0EEjYXiBManAci2d
12+
lH8zzs4TNpE0t3adYiPbGPW1F6Q+HaV52MDVpFwG9Ld0kJmKhkvoWiSXl58Db3VN
13+
Ef8Jjo2xF+5o9685CQ2o9L0RalcHxMxy1+6wdKMSp7PReYpIiEgmkAhUsKePOVmr
14+
JwL46/4EulcXrh+ASjobmknHzdBQEK+MHapb/XWewX4mzq777gPmP8RdILTHsc1m
15+
/hbR8uW9iTfo9LQFvXwnIPVfX0wzFXSZzSg/zLb2tN5D7VlDenUAdCDT1zNOfz5m
16+
9vLYwfo5GzXIkp2py0G40vrZlv7C9wIDAQABoxAwDjAMBgNVHRMBAf8EAjAAMA0G
17+
CSqGSIb3DQEBCwUAA4ICAQBp1Bx+mShpumQiVb2hv0amSzAKADyYIX3Xcef68rPu
18+
Eb+7HSCmQf4yyI9eU1TyvQCLbjum3U3OhDWwAiRvxOwj0oO/Q+dOUEZxTjbL9UF3
19+
4LIrUUBMRhRgy3wK73qy3o8hAcRtQyexUW7eoFS+7L++6XQOvMkYAtLO0DQCHeKG
20+
loiQa5RuWbzQDdP7810DLvNF8IMA8t9KKaKGybYze9WTzRUMTDbXby8pVs8DG7JI
21+
zIW6neEmtsVbxufk/nthG1b83/yZxe0StL42xI7f4xgguhkfd68E4lpf/gp91EAM
22+
K6MbTmCqkB68c0wOSXpWYkte7EvXTTmMSKf6FnMgOtqdxqYYMknLk4ZdI7tMqS31
23+
rpb9XxjBgXFbB18oOSDbW64KPMjE7vuOx+o32BTHKsUWxOiDc8+0ELrbhG2Bm1Gj
24+
CYkx9bq5iTLDwtZZlPoA8O/T0TJzBTtC/tlEdpHSkkLoEaWsx0nT9ipRWck1Kj59
25+
NGJkArbrpq9Ee8tWJKqTN/pv0X8r+MxowIY2dKvwweokXb7R6k9nfXyGw8ji22Hv
26+
H4iibv9FEyVFQ16HPR6fIKg9yE9u0223UhJZEwohA4DylCxpmI/YSXbUmzQJwjBP
27+
27qvT4Y07xsdNqIbkwhb5yEQB5huivITD+SBwI5NwDfUeY6eF/BEHpRq+Uy3itx0
28+
SA==
29+
-----END CERTIFICATE-----

docs/guide/config-nginx.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,20 @@ In Nginx UI v2, we parse the output of the `nginx -V` command to get the default
3333
If you need to set a different path, you can use this option.
3434
:::
3535

36+
### LogDirWhiteList
37+
38+
- Type: `[]string`
39+
- Version:`>= v2.0.0-beta.36`
40+
- Example: `/var/log/nginx,/var/log/sites`
41+
42+
This option is used to set the whitelist of directories for the Nginx logs viewer in Nginx UI.
43+
44+
::: warning Warning
45+
For security reasons, you must specify the directories where the logs are stored.
46+
47+
Only logs within these directories can be viewed online.
48+
:::
49+
3650
## Service Monitoring and Control
3751

3852
In this section, we will introduce configuration options in Nginx UI for monitoring and controlling Nginx services.

docs/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@
77
"docs:preview": "vitepress preview"
88
},
99
"dependencies": {
10-
"vitepress": "^1.3.4",
10+
"vitepress": "^1.4.0",
1111
"vue": "^3.5.11"
1212
},
1313
"devDependencies": {
14-
"@types/node": "^22.7.4",
14+
"@types/node": "^22.7.5",
1515
"less": "^4.2.0"
1616
},
1717
"license": "AGPL-3.0",

0 commit comments

Comments
 (0)