only-office: bar every account but the converter from the state root (issue 1843)
lib (bind-mounted into the container at /var/lib/onlyoffice) was 0711 so nginx inside the container could reach App_Data/cache, and the module root above it stayed 0711 too, so any account on the machine could walk through the root into lib's 0755 directories and 0644 files to read converted documents. The container never passes through the root — only the converter process does, to read jwt.secret and broker-converter.secret — so the root is now 0710, owned by the converter account: only that account and root pass through it. lib stays 0711 (1837/AC3).
This commit is contained in:
@@ -125,3 +125,55 @@ func TestLibDirectoryLetsNginxThrough(t *testing.T) {
|
||||
}
|
||||
t.Fatal("manifest declares no lib directory")
|
||||
}
|
||||
|
||||
// 1843/AC1 (unit: manifest check)
|
||||
// Given the catalogue, when only-office's manifest is read, then its state directory (the module
|
||||
// root, bind-mounted nowhere, so the container never passes through it) is mode 0710 and belongs
|
||||
// to the converter account — the only host process that reaches through the root to read
|
||||
// ${dir:state}/jwt.secret and broker-converter.secret — so no other account on the machine can
|
||||
// pass through it to the converted documents under lib (which stays 0711, 1837/AC3).
|
||||
func TestStateDirectoryBarsOtherAccounts(t *testing.T) {
|
||||
raw, err := os.ReadFile("module.json")
|
||||
if err != nil {
|
||||
t.Fatalf("reading module.json: %v", err)
|
||||
}
|
||||
var m struct {
|
||||
Resources []struct {
|
||||
ID string `json:"id"`
|
||||
Type string `json:"type"`
|
||||
Mode string `json:"mode"`
|
||||
Owner string `json:"owner"`
|
||||
Name string `json:"name"`
|
||||
} `json:"resources"`
|
||||
}
|
||||
if err := json.Unmarshal(raw, &m); err != nil {
|
||||
t.Fatalf("parsing module.json: %v", err)
|
||||
}
|
||||
|
||||
var converterAccount string
|
||||
for _, r := range m.Resources {
|
||||
if r.Type == "user" {
|
||||
converterAccount = r.Name
|
||||
}
|
||||
}
|
||||
if converterAccount == "" {
|
||||
t.Fatal("manifest declares no user resource for the converter account")
|
||||
}
|
||||
|
||||
var sawState bool
|
||||
for _, r := range m.Resources {
|
||||
if r.ID == "state" && r.Type == "directory" {
|
||||
sawState = true
|
||||
if r.Mode != "0710" {
|
||||
t.Errorf("state directory mode = %q, want 0710", r.Mode)
|
||||
}
|
||||
if r.Owner != converterAccount {
|
||||
t.Errorf("state directory owner = %q, want %q, the converter account (whose own group "+
|
||||
"the mode's group bit then names)", r.Owner, converterAccount)
|
||||
}
|
||||
}
|
||||
}
|
||||
if !sawState {
|
||||
t.Fatal("manifest declares no state directory")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,7 +144,8 @@
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0711",
|
||||
"mode": "0710",
|
||||
"owner": "only-office-converter",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user