NFe – Considerações sobre ambiente – Parte II

By Nataniel Strack

Escrito por Paulo Renato Godinho Amaral:

Buenas!
Voltando ao que interessa. Solução com Web Service.
GeneXus DE u4 e .Net Web u4.

Exemplificando a arquitetura

S.O. Windows 2003 Server R2
.Net Framework 2.0

IIS Application Pool “Sistemas”
> Usuário Identidade: Network Service
> Diretório Virtual : “SistemaWeb”

IIS Application Pool “WebServices”
> Usuário Identidade: nfe (usuário local no grupo Administradores
e IIS_WPG)
> Diretório Virtual : “wsnfe”
> Properties\Directory Security\Secure Comunications\Edit
\Accept Client Certificates

No lugar da chamada ao executável win, foi substituido por uma chamada
a um web service, que contém o mesmo código win, porém gerado com o
gerador web. Para debug fiz uma chamada a mesma procedure com o código
por uma web panel main. E o erro encontrado foi o mesmo da execução do
exe win chamado pela web, porém com mais detalhes, segue:

[CryptographicException: The system cannot find the file specified.]

System.Security.Cryptography.CryptographicException.ThrowCryptogaphicException
(Int32 hr) +33

System.Security.Cryptography.X509Certificates.X509Utils._LoadCertFromFile
(String fileName, IntPtr password, UInt32 dwFlags, Boolean
persistKeySet, SafeCertContextHandle& pCertCtx) +0

System.Security.Cryptography.X509Certificates.X509Certificate.LoadCertificateFromFile
(String fileName, Object password, X509KeyStorageFlags
keyStorageFlags) +228
GeneXus.Http.Client.GxHttpClient.AddCertificate(String file) +82
GeneXus.Programs.pnfeconsomewebservice.executePrivate() +366
GeneXus.Programs.pnfemanager.S1130() +580
GeneXus.Programs.pnfemanager.executePrivate() +521
GeneXus.Programs.pnfemanager.execute(String& aP0_DadosXml,
SdtNFEConfig& aP1_NFEConfig, GxObjectCollection& aP2_NFEProcessos) +61
GeneXus.Programs.pnfestart.executePrivate() +231
GeneXus.Programs.pnfestart.execute(String aP0_DadosXml, String
aP1_NFEServidorUF, String aP2_NFEWebService, String& aP3_SaidaXml,
SdtNFEConfig& aP4_NFEConfig) +80
GeneXus.Programs.pnfedisparo.executePrivate() +467
GeneXus.Programs.hnfedisparo.EVT012() +1089
GeneXus.Programs.hnfedisparo.webExecute() +141
GeneXus.Http.GXHttpHandler.ProcessRequest(HttpContext httpContext)
+143

[Exception: GXApplication exception]
GeneXus.Http.GXHttpHandler.ProcessRequest(HttpContext httpContext)
+250

System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute
() +358
System.Web.HttpApplication.ExecuteStep(IExecutionStep step,
Boolean& completedSynchronously) +64

I – A solução de contorno
Nesse meio tempo, em pesquisas pelo google, encontrei o seguinte
tópico de um fórum:

http://www.eggheadcafe.com/aspnet_answers/NETsecurity/Mar2006/post26409120.asp

Este fórum reportava os comportamento que estava enfrentando, e uma
dica surgiu, de criar uma tarefa agendada no Windows, com o usuário do
IIS Application Pool, no meu caso usuário nfe.
Com isso tudo passou a funcionar, tanto o web service, quanto a
chamada do executável win. Enfim, uma solução de contorno POG e com
isso optamos por manter a solução com o web service.

Não satisfeito, continuamos em busca da solução perfeita.

II – Esclarecimentos
Com o erro mais claro, a partir da aplicação web, seguindo a trilha,
notamos que o erro ocorre exatamente no momento de executar o método
AddCertificate do tipo de dados HttpClient.
A partir de uma ajuda externa, conseguimos identificar fazendo um
decompile da gxdata.dll que o código implementado pela ARTech para o
método em questão, necessita que o Profile do usuário “dono” do
processo esteja “carregado” no Windows. Isto ocorre, no logon do
usuário, pode ser por meio de uma tarefa agenda ou por logon
diretamente no servidor, por isso, nessas situaçãos a solução
funciona.

A partir de um report da Microsoft, identificamos a solução ideal.
Referência:

http://support.microsoft.com/kb/948154

III – A solução ideal
A implementação que temos hoje em dia da ARTech para o método
AddCertificate,

X509Certificate certificate = X509Certificate.CreateFromCertFile
(file);

Para buscar o certificado de um arquivo .pfx utilizando este método,
exige que o profile do usuário do processo, esteja carregado no
Windows.
A solução seria mudar esta implementação para buscar de um Store de
certificados do computador no lugar de buscar de um arquivo
(Referência de adicionar em Store: http://technet.microsoft.com/en-us/library/bb727068.aspx).
E para fazer com que busque o certificado do store, o código a ser
implementado teria que ser algo do tipo,

X509Store store = new X509Store(“My”, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);

System.Security.Cryptography.X509Certificates.X509Certificate2
newCert =
store.Certificates.Find(X509FindType.FindBySubjectName,
“XXXXXXXXXXXXX”, false)[0];

Estou criando um .CS a parte (gerei uma proc vazia GX para ver o
código necessário para a integração), já consegui implementar o código
e integrar parcialmente com o GeneXus.
– App web GX chama o CS
– Encontra o certificado no store
– Adiciona a coleção de certificados
Porém, não estou conseguindo passar adiante a coleção para que o
GeneXus prossiga seu curso normal, e adicione o certificado na
mensagem SOAP.

IV – A ARTech
Conversando com a ARTech por meio de um incidente, foi criado um SAC e
a sugestão ficou para ser implementada na versão GeneXus X ou
Evolution.
Na versão GeneXus 9.0 não será possível implantar a solução pois o
projeto dessa versão usa o .NetFramework 1.1 e a solução ideal precisa
do .NetFramework 2.0.

V – Reflexões
Solução de contorno encontrada e em busca de uma solução com melhoria
do código.
Pensei em tentar incluir o certificado à mensagem SOAP com tipo de
dados XMLWriter, porém, não achei ainda, como é a estrutura de
certificado na mensagem SOAP. Isso poderia simplificar a solução
Sempre tem brigas com estes tipos de tecnologias, complexas mas muito
interessantes de se aprender, quanto mais colaboramos com nosso
conhecimento, mais estaremos nos ajudando.

Por hoje é só pessoal!

Add to FacebookAdd to NewsvineAdd to DiggAdd to Del.icio.usAdd to StumbleuponAdd to RedditAdd to BlinklistAdd to Ma.gnoliaAdd to TechnoratiAdd to Furl

Deixe uma resposta