Using this blog you can maintain your AS2 agreements in a Azure Integration account. Furthermore, I describe how to maintain EDIFACT agreements too. This continues from my previous blog about Azure Integration Account configuration.
Setting up AS2 agreements in an Integration Account
Firstly, you can configure an agreement using the integration account blade following the Define agreements between partners in workflows – Azure Logic Apps | Microsoft Learn.
How do you deploy this using devops? Before describing how to deploy agreement using devops I will first describe why I had to include this in my devops project.
In short, moving agreements between environments using the integration account blade is tiresome and prone to error. Thus scripting the process is a requirement.
Scripting deployment of agreements
To get back to the point, I do not know of a devops task that deploys agreements. Instead, I use a powershell within a powershell devops tasks. My devops project contains two tasks “Deploy Partners to Integration Accounts” and “Deploy Agreements to Integration Account”.
Firstly the configure partners using AddNewTradingPartners-<env>.ps1. If you want to update you need delete the partner first because in my hands New-AzIntegrationAccountPartner (Az.LogicApp) | Microsoft Learn does no allow overwrite.
$RG = "edi-dev-rg"
$IA = "edi-dev-ia"
$IAAccountPartner = "BidfoodAU"
$BusinessIdentities = @( "14","9429000000031"),@("14", "9377778766249"),@("ZZ", "BidFood"),@("AS2Identity", "BidfoodAU_QA")
New-AzIntegrationAccountPartner -ResourceGroupName $RG -Name $IA -PartnerName $IAAccountPartner -PartnerType "B2B" -BusinessIdentities $BusinessIdentities
<#
$IAAccountPartner = "Baiada"
$BusinessIdentities = @("14","9377778014609"),@("AS2Identity","BaiadaTest")
New-AzIntegrationAccountPartner -ResourceGroupName $RG -Name $IA -PartnerName $IAAccountPartner -PartnerType "B2B" -BusinessIdentities $BusinessIdentities
.....more
Secondly configure agreements using AddNewAgreements-<env>.ps1. Once again to update you need to delete the agreement first.
#AddNewAgreements-UAT.ps1
param([String]$agreementdir)
$RG = "edi-uat-rg"
$IA = "edi-uat-ia"
#New-AzIntegrationAccountAgreement -Name $IA -ResourceGroupName $RG -AgreementName "BidfoodAU-BegaAU-AS2" -AgreementType "AS2" -GuestPartner "Bega" -HostPartner "BidfoodAU" -GuestIdentityQualifier "AS2Identity" -GuestIdentityQualifierValue "LIONQA" -HostIdentityQualifier "AS2Identity" -HostIdentityQualifierValue "BidfoodAU_QA" -AgreementContentFilePath ($agreementdir + "edi-supplier-biztalk-agreements-ia\BidfoodAU-BegaAU-AS2.json")
#New-AzIntegrationAccountAgreement -Name $IA -ResourceGroupName $RG -AgreementName "BidfoodAU-BegaAUCheese-EDI" -AgreementType "Edifact" -GuestPartner "Bega" -HostPartner "BidfoodAU" -GuestIdentityQualifier "14" -GuestIdentityQualifierValue "ID Hidden" -HostIdentityQualifier "14" -HostIdentityQualifierValue "ID Hidden" -AgreementContentFilePath ($agreementdir + "edi-supplier-biztalk-agreements-ia\BidfoodAU-BegaAUCheese-EDI.json")
.... more
Note that the script references an agreement file. Export this from the blade or craft from scratch. The file looks like JSON below. if you export the json representation from the blade please aware that json has to modified slightly to match what the Integration account REST API uses.
{
"aS2": {
"receiveAgreement": {
"protocolSettings": {
"messageConnectionSettings": {
"ignoreCertificateNameMismatch": false,
"supportHttpStatusCodeContinue": true,
"keepHttpConnectionAlive": true,
"unfoldHttpHeaders": true
},
"acknowledgementConnectionSettings": {
"ignoreCertificateNameMismatch": false,
"supportHttpStatusCodeContinue": false,
"keepHttpConnectionAlive": false,
"unfoldHttpHeaders": false
},
"mdnSettings": {
"needMDN": true,
"signMDN": true,
"sendMDNAsynchronously": false,
"receiptDeliveryUrl": "http://localhost",
"dispositionNotificationTo": "mark.brimble@bidone.co.nz",
"signOutboundMDNIfOptional": true,
"sendInboundMDNToMessageBox": false,
"micHashingAlgorithm": "SHA1"
},
"securitySettings": {
"overrideGroupSigningCertificate": false,
"enableNRRForInboundEncodedMessages": false,
"enableNRRForInboundDecodedMessages": false,
"enableNRRForOutboundMDN": false,
"enableNRRForOutboundEncodedMessages": false,
"enableNRRForOutboundDecodedMessages": false,
"enableNRRForInboundMDN": false,
"signingCertificateName": "B2BDDQA_begacheese_com_au",
"encryptionCertificateName": "bdirectedi.net"
},
"validationSettings": {
"overrideMessageProperties": true,
"encryptMessage": true,
"signMessage": false,
"compressMessage": false,
"checkDuplicateMessage": false,
"interchangeDuplicatesValidityDays": 5,
"checkCertificateRevocationListOnSend": false,
"checkCertificateRevocationListOnReceive": false,
"encryptionAlgorithm": "DES3"
},
"envelopeSettings": {
"messageContentType": "application/edifact",
"transmitFileNameInMimeHeader": false,
"fileNameTemplate": "%FILE.ReceivedFileName%",
"suspendMessageOnFileNameGenerationError": true,
"autogenerateFileName": false
},
"errorSettings": {
"suspendDuplicateMessage": false,
"resendIfMDNNotReceived": false
}
},
"senderBusinessIdentity": {
"qualifier": "AS2Identity",
"value": "Hidden"
},
"receiverBusinessIdentity": {
"qualifier": "AS2Identity",
"value": "Hidden"
}
},
"sendAgreement": {
"protocolSettings": {
"messageConnectionSettings": {
"ignoreCertificateNameMismatch": false,
"supportHttpStatusCodeContinue": true,
"keepHttpConnectionAlive": true,
"unfoldHttpHeaders": true
},
"acknowledgementConnectionSettings": {
"ignoreCertificateNameMismatch": false,
"supportHttpStatusCodeContinue": false,
"keepHttpConnectionAlive": false,
"unfoldHttpHeaders": false
},
"mdnSettings": {
"needMDN": true,
"signMDN": true,
"sendMDNAsynchronously": false,
"receiptDeliveryUrl": "http://localhost",
"dispositionNotificationTo": "mark.brimble@bidone.co.nz",
"signOutboundMDNIfOptional": true,
"sendInboundMDNToMessageBox": true,
"micHashingAlgorithm": "SHA1"
},
"securitySettings": {
"overrideGroupSigningCertificate": false,
"enableNRRForInboundEncodedMessages": false,
"enableNRRForInboundDecodedMessages": false,
"enableNRRForOutboundMDN": false,
"enableNRRForOutboundEncodedMessages": false,
"enableNRRForOutboundDecodedMessages": false,
"enableNRRForInboundMDN": false,
"signingCertificateName": "bdirectedi.net",
"encryptionCertificateName": "B2BDDQA_begacheese_com_au"
},
"validationSettings": {
"overrideMessageProperties": true,
"encryptMessage": false,
"signMessage": true,
"compressMessage": false,
"checkDuplicateMessage": false,
"interchangeDuplicatesValidityDays": 5,
"checkCertificateRevocationListOnSend": false,
"checkCertificateRevocationListOnReceive": false,
"encryptionAlgorithm": "DES3"
},
"envelopeSettings": {
"messageContentType": "application/edifact",
"transmitFileNameInMimeHeader": false,
"fileNameTemplate": "%FILE.ReceivedFileName%",
"suspendMessageOnFileNameGenerationError": true,
"autogenerateFileName": false
},
"errorSettings": {
"suspendDuplicateMessage": false,
"resendIfMDNNotReceived": false
}
},
"senderBusinessIdentity": {
"qualifier": "AS2Identity",
"value": "hidden"
},
"receiverBusinessIdentity": {
"qualifier": "AS2Identity",
"value": "hidden"
}
}
}
}
The EDIFACT agreement powershell and JSON file are a bit different.
#New-AzIntegrationAccountAgreement -Name $IA -ResourceGroupName $RG -AgreementName "BidfoodAU-SPSCommerceBegaAU-EDI" -AgreementType "Edifact" -GuestPartner "SPSCommerce" -HostPartner "BidfoodAU" -GuestIdentityQualifier "14" -GuestIdentityQualifierValue "value hidden" -HostIdentityQualifier "14" -HostIdentityQualifierValue "vakue hidden" -AgreementContentFilePath ($agreementdir + "edi-supplier-biztalk-agreements-ia\BidfoodAU-SPSCommerceBegaAU-EDI.json")
{
"edifact": {
"receiveAgreement": {
"protocolSettings": {
"validationSettings": {
"validateCharacterSet": true,
"checkDuplicateInterchangeControlNumber": false,
"interchangeControlNumberValidityDays": 30,
"checkDuplicateGroupControlNumber": false,
"checkDuplicateTransactionSetControlNumber": false,
"validateEDITypes": false,
"validateXSDTypes": false,
"trimLeadingAndTrailingSpacesAndZeroes": false,
"allowLeadingAndTrailingSpacesAndZeroes": false,
"trailingSeparatorPolicy": "NotAllowed"
},
"framingSettings": {
"ComponentSeparator": 58,
"CharacterEncoding": "",
"protocolVersion": 3,
"dataElementSeparator": 43,
"componentSeparator": 58,
"segmentTerminator": 39,
"releaseIndicator": 63,
"repetitionSeparator": 42,
"characterSet": "UNOC",
"decimalPointIndicator": "Decimal",
"segmentTerminatorSuffix": "None"
},
"envelopeSettings": {
"applyDelimiterStringAdvice": true,
"createGroupingSegments": false,
"enableDefaultGroupHeaders": true,
"interchangeControlNumberLowerBound": 1,
"interchangeControlNumberUpperBound": 999999999,
"rolloverInterchangeControlNumber": false,
"groupControlNumberLowerBound": 1,
"groupControlNumberUpperBound": 999999999,
"rolloverGroupControlNumber": false,
"overwriteExistingTransactionSetControlNumber": true,
"transactionSetControlNumberLowerBound": 1,
"transactionSetControlNumberUpperBound": 999999999,
"rolloverTransactionSetControlNumber": true,
"isTestInterchange": false,
"ApplicationReferenceId": "",
"CommunicationAgreementId": "",
"FunctionalGroupId": null,
"GroupApplicationPassword": null,
"GroupApplicationReceiverId": null,
"GroupApplicationReceiverQualifier": null,
"GroupApplicationSenderId": null,
"GroupApplicationSenderQualifier": null,
"GroupAssociationAssignedCode": null,
"GroupControllingAgencyCode": null,
"GroupControlNumberPrefix": null,
"GroupControlNumberSuffix": null,
"GroupMessageRelease": null,
"GroupMessageVersion": null,
"InterchangeControlNumberPrefix": null,
"InterchangeControlNumberSuffix": null,
"ProcessingPriorityCode": "",
"ReceiverInternalIdentification": "",
"ReceiverInternalSubIdentification": "",
"ReceiverReverseRoutingAddress": "",
"RecipientReferencePasswordQualifier": null,
"RecipientReferencePasswordValue": null,
"SenderInternalIdentification": "",
"SenderInternalSubIdentification": "",
"SenderReverseRoutingAddress": "",
"TransactionSetControlNumberPrefix": null,
"TransactionSetControlNumberSuffix": null
},
"acknowledgementSettings": {
"needTechnicalAcknowledgement": false,
"batchTechnicalAcknowledgements": true,
"needFunctionalAcknowledgement": false,
"batchFunctionalAcknowledgements": true,
"needLoopForValidMessages": true,
"sendSynchronousAcknowledgement": true,
"acknowledgementControlNumberLowerBound": 1,
"acknowledgementControlNumberUpperBound": 999999999,
"rolloverAcknowledgementControlNumber": true,
"AcknowledgementControlNumberPrefix": null,
"AcknowledgementControlNumberSuffix": null
},
"messageFilter": {
"messageFilterType": "Exclude"
},
"processingSettings": {
"maskSecurityInfo": true,
"preserveInterchange": false,
"suspendInterchangeOnError": false,
"createEmptyXmlTagsForTrailingSeparators": true,
"useDotAsDecimalSeparator": true
},
"envelopeOverrides": [],
"messageFilterList": [],
"schemaReferences": [{
"messageId": "ORDRSP",
"messageVersion": "D",
"messageRelease": "01B",
"associationAssignedCode": "EAN007",
"schemaName": "EFACT_D01B_ORDRSP_EAN007"
}, {
"messageId": "INVOIC",
"messageVersion": "D",
"messageRelease": "01B",
"associationAssignedCode": "EAN010",
"schemaName": "EFACT_D01B_INVOIC_EAN010"
}
],
"validationOverrides": [],
"edifactDelimiterOverrides": []
},
"senderBusinessIdentity": {
"qualifier": "14",
"value": "value hidden"
},
"receiverBusinessIdentity": {
"qualifier": "14",
"value": "value hidden"
}
},
"sendAgreement": {
"protocolSettings": {
"validationSettings": {
"validateCharacterSet": true,
"checkDuplicateInterchangeControlNumber": false,
"interchangeControlNumberValidityDays": 30,
"checkDuplicateGroupControlNumber": false,
"checkDuplicateTransactionSetControlNumber": false,
"validateEDITypes": false,
"validateXSDTypes": false,
"trimLeadingAndTrailingSpacesAndZeroes": false,
"allowLeadingAndTrailingSpacesAndZeroes": false,
"trailingSeparatorPolicy": "NotAllowed"
},
"framingSettings": {
"protocolVersion": 3,
"dataElementSeparator": 43,
"componentSeparator": 58,
"segmentTerminator": 39,
"releaseIndicator": 63,
"repetitionSeparator": 42,
"characterSet": "UNOC",
"decimalPointIndicator": "Decimal",
"segmentTerminatorSuffix": "None",
"ComponentSeparator": 58,
"CharacterEncoding": ""
},
"envelopeSettings": {
"applyDelimiterStringAdvice": true,
"createGroupingSegments": false,
"enableDefaultGroupHeaders": true,
"interchangeControlNumberLowerBound": 1,
"interchangeControlNumberUpperBound": 999999999,
"rolloverInterchangeControlNumber": false,
"groupControlNumberLowerBound": 1,
"groupControlNumberUpperBound": 999999999,
"rolloverGroupControlNumber": false,
"overwriteExistingTransactionSetControlNumber": true,
"transactionSetControlNumberLowerBound": 1,
"transactionSetControlNumberUpperBound": 999999999,
"rolloverTransactionSetControlNumber": true,
"isTestInterchange": false,
"ApplicationReferenceId": "",
"CommunicationAgreementId": "",
"FunctionalGroupId": null,
"GroupApplicationPassword": null,
"GroupApplicationReceiverId": null,
"GroupApplicationReceiverQualifier": null,
"GroupApplicationSenderId": null,
"GroupApplicationSenderQualifier": null,
"GroupAssociationAssignedCode": null,
"GroupControllingAgencyCode": null,
"GroupControlNumberPrefix": null,
"GroupControlNumberSuffix": null,
"GroupMessageRelease": null,
"GroupMessageVersion": null,
"InterchangeControlNumberPrefix": null,
"InterchangeControlNumberSuffix": null,
"ProcessingPriorityCode": "",
"ReceiverInternalIdentification": "",
"ReceiverInternalSubIdentification": "",
"ReceiverReverseRoutingAddress": "",
"RecipientReferencePasswordQualifier": null,
"RecipientReferencePasswordValue": null,
"SenderInternalIdentification": "",
"SenderInternalSubIdentification": "",
"SenderReverseRoutingAddress": "",
"TransactionSetControlNumberPrefix": null,
"TransactionSetControlNumberSuffix": null
},
"acknowledgementSettings": {
"needTechnicalAcknowledgement": false,
"batchTechnicalAcknowledgements": true,
"needFunctionalAcknowledgement": false,
"batchFunctionalAcknowledgements": true,
"needLoopForValidMessages": true,
"sendSynchronousAcknowledgement": true,
"acknowledgementControlNumberLowerBound": 1,
"acknowledgementControlNumberUpperBound": 999999999,
"rolloverAcknowledgementControlNumber": true,
"AcknowledgementControlNumberPrefix": null,
"AcknowledgementControlNumberSuffix": null
},
"messageFilter": {
"messageFilterType": "Exclude"
},
"processingSettings": {
"maskSecurityInfo": true,
"preserveInterchange": false,
"suspendInterchangeOnError": false,
"createEmptyXmlTagsForTrailingSeparators": true,
"useDotAsDecimalSeparator": true
},
"envelopeOverrides": [],
"messageFilterList": [],
"schemaReferences": [{
"messageId": "ORDERS",
"messageVersion": "D",
"messageRelease": "01B",
"associationAssignedCode": "EAN010",
"schemaName": "EFACT_D01B_ORDERS_EAN010"
}
],
"validationOverrides": [],
"edifactDelimiterOverrides": []
},
"senderBusinessIdentity": {
"qualifier": "14",
"value": "value hidden"
},
"receiverBusinessIdentity": {
"qualifier": "14",
"value": "value hidden"
}
}
}
}
The EDIFACT agreement contains a reference to the EDIFACT document type. This is a bit confusing for a novice because the Microsoft method to do this is not intuitive. Let's look at that line to understand this.
"schemaReferences": [{
"messageId": "ORDRSP",
"messageVersion": "D",
"messageRelease": "01B",
"associationAssignedCode": "EAN007",
"schemaName": "EFACT_D01B_ORDRSP_EAN007"
}, {
"messageId": "INVOIC",
"messageVersion": "D",
"messageRelease": "01B",
"associationAssignedCode": "EAN010",
"schemaName": "EFACT_D01B_INVOIC_EAN010"
}
],
"validationOverrides": [],
"edifactDelimiterOverrides": []
},
In an EDIFACT document, the UNH2.5 segment is used for used for schema lookup. You must use a schema to resolve inbound EDIFACT messages. Thus you must follow this Microsoft documentation to create and modify EDIFACT schemas. Note that the EDIFACT schemas that you can download from Microsoft require modification.
Conclusion
Using PowerShell scripting of agreements you can load these to an Azure integration account. This is reduces potential errors and is easier then configuring many agreements using the Azure Portal.