Ir para o conteúdo

Blogue ·

Sem privilégios é uma medição, não uma definição

Restaurar a cópia de um contentor começa por ler a configuração dentro do arquivo, porque o valor seguro de um sinalizador não pode ser enviado às cegas.

Por Provibr

Restaurar um contentor no Proxmox é a mesma chamada de API que criar um. Faz-se um POST ao ponto final de contentores de um nó, entrega-se-lhe o arquivo e acrescenta-se o sinalizador que transforma a criação num restauro. O caminho da máquina virtual nem sequer tem esse sinalizador: aí o próprio arquivo é o restauro. Essa simetria é cómoda e esconde uma armadilha, porque um dos campos dessa chamada descreve uma propriedade de segurança que já tem um valor dentro do arquivo.

Enviar o valor seguro pode partir o contentor. Deixar o campo de fora pode meter um contentor privilegiado num parque que, à partida, não devia ter nenhum. A única jogada correta é ler primeiro o arquivo e depois agir sobre o que ele diz.

Dois pontos finais que se parecem

O caminho da máquina virtual e o do contentor divergem em mais sítios do que o nome sugere:

Máquina virtualContentor
Ponto finalPOST /nodes/{node}/qemuPOST /nodes/{node}/lxc
O arquivoarchive=<volid>ostemplate=<volid> mais restore=1
O nomename=hostname=
O armazenamento de destino tem de aceitarimagesrootdir
Tipo de tarefa no identificador da tarefaqmrestorevzrestore

Duas dessas linhas são fáceis de errar de uma maneira que produz um erro confuso. O Proxmox chama modelo de sistema operativo ao arquivo de um contentor, porque o mesmo parâmetro aceita os dois, e numa máquina virtual a presença de archive é, por si só, o restauro, pelo que não existe sinalizador separado. E images e rootdir são dois tipos de conteúdo diferentes: um armazenamento pode oferecer um sem o outro, pelo que exigir images em todo o lado recusa armazenamento de contentores perfeitamente bom, ao passo que não verificar coisa nenhuma entrega ao cliente uma frase sobre diretórios de contentores que não lhe diz nada.

Qual das duas espécies isto é fica decidido uma só vez. É lido do nome de ficheiro do arquivo no momento em que o arquivo é listado, guardado com o ponto de restauro e enviado juntamente com a instrução; o agente escolhe o seu ponto final a partir dessa palavra e não tem caminho de recurso. Tem mesmo de ser por esta ordem, porque um 404 do Proxmox não distingue um convidado da outra espécie de um convidado que já não existe. Tentar o outro ponto final depois de um 404 deixaria endereçar como contentor uma máquina virtual eliminada e, num cluster onde esse número tenha entretanto sido reemitido, é o convidado errado que é tocado.

Um dos sinalizadores nunca é enviado de todo, e chama-se force. Este é o restauro aditivo: aparece uma máquina ao lado da original e a original continua a correr. force é o sinalizador com que o Proxmox sobrescreve um convidado existente, existe nos dois pontos finais e pertence à outra espécie de restauro, que tem mensagem própria, permissão própria e uma confirmação que é preciso escrever. Deixá-lo permanentemente fora deste caminho de código sai mais barato do que ter de se lembrar de não o definir.

Um dos sinalizadores é sempre enviado, e chama-se unique. Sem ele, o convidado restaurado herda os endereços de hardware das placas de rede do original, e duas máquinas a responder ao mesmo endereço são uma interrupção na máquina em que se estava a ter o cuidado de não tocar.

Três recusas antes de alguma coisa ser escrita

Cada verificação prévia existe porque a alternativa é uma citação do Proxmox sobre a qual um cliente não consegue agir. O arquivo tem de continuar lá, porque a plataforma escolhe-o a partir de um índice que é, por construção, uma observação do passado. O número de destino tem de estar livre, e livre tem de significar livre no hipervisor e não livre na nossa própria administração: a plataforma atribui dentro do intervalo que gere, pelo que um convidado que alguém criou à mão é inteiramente real e está inteiramente ausente de todos os registos que guardamos. E o armazenamento de destino tem de aceitar o tipo de conteúdo certo.

Para um contentor há uma quarta, e é dela que este artigo trata.

Três coisas que se podem fazer com um arquivo privilegiado, e duas estão erradas em silêncio

Os contentores sem privilégios são a predefinição segura, e a plataforma não tem maneira nenhuma de exprimir outra coisa. Portanto, quando um arquivo se revela conter um contentor privilegiado, o agente tem exatamente três opções.

A primeira é enviar mesmo assim o sinalizador que marca o contentor como sem privilégios. O Proxmox aplica então um mapeamento de identidade sobre o sistema de ficheiros restaurado; a descrição do próprio parâmetro diz que o campo não deve ser alterado à mão. O restauro tem sucesso, a tarefa comunica que correu bem, e o contentor não funciona.

A segunda é omitir o campo. O Proxmox passa então a tirar o valor do arquivo, e um contentor privilegiado junta-se ao parque: um que partilha o kernel do anfitrião com privilégios de root, que é exatamente aquilo que a política existe para impedir.

A terceira é recusar, com uma frase a dizer o que está no arquivo. É isso que acontece, e acontece antes de alguma coisa ser escrita. Não é enviado pedido nenhum para criar o contentor.

Ler a configuração que está dentro do arquivo

A medição é uma chamada ao ponto final de extração do arquivo. Há três pormenores que vale a pena conhecer.

A resposta é texto e não JSON. É o ficheiro de configuração do contentor, uma chave e um valor por linha, exatamente como está em disco, pelo que precisa de um pequeno analisador próprio ao lado daquele que trata do JSON da API.

E a ausência da chave significa o contrário do que uma ausência costuma significar. O Proxmox escreve a linha que marca o contentor como sem privilégios apenas quando ela é verdadeira. Uma configuração sem ela descreve um contentor privilegiado. Qualquer leitor que trate «não encontrado» como «desconhecido, provavelmente sem problema» deixa passar precisamente o caso para o qual a verificação foi construída, pelo que a comparação é generosa quanto ao que aceita como verdadeiro e recusa tudo o resto.

Se a configuração não puder ser lida de todo, o restauro é recusado também, e a citação do Proxmox viaja de volta com ele. Costuma ser uma mensagem de permissões, porque o ponto final de extração quer direitos de cópia de segurança sobre o convidado e direitos de atribuição sobre o armazenamento das cópias. Falhar para o lado fechado tem aqui um custo real: um token de API a que falte uma permissão não consegue restaurar um contentor, e a razão é uma verificação e não uma limitação. Continua a ser o lado certo para onde falhar, porque a pergunta em aberto por trás dela tem duas respostas silenciosamente erradas.

A mesma leitura responde a uma segunda pergunta

A configuração dentro do arquivo diz também que pontos de montagem fizeram parte dele, e as regras do Proxmox nesse ponto não são as que as pessoas esperam:

O que a configuração dizEstá no arquivo?Porquê
O sistema de ficheiros raizSempreNão tem opção de cópia de segurança nenhuma; o campo não existe no seu esquema
Um volume gerido com a opção de cópia de segurança ligadaSimExplicitamente ativada
Um volume gerido sem elaNãoA opção tem de ser ligada para que um ponto de montagem seja incluído
Um diretório do anfitriãoNãoO conteúdo dos bind mounts não é copiado
Um dispositivo de blocos do anfitriãoNãoO mesmo, para os pontos de montagem de dispositivo

A terceira linha é a perigosa. Num disco de máquina virtual, excluído é a exceção e incluído é a predefinição; num ponto de montagem de contentor é ao contrário. Trocar isso produz uma tabela de cobertura que diz «está na cópia» sobre a configuração mais comum que existe, o que é pior do que não ter tabela nenhuma, porque é uma promessa.

As secções de snapshot da configuração são saltadas. Caso contrário, um contentor com cinco snapshots contribuiria com cinco versões do mesmo sistema de ficheiros raiz, cada uma de um momento arbitrário.

Uma única chamada serve as duas perguntas em vez de duas, porque duas chamadas podiam descrever dois arquivos diferentes. E o veredicto é calculado na plataforma e não pelo agente: o agente comunica as linhas tal como as encontrou, e não existe campo nenhum em que pudesse afirmar cobertura completa, mesmo que quisesse. Demonstravelmente fora da cópia vence não medido, pelo que um contentor com um bind mount e uma linha ilegível fica parcial e não desconhecido, e a linha ilegível mantém a sua própria palavra na tabela.

Existe um sinalizador a dizer se a configuração chegou sequer a ser lida, e não é decoração. Um agente que não a tenha conseguido ler devolve uma lista vazia, e uma lista vazia é indistinguível de um contentor sem pontos de montagem, exceto que o segundo não existe.

Quando ninguém consegue dizer o que aconteceu

Um restauro que começa e depois perde a sua resposta, porque o agente reiniciou ou a ligação caiu, não pode ser adivinhado. Há três fontes de prova: o índice de arquivos, a máquina que era suposto aparecer e o estado da tarefa do Proxmox. Só a terceira consegue estabelecer uma falha; as outras duas só conseguem confirmar um sucesso, porque um arquivo em falta e uma máquina em falta são ambos igualmente compatíveis com um restauro que ainda está a correr.

Esse raciocínio acontece na plataforma. A consulta da tarefa feita pelo agente limita-se a trazer de volta a citação do Proxmox e não tira conclusão própria nenhuma, porque decidir o que as três fontes somadas significam precisa de ter lado a lado a execução e a intenção de que partiu, e só a plataforma tem as duas.

Nada é repetido para sempre. Há um contador com um teto de oito tentativas e, no intervalo predefinido de seis horas, isso dá cerca de dois dias. As tentativas em que a tarefa estava demonstravelmente ainda a correr não contam contra ele, porque uma cópia de segurança grande sobre uma rede lenta tem direito a demorar uma noite. Quando o contador se esgota, a execução passa a desconhecida, e nunca a falhada. Falhada seria uma afirmação que ninguém verificou, e concluída afirmaria um arquivo que ninguém viu.

O que registaríamos

  1. Não enviar um valor para uma propriedade que já existe na entrada. Lê-la e depois, ou confirmá-la, ou recusar.
  2. Descobrir o que significa uma chave ausente antes de escrever o analisador. Aqui significa o valor inseguro, que é o contrário da convenção habitual.
  3. Falhar para o lado fechado quando a medição não está disponível, e dizer em voz alta o que isso custa, porque alguém vai lá bater.
  4. Fazer com que uma leitura responda a todas as perguntas a que consegue responder. Duas chamadas podem descrever dois estados diferentes.
  5. Pôr o juízo onde está o contexto. Um observador que não consegue exprimir um veredicto também não o consegue errar.
  6. Dar a uma repetição esgotada uma palavra terminal própria. Desconhecido é honesto; falhado e concluído são ambos afirmações que ninguém fez.

Para ser claro quanto ao ponto em que isto está: as cópias de segurança de clientes vivem atrás de um sinalizador de lançamento que está desligado por predefinição, pelo que nada disto é comprável hoje. E o limite importante quanto à prova: não foi corrida nenhuma cópia de segurança nem nenhum restauro reais contra um hipervisor a funcionar. O comportamento dos parâmetros descrito acima foi lido da própria fonte e da documentação do Proxmox, e o código foi exercitado contra um servidor substituto que responde aos mesmos pontos finais. A chamada de extração também não foi experimentada contra um arquivo num servidor de cópias de segurança dedicado, apenas contra armazenamento baseado em ficheiros.

Do trabalho de cópias de segurança no Provibr. A razão pela qual um arquivo que ninguém restaurou ainda não é uma cópia de segurança está em uma cópia que nunca foi restaurada não é cópia, o que os diferentes modos de cópia garantem de facto está em o que garantem os modos vzdump do Proxmox, e a razão pela qual reinstalar um contentor é destruir e voltar a construir está em reinstalar um contentor é uma substituição.

Comece com um host e um agente

Crie uma conta, instale o agente com um único comando e ligue o seu primeiro host Proxmox. O período experimental dura 14 dias e não pede quaisquer dados de pagamento.