If the WCF LOB Adapter Pack receives a RFC_ERROR_COMMUNICATION from SAP saying "Connect from SAP gateway to RFC server failed", you have to double check that all network settings are correct so that send and receive are possible. In our case that NATting of the response did not reach us, while we could track our call successfully on the firewall.
Other reasons might be SAP configuration or missing entries in services file.
Random pitfalls (and their solutions) in EAI technologies such as BizTalk
Friday, January 24, 2014
Thursday, November 14, 2013
Encrypt XML Content with X.509 Certificates
On MSDN, there is some help how to encrypt XML elements with certificates, for example here: How To: Encrypt XML Element with X.509 Certificates
However, what is missing, is advice about how to encrypt XML content, i.e. in the famous XML example
<root>
<creditcard>
<number>19834209</number>
<expiry>02/02/2002</expiry>
</creditcard>
</root>
you might not want to decrypt the whole <creditcard> element, but rather its two subnodes <number> and <expiry>. This is necessary when the http://www.w3.org/2001/04/xmlenc#Content standard is used.
I just reuse the code from the how-to-article and add specific lines for the content-encryption:
For Encryption, you use this method:
public static XmlDocument Encrypt(XmlDocument doc, string elementToEncryptName, X509Certificate2 cert)
{
// Check the arguments.
if (doc == null)
throw new ArgumentNullException("doc");
if (elementToEncryptName == null)
throw new ArgumentNullException("elementToEncryptName");
if (cert == null)
throw new ArgumentNullException("cert");
////////////////////////////////////////////////
// Find the specified element in the XmlDocument
// object and create a new XmlElemnt object.
////////////////////////////////////////////////
XmlElement elementToEncrypt = doc.GetElementsByTagName(elementToEncryptName)[0] as XmlElement;
// Throw an XmlException if the element was not found.
if (elementToEncrypt == null)
{
throw new XmlException("The specified element was not found");
}
//////////////////////////////////////////////////
// Create a new instance of the EncryptedXml class
// and use it to encrypt the XmlElement with the
// a new random symmetric key.
//////////////////////////////////////////////////
// Create a 256 bit Rijndael key.
RijndaelManaged sessionKey = new RijndaelManaged();
sessionKey.KeySize = 128;
// Set RSA crypto provider to certificate's public key
RSACryptoServiceProvider alg = (RSACryptoServiceProvider) cert.PublicKey.Key;
// Encrypt the content of the XML element
EncryptedXml eXml = new EncryptedXml();
byte[] encryptedElement = eXml.EncryptData(Encoding.UTF8.GetBytes(elementToEncrypt.InnerXml), sessionKey);
////////////////////////////////////////////////
// Construct an EncryptedData object and populate
// it with the desired encryption information.
////////////////////////////////////////////////
EncryptedData edElement = new EncryptedData();
edElement.Type = EncryptedXml.XmlEncElementContentUrl;
//edElement.Id = encryptionElementId;
// Create an EncryptionMethod element so that the
// receiver knows which algorithm to use for decryption.
edElement.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncAES128Url);
// Encrypt the session key and add it to an EncryptedKey element.
EncryptedKey ek = new EncryptedKey();
byte[] encryptedKey = EncryptedXml.EncryptKey(sessionKey.Key, alg, true);
ek.CipherData = new CipherData(encryptedKey);
ek.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncRSAOAEPUrl);
edElement.KeyInfo.AddClause(new KeyInfoEncryptedKey(ek));
//// Create a new KeyInfo element.
KeyInfo ki = new KeyInfo();
ki.AddClause(new KeyInfoX509Data(cert, X509IncludeOption.EndCertOnly));
// Add the KeyInfoName element to the
// EncryptedKey object.
ek.KeyInfo = ki;
// Add the encrypted element data to the
// EncryptedData object.
edElement.CipherData.CipherValue = encryptedElement;
////////////////////////////////////////////////////
// Replace the element from the original XmlDocument
// object with the EncryptedData element.
////////////////////////////////////////////////////
EncryptedXml.ReplaceElement(elementToEncrypt, edElement, true);
sessionKey.Clear();
return doc;
}
The decryption can be taken from the MSDN example:
public static XmlDocument Decrypt(XmlDocument doc)
{
// Check the arguments.
if (doc == null)
throw new ArgumentNullException("doc");
// Decrypt the XML document, with the help of the private key from the certification store
EncryptedXml exml = new EncryptedXml(doc);
exml.DecryptDocument();
return doc;
}
The calling code will be:
X509Certificate2 cert = new X509Certificate2("xxx.pfx", "xxx");
var encrypted = Encrypt(xmlDoc, "creditcard", cert);
var decrypted = Decrypt(encrypted);
However, what is missing, is advice about how to encrypt XML content, i.e. in the famous XML example
<creditcard>
<number>19834209</number>
<expiry>02/02/2002</expiry>
</creditcard>
</root>
you might not want to decrypt the whole <creditcard> element, but rather its two subnodes <number> and <expiry>. This is necessary when the http://www.w3.org/2001/04/xmlenc#Content standard is used.
I just reuse the code from the how-to-article and add specific lines for the content-encryption:
For Encryption, you use this method:
public static XmlDocument Encrypt(XmlDocument doc, string elementToEncryptName, X509Certificate2 cert)
{
// Check the arguments.
if (doc == null)
throw new ArgumentNullException("doc");
if (elementToEncryptName == null)
throw new ArgumentNullException("elementToEncryptName");
if (cert == null)
throw new ArgumentNullException("cert");
////////////////////////////////////////////////
// Find the specified element in the XmlDocument
// object and create a new XmlElemnt object.
////////////////////////////////////////////////
XmlElement elementToEncrypt = doc.GetElementsByTagName(elementToEncryptName)[0] as XmlElement;
// Throw an XmlException if the element was not found.
if (elementToEncrypt == null)
{
throw new XmlException("The specified element was not found");
}
//////////////////////////////////////////////////
// Create a new instance of the EncryptedXml class
// and use it to encrypt the XmlElement with the
// a new random symmetric key.
//////////////////////////////////////////////////
// Create a 256 bit Rijndael key.
RijndaelManaged sessionKey = new RijndaelManaged();
sessionKey.KeySize = 128;
// Set RSA crypto provider to certificate's public key
RSACryptoServiceProvider alg = (RSACryptoServiceProvider) cert.PublicKey.Key;
// Encrypt the content of the XML element
EncryptedXml eXml = new EncryptedXml();
byte[] encryptedElement = eXml.EncryptData(Encoding.UTF8.GetBytes(elementToEncrypt.InnerXml), sessionKey);
////////////////////////////////////////////////
// Construct an EncryptedData object and populate
// it with the desired encryption information.
////////////////////////////////////////////////
EncryptedData edElement = new EncryptedData();
edElement.Type = EncryptedXml.XmlEncElementContentUrl;
//edElement.Id = encryptionElementId;
// Create an EncryptionMethod element so that the
// receiver knows which algorithm to use for decryption.
edElement.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncAES128Url);
// Encrypt the session key and add it to an EncryptedKey element.
EncryptedKey ek = new EncryptedKey();
byte[] encryptedKey = EncryptedXml.EncryptKey(sessionKey.Key, alg, true);
ek.CipherData = new CipherData(encryptedKey);
ek.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncRSAOAEPUrl);
edElement.KeyInfo.AddClause(new KeyInfoEncryptedKey(ek));
//// Create a new KeyInfo element.
KeyInfo ki = new KeyInfo();
ki.AddClause(new KeyInfoX509Data(cert, X509IncludeOption.EndCertOnly));
// Add the KeyInfoName element to the
// EncryptedKey object.
ek.KeyInfo = ki;
// Add the encrypted element data to the
// EncryptedData object.
edElement.CipherData.CipherValue = encryptedElement;
////////////////////////////////////////////////////
// Replace the element from the original XmlDocument
// object with the EncryptedData element.
////////////////////////////////////////////////////
EncryptedXml.ReplaceElement(elementToEncrypt, edElement, true);
sessionKey.Clear();
return doc;
}
The decryption can be taken from the MSDN example:
public static XmlDocument Decrypt(XmlDocument doc)
{
// Check the arguments.
if (doc == null)
throw new ArgumentNullException("doc");
// Decrypt the XML document, with the help of the private key from the certification store
EncryptedXml exml = new EncryptedXml(doc);
exml.DecryptDocument();
return doc;
}
The calling code will be:
X509Certificate2 cert = new X509Certificate2("xxx.pfx", "xxx");
var encrypted = Encrypt(xmlDoc, "creditcard", cert);
var decrypted = Decrypt(encrypted);
Thursday, July 4, 2013
SftpException "List remote directory error"
If you get this error message in the BTS2013 SFTP adapter:
The Messaging Engine failed to add a receive location "TestFTP_FTPOUTIN" with URL "sftp://ehavftp6402.eha.net:22/IN/*.xml" to the adapter "SFTP". Reason: "Microsoft.BizTalk.Adapter.SftpInvoker.SftpException: List remote directory error.
... the adapter can't find the directory at the remote server. Just add a slash ("/") before the folder name in the FolderPath field of the Receive Location adapter configuration.
The Messaging Engine failed to add a receive location "TestFTP_FTPOUTIN" with URL "sftp://ehavftp6402.eha.net:22/IN/*.xml" to the adapter "SFTP". Reason: "Microsoft.BizTalk.Adapter.SftpInvoker.SftpException: List remote directory error.
... the adapter can't find the directory at the remote server. Just add a slash ("/") before the folder name in the FolderPath field of the Receive Location adapter configuration.
Tuesday, July 2, 2013
ActionNotSupported after WSCF
After using WSCF to generate code from a WSDL, I receveied an ActionNotSupported-Fault from the webservice. The exception said furthermore (in German):
Die Nachricht mit Action "http://www.energylink.at/datenplattform/ws20/ENERGYLINKTransaction" kann aufgrund einer fehlenden ContractFilter-Übereinstimmung beim EndpointDispatcher nicht verarbeitet werden. Mögliche Ursachen: Vertragskonflikt (keine Action-Übereinstimmung zwischen Sender und Empfänger) oder ein Bindung/Sicherheit-Konflikt zwischen dem Sender und dem Empfänger. Stellen Sie sicher, dass Sender und Empfänger über den gleichen Vertrag und die gleiche Bindung verfügen (einschließlich Sicherheitsanforderungen, z. B. "Message", "Transport", "None")
If you run into this exception, check the Action, that has been generated in the code for the interface. Most probably, a wrong action had been created. It has to be the same that is written in your WSDL.
Die Nachricht mit Action "http://www.energylink.at/datenplattform/ws20/ENERGYLINKTransaction" kann aufgrund einer fehlenden ContractFilter-Übereinstimmung beim EndpointDispatcher nicht verarbeitet werden. Mögliche Ursachen: Vertragskonflikt (keine Action-Übereinstimmung zwischen Sender und Empfänger) oder ein Bindung/Sicherheit-Konflikt zwischen dem Sender und dem Empfänger. Stellen Sie sicher, dass Sender und Empfänger über den gleichen Vertrag und die gleiche Bindung verfügen (einschließlich Sicherheitsanforderungen, z. B. "Message", "Transport", "None")
If you run into this exception, check the Action, that has been generated in the code for the interface. Most probably, a wrong action had been created. It has to be the same that is written in your WSDL.
Friday, May 24, 2013
Visual Studio 2013 enables Build and Deploy after Migration
Just to know when you migrate from VS2010 to VS2012: The configuration manager can change an inactive project so that it would be build and deployed. So just check the configuration manager after migrating.
EDIOverride Properties have been renamed
Short info: When migrating from BizTalk 2010 to BizTalk 2013, you have to adapt the EDIOverride properties. For example, the property Unb21 is now called UNB2_1.
The EDIOverride properties are stored in Microsoft.BizTalk.Edi.BaseArtifacts.dll.
The EDIOverride properties are stored in Microsoft.BizTalk.Edi.BaseArtifacts.dll.
Thursday, December 13, 2012
Error "There was an authentication failure"
Whenever our POP3 Receive Location read a signed mail, it throwed the following exception and suspended the instance:
A message received by adapter "POP3" on receive location "yyy" with URI "POP3://yyy#yyy\yyy" is suspended.
Error details: There was an authentication failure. "The status of the certificate authority that issued the certificate used to sign the message is unknown.".
The reason behind was, that the certificate was found, but the Certificate Revocation List (CRL) from the Internet could not be opened, because the server had no Internet access. Since the CRL is saved in public available CRL files, we only had to open the firewall for these types of files, and BizTalk could accept the mails.
A message received by adapter "POP3" on receive location "yyy" with URI "POP3://yyy#yyy\yyy" is suspended.
Error details: There was an authentication failure. "The status of the certificate authority that issued the certificate used to sign the message is unknown.".
The reason behind was, that the certificate was found, but the Certificate Revocation List (CRL) from the Internet could not be opened, because the server had no Internet access. Since the CRL is saved in public available CRL files, we only had to open the firewall for these types of files, and BizTalk could accept the mails.
Labels:
Biztalk,
CA,
Certificate Revocation List,
CRL,
POP3
Thursday, November 1, 2012
BatchComplete-Error in Biztalk Base Adapter
After migrating from Biztalk 2006 to Biztalk 2010, our custom adapters threw new errors when a message suspended:
One from MS CoreAdapter
... the other one in our customer Adapter:
The reason was a missing bugfix that Microsoft introduced in BTS2010 into the BaseAdapter. If you get the new version (however, with the same version number 1.0.2) from C:\Program Files (x86)\Microsoft BizTalk Server 2010\SDK\Samples\AdaptersDevelopment\BaseAdapter\v1.0.2, the problem should be fixed.
One from MS CoreAdapter
Batch.BatchComplete hrStatus:c000010x00c00001:
BTS_S_EPM_MESSAGE_SUSPENDED (Transport Proxy)
... the other one in our customer Adapter:
[26]
ERROR [(null)] BIZTALK_StammdatenTransfers_XferDBAdapter_StammdatenTransfer -
Beim Versenden des Batches [BatchInfo(00d6d71f), Batch(00e70a8e)]trat ein
Problem auf:
12582913-0x00c00001: BTS_S_EPM_MESSAGE_SUSPENDED (Transport Proxy)
The reason was a missing bugfix that Microsoft introduced in BTS2010 into the BaseAdapter. If you get the new version (however, with the same version number 1.0.2) from C:\Program Files (x86)\Microsoft BizTalk Server 2010\SDK\Samples\AdaptersDevelopment\BaseAdapter\v1.0.2, the problem should be fixed.
Thursday, October 18, 2012
BizTalk 2010 Tracking error: Receive and Send Ports do not track
We've just run into the problem that our receive and send ports did not track anything, although we've checked all tracking options and all needed database jobs were running. After analysing the problem for a while, we found out that orchestrations and custom pipelines track, but not the Biztalk system pipelines XmlTransmit, XmlReceive and PassThru pipeline.
With the help of the Biztalk support team, we found that somehow the database was screwed up - while the UI showed us all tracking checks enabled, the exported binding file showed only PipelineEvents as TrackingOption, while ServiceStartEnd and MessageSendReceive were missing.
The actual error was in table TraceTrackingInfo where imgData had the value 0x10000000 instead of 0x13000000. You can change it with SQL but keep in mind that the column is in hexadecimal format. Manipulate the table hence like this (after making a backup):
begin transaction
update BizTalkMgmtDb.dbo.StaticTrackingInfo set imgData = 0x13000000 where strServiceName in (
'Microsoft.BizTalk.DefaultPipelines.XMLTransmit',
'Microsoft.BizTalk.DefaultPipelines.XMLReceive',
'Microsoft.BizTalk.DefaultPipelines.PassThruTransmit',
'Microsoft.BizTalk.DefaultPipelines.PassThruReceive')
--commit
Addition 24.10.2012: Two actions had changed the pipeline:
First, the wrong field value had been inserted by another, self-written script during a deplyoment step, so this is not a Biztalk error.
Second, when importing a binding file where TransmitPipeline had only the TrackingOption="PipelineEvents", this pipeline was modified to the wrong value.
If you now run into the same problem, you can check (and correct) imgData; then, you should also check which routine in your system might have modified imgData before.
With the help of the Biztalk support team, we found that somehow the database was screwed up - while the UI showed us all tracking checks enabled, the exported binding file showed only PipelineEvents as TrackingOption, while ServiceStartEnd and MessageSendReceive were missing.
The actual error was in table TraceTrackingInfo where imgData had the value 0x10000000 instead of 0x13000000. You can change it with SQL but keep in mind that the column is in hexadecimal format. Manipulate the table hence like this (after making a backup):
begin transaction
update BizTalkMgmtDb.dbo.StaticTrackingInfo set imgData = 0x13000000 where strServiceName in (
'Microsoft.BizTalk.DefaultPipelines.XMLTransmit',
'Microsoft.BizTalk.DefaultPipelines.XMLReceive',
'Microsoft.BizTalk.DefaultPipelines.PassThruTransmit',
'Microsoft.BizTalk.DefaultPipelines.PassThruReceive')
--commit
Addition 24.10.2012: Two actions had changed the pipeline:
First, the wrong field value had been inserted by another, self-written script during a deplyoment step, so this is not a Biztalk error.
Second, when importing a binding file where TransmitPipeline had only the TrackingOption="PipelineEvents", this pipeline was modified to the wrong value.
If you now run into the same problem, you can check (and correct) imgData; then, you should also check which routine in your system might have modified imgData before.
Friday, October 12, 2012
Reading current UNB Reference numbers from Biztalk
While migrating EDIFACT partners from Biztalk 2006 to 2010, we had to read the current UNB Reference numbers from the Biztalk 2006 database. They are stored in the BiztalkMsgBoxDb database in table EdiSequenceNumbers. Using the column PartyId, one can link the numbers to the EDI party information from database BiztalkMgmtDb, table EdiPartnerEdifactInterchange.
BTW, beginning from Biztalk 2009, you can directly set the UNB Reference number before sending the EDIFACT XML to the EDI Send Pipeline, hence it might be useful to create the number by oneself.
Labels:
Biztalk,
EDIFACT,
EDISendPipeline
Location:
Hamburg, Deutschland
Subscribe to:
Posts (Atom)