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();
...
}
}