Hooks que rodam sem erro e ainda assim relatam um arquivo ausente costumam olhar no lugar errado, não falhar na sua tarefa. Caminhos relativos em um script são resolvidos contra o diretório de trabalho do processo, e um serviço começa com um diretório de trabalho que você não escolheu. O arquivo ao lado do script e o arquivo que o processo abre só são a mesma coisa quando algo os ancora. Essa lacuna explica boa parte das falhas de hook que são lidas por engano como problemas de permissão.

Verifique o caminho antes das permissões, porque um erro de permissão no arquivo errado continua sendo o arquivo errado.

Um caminho relativo é resolvido contra o processo, não contra o arquivo

Quando um script chama open("policy.json"), o kernel resolve o nome contra o diretório de trabalho atual do processo. Nada da localização do próprio script participa dessa busca. OpenVPN inicia hooks a partir de um diretório que ele mesmo escolhe, e a opção cd pode alterá-lo, então um script testado à mão na própria pasta se comporta diferente quando o daemon o executa. O teste manual passa, a execução do serviço falha, e a linha de log menciona apenas o nome ausente.

O Python expõe a localização do script como __file__, e é isso que torna a ancoragem possível. Path(__file__).resolve().parent / "policy.json" constrói um caminho a partir do arquivo em vez do processo. Essa única linha remove a dependência do diretório de trabalho sem mudar nada nos privilégios.

Ancore o caminho de propósito e depois verifique o que resolve faz

resolve() segue links simbólicos, então uma instalação que liga o hook no lugar ancora no destino do link, não no diretório que contém o link. Isso costuma ser o desejado para uma implantação versionada, e é errado para um arranjo que espera dados ao lado do link simbólico. Decida o que a implantação quer dizer e escreva o código de acordo, em vez de descobrir a diferença em produção. Path(__file__).parent sem resolve() mantém o diretório próprio do link.

Se os dados pertencem à instância e não ao programa, pegue um caminho absoluto da configuração. Codificar uma localização fixa prende o hook a um único arranjo de host.

Percorra quatro fronteiras na ordem

Comece pelo diretório de trabalho: compare o WorkingDirectory, a opção cd do OpenVPN e qualquer envoltório que troque de diretório antes do exec. Depois confirme a localização resolvida, porque um arquivo de nome semelhante em outra implantação pode responder à busca e esconder o erro. Em seguida vem a visão do sistema de arquivos: um chroot ou um espaço de nomes de montagem do serviço podem simplesmente tornar ausente um caminho absoluto do host. Por último, a identidade de acesso, que é uma questão separada da visibilidade.

ProtectHome e PrivateTmp escondem localizações diferentes, e nenhum dos dois aparece numa listagem de diretório tirada do host. Um caminho que existe para root num shell pode ser invisível dentro do espaço de nomes da unidade, e é por isso que testar o mesmo comando fora do serviço prova tão pouco.

Corrija a busca sem ampliar o serviço

Ancorar o caminho resolve apenas a primeira fronteira. Não expõe um diretório que o serviço esconde nem concede a uma conta sem privilégios acesso a um arquivo só para root. Elevar script-security muda quais scripts o OpenVPN executará; não tem efeito sobre onde um nome relativo é resolvido. Mudar o diretório de trabalho de todo o serviço é mais amplo que o problema, porque qualquer outro caminho relativo de certificado, log ou auxiliar se desloca junto.

Prefira a correção estreita: um caminho determinístico no script, um valor de configuração explícito para os dados da instância e uma propriedade de arquivos que corresponda à conta com que o hook realmente roda.

Registre evidências que nomeiem a fronteira

Um relatório de falha útil contém três coisas: o caminho exato que o hook tentou, o ambiente que o produziu e qual fronteira recusou. Imprima o caminho resolvido e a exceção sem despejar o conteúdo do arquivo. Essa tríade separa uma ancoragem errada de uma montagem escondida e de uma negação de permissão, que são três correções diferentes.

A afirmação de que root pode ler o arquivo de um terminal responde a uma dessas perguntas e a nenhuma das outras. Teste, em vez disso, a partir do próprio contexto do serviço.

Artigos relacionados