Antecedentes
Eu tenho a tarefa de configurar o CI. Decidiu-se usar a transformação dos arquivos de configuração e armazenar dados confidenciais em formato criptografado. Você pode criptografar e descriptografá-los usando o Key Container.
Recipiente chave
Cada sistema operacional Windows possui conjuntos de chaves geradas. A chave é gerada na conta ou na máquina. As chaves geradas pela máquina podem ser exibidas nesse caminho C: \ ProgramData \ Microsoft \ Crypto \ RSA \ MachineKeys. É aqui que a chave que criaremos a seguir irá.
Criação de chave
Começamos o cmd a partir do administrador e alternamos para o diretório com aspnet_regiis, tenho este C: \ Windows \ Microsoft.NET \ Framework64 \ v4.0.30319
Execute o comando
aspnet_regiis -pc "TestKey" -exp
exp - é adicionado para que você possa exportar a chave no futuro
TestKey - o nome do nosso Key Container
Exportação de chaves
A equipe
aspnet_regiis -px "TestKey" :\TestKey.xml -pri
TestKey - nome Key Container
C: \ TestKey.xml - o caminho para o qual o arquivo será exportado
pri - adicione uma chave privada para exportar
Chave de importação
A equipe
aspnet_regiis -pi "TestKey" :\TestKey.xml
TestKey - nome Key Container
C: \ TestKey.xml - o caminho de onde o arquivo será exportado
Definir direitos
Para que seu aplicativo ou IIS funcione com o contêiner de chaves, você precisa configurar os direitos para ele.
Isso é feito pela equipe
aspnet_regiis -pa "TestKey" "NT AUTHORITY\NETWORK SERVICE"
TestKey - nome Key Container
NT AUTHORITY \ NETWORK SERVICE - a quem será concedido acesso à chave
Por padrão, o IIS tem ApplicationPoolIdentity para o pool.
A documentação da Microsoft (consulte o link 2) descreve ApplicationPoolIdentity como:
ApplicationPoolIdentity : quando um novo pool de aplicativos é criado, o IIS cria uma conta virtual com o nome do novo pool de aplicativos e que executa o processo de trabalho do pool de aplicativos nessa conta. Essa também é uma conta com menos privilégios.
Portanto, para que o IIS possa descriptografar a configuração, a Identidade deve estar configurada no pool da conta ou você pode selecionar "SERVIÇO DE REDE" e conceder direitos a ela.
Adicionando uma seção à configuração
<configProtectedData defaultProvider="RsaProtectedConfigurationProvider"> <providers> <add name="CustomRsaProtectedConfigurationProvider" type="System.Configuration.RsaProtectedConfigurationProvider,System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" description="Uses RsaCryptoServiceProvider to encrypt and decrypt" keyContainerName="TestKey" cspProviderName="" useMachineContainer="true" useOAEP="false"/> </providers> </configProtectedData>
Também o contêiner de chaves e o RsaProtectedConfigurationProvider são definidos globalmente nos arquivos
C: \ Windows \ Microsoft.NET \ Framework \ v4.0.30319 \ Config \ machine.config, C: \ Windows \ Microsoft.NET \ Framework64 \ v4.0.30319 \ Config \ machine.config
<configProtectedData defaultProvider="RsaProtectedConfigurationProvider"> <providers> <add name="RsaProtectedConfigurationProvider" type="System.Configuration.RsaProtectedConfigurationProvider,System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" description="Uses RsaCryptoServiceProvider to encrypt and decrypt" keyContainerName="NetFrameworkConfigurationKey" cspProviderName="" useMachineContainer="true" useOAEP="false"/> <add name="DataProtectionConfigurationProvider" type="System.Configuration.DpapiProtectedConfigurationProvider,System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" description="Uses CryptProtectData and CryptUnProtectData Windows APIs to encrypt and decrypt" useMachineProtection="true" keyEntropy=""/> </providers> </configProtectedData>
= "System.Configuration.DpapiProtectedConfigurationProvider, System.Configuration, versão = 4.0.0.0, Culture = neutral, PublicKeyToken = b03f5f7f11d50a3a" description = "Usa CryptProtectData e CryptUnprotectData do Windows APIs para criptografar e descriptografar" useMachineProtection = <configProtectedData defaultProvider="RsaProtectedConfigurationProvider"> <providers> <add name="RsaProtectedConfigurationProvider" type="System.Configuration.RsaProtectedConfigurationProvider,System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" description="Uses RsaCryptoServiceProvider to encrypt and decrypt" keyContainerName="NetFrameworkConfigurationKey" cspProviderName="" useMachineContainer="true" useOAEP="false"/> <add name="DataProtectionConfigurationProvider" type="System.Configuration.DpapiProtectedConfigurationProvider,System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" description="Uses CryptProtectData and CryptUnProtectData Windows APIs to encrypt and decrypt" useMachineProtection="true" keyEntropy=""/> </providers> </configProtectedData>
Criptografia
A criptografia em si pode ser feita de três maneiras.
Criptografia de linha de comando
aspnet_regiis.exe -pef connectionStrings :\Site -prov "CustomRsaProtectedConfigurationProvider"
C: \ Site - caminho para o arquivo com a configuração.
CustomRsaProtectedConfigurationProvider - nosso provedor especificado na configuração chamada key container.
Criptografia através de um aplicativo escrito
private static string provider = "CustomRsaProtectedConfigurationProvider"; public static void ProtectConfiguration() { Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); ConfigurationSection connStrings = config.ConnectionStrings; if (connStrings != null && !connStrings.SectionInformation.IsProtected && !connStrings.ElementInformation.IsLocked) { connStrings.SectionInformation.ProtectSection(provider); connStrings.SectionInformation.ForceSave = true; config.Save(ConfigurationSaveMode.Full); } } public static void UnProtectConfiguration(string path) { Configuration config = ConfigurationManager.OpenExeConfiguration(path); ConfigurationSection connStrings = config.ConnectionStrings; if (connStrings != null && connStrings.SectionInformation.IsProtected && !connStrings.ElementInformation.IsLocked) { connStrings.SectionInformation.UnprotectSection(); } }
Bicicleta
Quando houver uma transformação de arquivo e você precisar criptografar seções separadamente de toda a configuração, apenas uma versão auto-escrita será adequada. Criamos uma instância da classe RsaProtectedConfigurationProvider, pegamos um nó do xml e o criptografamos separadamente, depois substituímos o nó no nosso xml original pelo nosso criptografado e salvamos o resultado.
public void Protect(string filePath, string sectionName = null) { XmlDocument xmlDocument = new XmlDocument { PreserveWhitespace = true }; xmlDocument.Load(filePath); if (xmlDocument.DocumentElement == null) { throw new InvalidXmlException($"Invalid Xml document"); } sectionName = !string.IsNullOrEmpty(sectionName) ? sectionName : xmlDocument.DocumentElement.Name; var xmlElement = xmlDocument.GetElementsByTagName(sectionName)[0] as XmlElement; var config = new NameValueCollection { { "keyContainerName", _settings.KeyContainerName }, { "useMachineContainer", _settings.UseMachineContainer ? "true" : "false" } }; var rsaProvider = new RsaProtectedConfigurationProvider(); rsaProvider.Initialize(_encryptionProviderSettings.ProviderName, config); var encryptedData = rsaProvider.Encrypt(xmlElement); encryptedData = xmlDocument.ImportNode(encryptedData, true); var createdXmlElement = xmlDocument.CreateElement(sectionName); var xmlAttribute = xmlDocument.CreateAttribute("configProtectionProvider"); xmlAttribute.Value = _encryptionProviderSettings.ProviderName; createdXmlElement.Attributes.Append(xmlAttribute); createdXmlElement.AppendChild(encryptedData); if (createdXmlElement.ParentNode == null || createdXmlElement.ParentNode.NodeType == XmlNodeType.Document || xmlDocument.DocumentElement == null) { XmlDocument docNew = new XmlDocument { InnerXml = createdXmlElement.OuterXml }; docNew.Save(filePath); } else { xmlDocument.DocumentElement.ReplaceChild(createdXmlElement, xmlElement); xmlDocument.Save(filePath); } }
Referências
1.docs.microsoft.com/pt-br/previous-versions/53tyfkaw2.support.microsoft.com/pt-br/help/4466942/understanding-identities-in-iis