Show / Hide Table of Contents
Editar no GitHub

Integração com Azure Key Vault

O pacote Lacuna PKI Azure Connector possibilita utilizar certificados e chaves armazenadas em Azure Key Vaults para assinar documentos, emitir certificados etc.

Para utilizar certificados ou chaves armazenados em um key vault, você precisará dos seguintes parâmetros:

  • Endpoint: campo DnsName do key vault, pode ser obtido na área Overview do vault
  • AppId: campo Application ID de uma aplicação registrada no Microsoft Entra ID
  • AppSecret: segredo da aplicação, gerado na área Certificates & secrets da aplicação

Além disso, para cada certificado ou chave que se pretende utilizar é necessário saber seu name.

Instruções para uso

Tip

Veja a sessão ASP.NET Core abaixo caso a sua aplicação utilize essa tecnologia.

De posse dos parâmetros necessários, instancie um AzureKeyVaultOptions e, com este, um AzureApiAuthenticator:

var options = new AzureKeyVaultOptions() {
    Endpoint = "...",
    AppId = "...",
    AppSecret = "...",
};
var azureApiAuthenticator = new AzureApiAuthenticator(options);
Note

A sua aplicação deve manter uma única instância do AzureApiAuthenticator (singleton lifetime).

Em seguida, instancie um AzureCertificateProvider e então solicite um PKCertificateWithKey passando o certificateName do certificado que deseja utilizar:

Note

Se você armazena apenas as chaves dos certificados no Azure Key Vault, mas não os próprios certificados, leia a seção abaixo.

var azureCertProvider = new AzureCertificateProvider(options, azureApiAuthenticator);
var certWithKey = await azureCertProvider.GetCertificateWithKeyAsync(/* certificateName */);
Note

A instância do AzureCertificateProvider deve ser criada e descartada à medida que for necessário (transient lifetime).

Com um PKCertificateWithKey, é possível fazer assinaturas em "um único passo", por exemplo:

var signer = new PadesSigner();
signer.SetPdfToSign(/* PDF file path, content or stream */);
signer.SetSigningCertificate(certWithKey);
signer.SetPolicy(PadesPoliciesForGeneration.GetPadesBasic(TrustArbitrators.PkiBrazil));
signer.ComputeSignature();
var signedPdf = signer.GetPadesSignature();

Segue um exemplo completo:

// System-wide singletons
Global.AzureKeyVaultOptions = new AzureKeyVaultOptions() {
    Endpoint = "...",
    AppId = "...",
    AppSecret = "...",
};
Global.AzureApiAuthenticator = new AzureApiAuthenticator(options);

...

var azureCertProvider = new AzureCertificateProvider(Global.AzureKeyVaultOptions, Global.AzureApiAuthenticator);
var certWithKey = await azureCertProvider.GetCertificateWithKeyAsync(/* certificateName */);

var signer = new PadesSigner();
signer.SetPdfToSign(/* PDF file path, content or stream */);
signer.SetSigningCertificate(certWithKey);
signer.SetPolicy(PadesPoliciesForGeneration.GetPadesBasic(TrustArbitrators.PkiBrazil));
signer.ComputeSignature();
var signedPdf = signer.GetPadesSignature();

ASP.NET Core

Caso a sua aplicação web seja em ASP.NET Core, adicione o seguinte código ao método ConfigureServices do startup da sua aplicação:

public void ConfigureServices(IServiceCollection services) {
    ...
    services.AddAzureKeys()
        .Configure(Configuration.GetSection("AzureKeyVault"));
}

No arquivo de configuração appsettings.json, adicione a seção AzureKeyVault:

...
"AzureKeyVault": {
    "Endpoint": "https://my-key-vault.vault.azure.net/",
    "AppId": "...",
    "AppSecret": "..."
},
...

Nas partes da aplicação que precisarem utilizar certificados armazenados no Key Vault, peça via dependency injection uma instância de IAzureCertificateProvider:

using Lacuna.Pki.AzureConnector;

public MyController : ApiController {

    private readonly IAzureCertificateProvider azureCertProvider;

    public MyController(IAzureCertificateProvider azureCertProvider) {
        this.azureCertProvider = azureCertProvider;
    }

    ...
}

Daí em diante, o uso é idêntico ao descrito na seção anterior:

var certWithKey = await azureCertProvider.GetCertificateWithKeyAsync(/* certificateName */);

var signer = new PadesSigner();
signer.SetPdfToSign(/* PDF file path, content or stream */);
signer.SetSigningCertificate(certWithKey);
signer.SetPolicy(PadesPoliciesForGeneration.GetPadesBasic(TrustArbitrators.PkiBrazil));
signer.ComputeSignature();
var signedPdf = signer.GetPadesSignature();

Usando certificados apenas com chave armazenada em Key Vault

Você pode optar por armazenar em Azure Key Vault apenas as chaves dos certificados, armazenando na sua aplicação a parte pública dos certificados (arquivos .cer/.crt/.pem) correspondente às chaves.

Nesse caso, instancie um AzureKeyProvider e então solicite uma AzureKey passando o keyName da chave que deseja utilizar:

var azureKeyProvider = new AzureKeyProvider(options, azureApiAuthenticator);
var key = await azureKeyProvider.GetKeyAsync(/* keyName */);
Note

A instância do AzureKeyProvider deve ser criada e descartada à medida que for necessário (transient lifetime).

A classe AzureKey implementa a interface IPrivateKey, portanto pode ser usada como tal:

byte[] toSignHash = ...;
var signature = key.GetSignatureCsp(DigestAlgorithm.SHA256).SignHash(toSignHash);

Entretanto, a forma mais fácil de usar a chave é chamando o método GetCertificateWithKey() com o certificado (que pode estar disponível como uma configuração da sua aplicação, ou armazenado em banco de dados, ou ainda estar hardcoded):

var certificate = PKCertificate.Decode(/* certificate file path or content */);
var certWithKey = key.GetCertificateWithKey(certificate);

No caso de aplicações em ASP.NET Core, ao invés de pedir uma instância de IAzureCertificateProvider por injeção de dependência, peça um IAzureKeyProvider e chame o método GetKeyAsync() quando necessário:

using Lacuna.Pki.AzureConnector;

public MyController : ApiController {

    private readonly IAzureKeyProvider azureKeyProvider;

    public MyController(IAzureKeyProvider azureKeyProvider) {
        this.azureKeyProvider = azureKeyProvider;
    }

    ...

    public async Task<ActionResult> Post() {

        ...

        var key = await azureKeyProvider.GetKeyAsync(/* keyName */);
        var certificate = PKCertificate.Decode(/* certificate file path or content */);
        var certWithKey = key.GetCertificateWithKey(certificate);

        var signer = new PadesSigner();
        signer.SetPdfToSign(/* PDF file path, content or stream */);
        signer.SetSigningCertificate(certWithKey);
        signer.SetPolicy(PadesPoliciesForGeneration.GetPadesBasic(TrustArbitrators.PkiBrazil));
        signer.ComputeSignature();
        var signedPdf = signer.GetPadesSignature();

        ...
    }
}
Back to top Copyright © 2015-2020 Lacuna Software