KB-PLUGIN-018: ZIP via python zipfile precisa de permissões explícitas
Entradas criadas com ZipInfo() nascem com external_attr=0; o unzip cria os diretórios como drw------- e o webserver não consegue atravessá-los — plugin some da lista ou dá 'Unable to load plugin information' (Plugin.php linha 882). Inclui forma correta, sintoma do Jan 1 1980, validação do ZIP e comando de correção no servidor. Diagnosticado no build VIP do butterfly. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
5c3cff2f81
commit
d49d5bbaa6
2 changed files with 52 additions and 1 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"last_updated": "2026-07-15",
|
"last_updated": "2026-07-31",
|
||||||
"records": [
|
"records": [
|
||||||
{
|
{
|
||||||
"id": "KB-INFRA-001",
|
"id": "KB-INFRA-001",
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,57 @@ zip -r mcprotocol-1.0.3.zip mcprotocol/ \
|
||||||
|
|
||||||
**Não** fazer `cd plugin && zip -r ...zip .` — esse padrão produz ZIP sem wrapper e era o bug histórico do script.
|
**Não** fazer `cd plugin && zip -r ...zip .` — esse padrão produz ZIP sem wrapper e era o bug histórico do script.
|
||||||
|
|
||||||
|
## Gotcha — ZIP gerado com `python zipfile` precisa de permissões explícitas
|
||||||
|
|
||||||
|
Quando o `zip` CLI não está disponível e o pacote é montado com `zipfile`
|
||||||
|
(cenário comum neste ambiente, ver [[redmine-plugin-project]]), as entradas
|
||||||
|
criadas com `zipfile.ZipInfo(nome)` nascem com `external_attr = 0` — sem bits
|
||||||
|
de permissão e sem a flag MS-DOS de diretório. O `unzip` então cria as pastas
|
||||||
|
como **`drw-------`** (sem bit de execução), e o resultado no servidor é:
|
||||||
|
|
||||||
|
- o usuário do webserver **não consegue atravessar** o diretório do plugin;
|
||||||
|
- `Plugin::isLoadable()` não enxerga o `setup.php`;
|
||||||
|
- o plugin **some da lista** sem nenhum erro, ou aparece
|
||||||
|
`Unable to load plugin "<key>" information. at Plugin.php line 882`
|
||||||
|
quando já existe registro dele no banco.
|
||||||
|
|
||||||
|
Diagnosticado em 2026-07-31 no build VIP do butterfly instalado no HML de um
|
||||||
|
cliente (`drw------- root root` na pasta do plugin).
|
||||||
|
|
||||||
|
### Forma correta
|
||||||
|
|
||||||
|
```python
|
||||||
|
DIR_ATTR = (0o40755 << 16) | 0x10 # drwxr-xr-x + flag de diretório
|
||||||
|
FILE_ATTR = (0o100644 << 16) # -rw-r--r--
|
||||||
|
|
||||||
|
zi = zipfile.ZipInfo(arcname, date_time=(2026, 7, 31, 12, 0, 0))
|
||||||
|
zi.external_attr = DIR_ATTR # entradas de diretório
|
||||||
|
z.writestr(zi, '')
|
||||||
|
|
||||||
|
zi = zipfile.ZipInfo.from_file(src, arcname)
|
||||||
|
zi.external_attr = FILE_ATTR # arquivos
|
||||||
|
zi.compress_type = zipfile.ZIP_DEFLATED
|
||||||
|
```
|
||||||
|
|
||||||
|
Sintoma acessório que denuncia o problema: data **`Jan 1 1980`** no diretório
|
||||||
|
extraído (timestamp default de `ZipInfo` sem `date_time`).
|
||||||
|
|
||||||
|
### Validação obrigatória do ZIP
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# extrair em pasta temporária e conferir os modos
|
||||||
|
unzip -q <plugin>-<ver>.zip -d /tmp/ziptest && ls -ld /tmp/ziptest/<plugin>
|
||||||
|
# esperado: drwxr-xr-x (NUNCA drw-------)
|
||||||
|
```
|
||||||
|
|
||||||
|
Correção no servidor quando o ZIP defeituoso já foi extraído:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
chown -R www-data:www-data <glpi>/plugins/<key>
|
||||||
|
find <glpi>/plugins/<key> -type d -exec chmod 755 {} \;
|
||||||
|
find <glpi>/plugins/<key> -type f -exec chmod 644 {} \;
|
||||||
|
```
|
||||||
|
|
||||||
## .gitignore padrão do plugin
|
## .gitignore padrão do plugin
|
||||||
|
|
||||||
Para que o ZIP não inclua arquivos sensíveis ou de teste, garantir `.gitignore` na raiz do plugin:
|
Para que o ZIP não inclua arquivos sensíveis ou de teste, garantir `.gitignore` na raiz do plugin:
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue