SDK da Proteção de Informações da Microsoft: conceitos do manipulador de arquivos

No SDK do arquivo da PIM, o mip::FileHandler expõe todas as várias operações que podem ser usadas para ler e gravar rótulos, ou proteção, em um conjunto de tipos de arquivo para os quais o suporte é interno.

Tipos de arquivo compatíveis

  • Formatos de arquivo do Office baseados em OPC (Office 2010 e posterior)
  • Formatos de arquivo herdados do Office (Office 2007)
  • PDF
  • Suporte a PFILE genérico
  • Arquivos compatíveis com Adobe XMP

Funções do manipulador de arquivos

mip::FileHandler expõe métodos para ler, gravar e remover rótulos e informações de proteção. Para obter a lista completa, consulte a Referência de API.

Neste artigo, os seguintes métodos serão abordados:

  • GetLabelAsync()
  • SetLabel()
  • DeleteLabel()
  • RemoveProtection()
  • CommitAsync()

Requisitos

A criação de um FileHandler para trabalhar com um arquivo específico requer:

  • Uma FileProfile
  • Um FileEngine adicionado ao FileProfile
  • Uma classe que herde mip::FileHandler::Observer

Criar um manipulador de arquivo

A primeira etapa necessária no gerenciamento de arquivos no SDK de arquivo é criar um objeto FileHandler. Essa classe implementa toda a funcionalidade necessária para obter, definir, atualizar, excluir e confirmar alterações de rótulos em arquivos.

A criação do FileHandler é tão fácil quanto chamar a função CreateFileHandlerAsync do FileEngine usando o padrão promessa/futuro.

CreateFileHandlerAsync aceita três parâmetros: o caminho para o arquivo que deve ser lido ou modificado, o mip::FileHandler::Observer para notificações de eventos assíncronos e a promessa para o FileHandler.

Observação: a classe mip::FileHandler::Observer deve ser implementada em uma classe derivada, uma vez que CreateFileHandler exige o objeto Observer.

auto createFileHandlerPromise = std::make_shared<std::promise<std::shared_ptr<mip::FileHandler>>>();
auto createFileHandlerFuture = createFileHandlerPromise->get_future();
fileEngine->CreateFileHandlerAsync(filePath, std::make_shared<FileHandlerObserver>(), createFileHandlerPromise);
auto fileHandler = createFileHandlerFuture.get();

Depois de criar o objeto FileHandler com êxito, as operações de arquivo (obter/definir/excluir/confirmar) podem ser executadas.

Ler um rótulo

Requisitos de metadados

Existem alguns requisitos para ler com êxito os metadados de um arquivo e convertê-los em algo que possa ser usado em aplicativos.

  • O rótulo que está sendo lido ainda deve existir no serviço do Microsoft 365. Se ele tiver sido excluído por completo, o SDK não conseguirá obter informações sobre esse rótulo e retornará um erro.
  • Os metadados do arquivo devem estar intactos. Esses metadados incluem:
    • Attribute1
    • Attribute2

GetLabelAsync()

Tendo criado o manipulador para apontar para um arquivo específico, retornamos ao padrão promessa/futuro para ler o rótulo de forma assíncrona. A promessa é para um objeto mip::ContentLabel que contém todas as informações sobre o rótulo aplicado.

Depois da criação de uma instância dos objetos promise e future, lemos o rótulo chamando fileHandler->GetLabelAsync() e fornecendo o promise como o parâmetro solitário. Por fim, o rótulo pode ser armazenado em um objeto mip::ContentLabel que obteremos do future.

auto loadPromise = std::make_shared<std::promise<std::shared_ptr<mip::ContentLabel>>>();
auto loadFuture = loadPromise->get_future();
fileHandler->GetLabelAsync(loadPromise);
auto label = loadFuture.get();

Os dados do rótulo podem ser lidos no objeto label e passados para outro componente ou funcionalidade no aplicativo.


Definir um rótulo

A definição de um rótulo é um processo de duas partes. Primeiro, tendo criado um manipulador que aponte para o arquivo em questão, o rótulo pode ser definido ao ser chamado FileHandler->SetLabel() com alguns parâmetros: mip::Label, mip::LabelingOptions e mip::ProtectionOptions. Primeiro, devemos resolver a ID do rótulo para um rótulo e, em seguida, definir as opções de rotulagem.

Resolver ID do rótulo para mip::Label

O primeiro parâmetro da função SetLabel é um mip::Label. Muitas vezes, o aplicativo está trabalhando com identificadores de rótulo e não com rótulos. O identificador do rótulo pode ser resolvido no mip::Label chamando GetLabelById no mecanismo de arquivo ou política:

mip::Label label = mEngine->GetLabelById(labelId);

Opções de rotulagem

O segundo parâmetro necessário para definir o rótulo é mip::LabelingOptions.

LabelingOptions especifica informações adicionais sobre o rótulo, como o AssignmentMethod e a justificativa de uma ação.

  • mip::AssignmentMethod é um enumerador que tem três valores: STANDARD, PRIVILEGED ou AUTO. Revise a referência mip::AssignmentMethod para obter mais detalhes.
  • A justificativa só será necessária se a política de serviço exigi-la e quando a confidencialidade existente de um arquivo for reduzida.

Essa captura demonstra a criação do objeto mip::LabelingOptions e a configuração da justificativa e da mensagem de downgrade.

auto labelingOptions = mip::LabelingOptions(mip::AssignmentMethod::STANDARD);
labelingOptions.SetDowngradeJustification(true, "Because I made an educated decision based upon the contents of this file.");

Configurações de proteção

Alguns aplicativos podem precisar executar operações em nome de uma identidade de usuário delegado. A classe mip::ProtectionSettings permite que o aplicativo defina a identidade delegada por manipulador. Anteriormente, a delegação era realizada pelas classes de mecanismos. Isso tinha desvantagens significativas na sobrecarga dos aplicativos e em viagens de ida e volta dos serviços. Ao mover as configurações de usuário delegado para mip::ProtectionSettings e torná-las parte da classe do manipulador, eliminamos essa sobrecarga, resultando em melhor desempenho para os aplicativos que estão executando muitas operações em nome de diversos conjuntos de identidades do usuário.

Se a delegação não for necessária, passe mip::ProtectionSettings() para a função SetLabel . Se a delegação for necessária, ela poderá ser obtida com a criação de um objeto mip::ProtectionSettings e com a definição do endereço para correspondência delegado:

mip::ProtectionSettings protectionSettings; 
protectionSettings.SetDelegatedUserEmail("alice@contoso.com");

Definir o rótulo

Depois de buscar o mip::Label usando a ID, de ter definido as opções de rotulagem e, opcionalmente, ter definido as configurações de proteção, o rótulo agora poderá ser definido no manipulador.

Se você não tiver definido as configurações de proteção, defina o rótulo chamando SetLabel no manipulador:

fileHandler->SetLabel(label, labelingOptions, mip::ProtectionSettings());

Se você realmente precisava de configurações de proteção para executar uma operação delegada, então:

fileHandler->SetLabel(label, labelingOptions, protectionSettings);

Agora, depois de ter definido o rótulo no arquivo referenciado pelo manipulador, ainda há mais uma etapa para confirmar a alteração e gravar um arquivo no disco ou criar um fluxo de saída.

Confirmar alterações

A etapa final para confirmar uma alteração em um arquivo no SDK da PIM é confirmar a alteração. Isso é feito usando a função FileHandler->CommitAsync().

Para implementar a função de confirmação, voltamos à promessa/futuro, criando uma promessa para um bool. A função CommitAsync() retornará true se a operação for bem-sucedida, ou false se apresentar falha por qualquer motivo.

Depois de criar o promise e o future, o CommitAsync() é chamado e dois parâmetros são fornecidos: o caminho do arquivo de saída (std::string) e a promessa. Por fim, o resultado é alcançado pela obtenção do valor do objeto future.

auto commitPromise = std::make_shared<std::promise<bool>>();
auto commitFuture = commitPromise->get_future();
fileHandler->CommitAsync(outputFile, commitPromise);
auto wasCommitted = commitFuture.get();

Importante: o FileHandler não atualizará nem substituirá arquivos existentes. Cabe ao desenvolvedor implementar a substituição do arquivo que está sendo rotulado.

Se um rótulo for gravado em FileA.docx, uma cópia do arquivo, FileB.docx, será criada com o rótulo aplicado. Um código deve ser gravado para remover/renomear FileA.docx e renomear FileB.docx.


Excluir um rótulo

auto fileHandler = mEngine->CreateFileHandler(filePath, std::make_shared<FileHandlerObserverImpl>());
fileHandler->DeleteLabel(mip::AssignmentMethod::PRIVILEGED, "Label unnecessary.");
auto commitPromise = std::make_shared<std::promise<bool>>();
auto commitFuture = commitPromise->get_future();
fileHandler->CommitAsync(outputFile, commitPromise);

Remover proteção

O aplicativo do SDK do arquivo da PIM deve validar se o usuário tem direitos para remover a proteção do arquivo que está sendo acessado. Isso pode ser feito por meio de uma verificação de acesso antes de remover a proteção.

A função RemoveProtection() se comporta de maneira semelhante a SetLabel() ou DeleteLabel(). O método é chamado no objeto FileHandler existente. Portanto, a alteração deve ser confirmada.

Importante

Como desenvolvedor de aplicativos, é sua responsabilidade executar essa verificação de acesso. A não execução adequada da verificação de acesso poderá resultar em vazamento de dados.

Exemplo de C++:

// Validate that the file referred to by the FileHandler is protected.
if (fileHandler->GetProtection() != nullptr)
{
    // Validate that user is allowed to remove protection.
    if (fileHandler->GetProtection()->AccessCheck(mip::rights::Export() || fileHandler->GetProtection()->AccessCheck(mip::rights::Owner()))
    {
        auto commitPromise = std::make_shared<std::promise<bool>>();
        auto commitFuture = commitPromise->get_future();
        // Remove protection and commit changes to file.
        fileHandler->RemoveProtection();
        fileHandler->CommitAsync(outputFile, commitPromise);
        result = commitFuture.get();
    }
    else
    {
        // Throw an exception if the user doesn't have rights to remove protection.
        throw std::runtime_error("User doesn't have EXPORT or OWNER right.");
    }
}

Exemplo de .NET:

if(handler.Protection != null)
{                
    // Validate that user has rights to remove protection from the file.                    
    if(handler.Protection.AccessCheck(Rights.Export) || handler.Protection.AccessCheck(Rights.Owner))
    {
        // If user has Extract right, remove protection and commit the change. Otherwise, throw exception. 
        handler.RemoveProtection();
        bool result = handler.CommitAsync(outputPath).GetAwaiter().GetResult();     
        return result;   
    }
    else
    {
        throw new Microsoft.InformationProtection.Exceptions.AccessDeniedException("User lacks EXPORT right.");
    }
}