Invalid signature on SAML response using Spring Security SAML2 Azure - spring

I am having an issue trying to get SSO to work with Azure AD using SAML2. I have these properties set:
FYI, where there are "..."'s these are replacing the legitimate UUID's.
Dependencies:
Spring boot version is 2.7.0
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.security:spring-security-saml2-service-provider:5.7.2'
application.yaml
spring:
security:
saml2:
relyingparty:
registration:
SomeReg:
entity-id: SomeEntity
signing.credentials:
- private-key-location: 'classpath:saml/signingPriv.pem'
certificate-location: 'classpath:saml/signing.pem'
identityprovider:
entity-id: https://sts.windows.net/.../
verification.credentials:
- certificate-location: 'classpath:saml/AzureAD.cer'
singlesignon.url: 'https://login.microsoftonline.com/.../saml2'
singlesignon.sign-request: true
This is the response I have captured in SAML Trace:
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
ID="_295ce6a6-5964-440e-9842-03dac25e7cff"
Version="2.0"
IssueInstant="2022-08-07T02:00:33.331Z"
Destination="https://localhost:8443/login/saml2/sso/PhyCompSys"
InResponseTo="ARQ1acff8a-1488-4c17-8f69-c185aca3bd65"
>
<Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion">https://sts.windows.net/.../</Issuer>
<samlp:Status>
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />
</samlp:Status>
<Assertion xmlns="urn:oasis:names:tc:SAML:2.0:assertion"
ID="_e27b35ca-7a11-45a5-8ddb-182358f17800"
IssueInstant="2022-08-07T02:00:33.315Z"
Version="2.0"
>
<Issuer>https://sts.windows.net/.../</Issuer>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
<SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
<Reference URI="#_e27b35ca-7a11-45a5-8ddb-182358f17800">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
<DigestValue>hB9ZjSQ0SVYW57JhO3mKYQ7bN3gUgVNx2fOUB2NYq/Y=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>...</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>...</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
<Subject>
<NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">user#foo.com</NameID>
<SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<SubjectConfirmationData InResponseTo="ARQ1acff8a-1488-4c17-8f69-c185aca3bd65"
NotOnOrAfter="2022-08-07T03:00:33.221Z"
Recipient="https://localhost:8443/login/saml2/sso/SomeEntity"
/>
</SubjectConfirmation>
</Subject>
<Conditions NotBefore="2022-08-07T01:55:33.221Z"
NotOnOrAfter="2022-08-07T03:00:33.221Z"
>
<AudienceRestriction>
<Audience>SomeAudience</Audience>
</AudienceRestriction>
</Conditions>
<AttributeStatement>
<Attribute Name="http://schemas.microsoft.com/identity/claims/tenantid">
<AttributeValue>...</AttributeValue>
</Attribute>
<Attribute Name="http://schemas.microsoft.com/identity/claims/objectidentifier">
<AttributeValue>debe9fa9-dc1c-432a-b700-59ebf78549c2</AttributeValue>
</Attribute>
<Attribute Name="http://schemas.microsoft.com/identity/claims/displayname">
<AttributeValue>User Test</AttributeValue>
</Attribute>
<Attribute Name="http://schemas.microsoft.com/identity/claims/identityprovider">
<AttributeValue>https://sts.windows.net/.../</AttributeValue>
</Attribute>
<Attribute Name="http://schemas.microsoft.com/claims/authnmethodsreferences">
<AttributeValue>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</AttributeValue>
</Attribute>
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname">
<AttributeValue>Test</AttributeValue>
</Attribute>
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname">
<AttributeValue>Test</AttributeValue>
</Attribute>
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress">
<AttributeValue>user#foo.com</AttributeValue>
</Attribute>
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name">
<AttributeValue>user#foo.com</AttributeValue>
</Attribute>
</AttributeStatement>
<AuthnStatement AuthnInstant="2022-08-06T15:36:02.335Z"
SessionIndex="_e27b35ca-7a11-45a5-8ddb-182358f17800"
>
<AuthnContext>
<AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</AuthnContextClassRef>
</AuthnContext>
</AuthnStatement>
</Assertion>
</samlp:Response>
This results in this warning from OpenSAML:
Signature of Assertion '_e27b35ca-7a11-45a5-8ddb-182358f17800' from Issuer 'https://sts.windows.net/.../' was not valid
Which fails the login attempt.
I found one other post that suggested the issuer URL should be https://sts.windows.net/.../v2, I have tried that in the entity-id but OpenSAML always takes the value in the response to check the signature.
Has anyone else encountered this problem?

Related

How to set current time (-zone) for Logging?

I use for logging Microsoft.Extensions.Logging and NLog. The logs are written to Elasticsearch. When I look up my logs using Kibana all my logs are written at UT what means two houers different to my local time (-zone) MET. I would like to see my logs with my local time at Kibana. How can I adjust the time zone for logging?
I add the NLog.config:
<nlog autoReload="true" throwExceptions="false"
internalLogLevel="Info" internalLogFile="NLogError.log"
xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<targets>
<target name="Logfile" xsi:type="File"
fileName="${basedir}dap.log"
layout="${longdate} ${level} ${callsite} -> ${message} ${exception:format=Message,StackTrace}"
archiveFileName="${basedir}/archives/log.{#}.log"
archiveEvery="Day"
archiveNumbering="Rolling"
maxArchiveFiles="14"
keepFileOpen="false"
/>
<target xsi:type="Network"
name="CentralLog"
newLine ="false"
maxMessageSize="65000"
connectionCacheSize="5"
encoding="utf-8"
keepConnection="false"
maxQueueSize="100"
address="tcp://myurl.org:5544"
onOverflow="Split">
<layout type="JsonLayout">
<attribute name="machinename" layout="${machinename}" />
<attribute name="level" layout="${level:upperCase=true}" />
<attribute name="processname" layout="${processname}" />
<attribute name="processid" layout="${processid}" />
<attribute name="sendertimestamp" layout="${date:universalTime=true:format=yyyy-MM-ddTHH\:mm\:ss.fff}" />
<attribute name="module" layout="dhp DataPickerApi ${logger}" />
<attribute name="message" layout="${message}" />
<attribute name="exception" layout="${exception}" />
<attribute name="activityId" layout="${activityId}" />
</layout>
</target>
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="Logfile" />
<logger name="*" minlevel="Trace" writeTo="CentralLog"/>
</rules>
</nlog>
Don't use universalTime=true?
So instead of this:
<attribute name="sendertimestamp"
layout="${date:universalTime=true:format=yyyy-MM-ddTHH\:mm\:ss.fff}" />
Use this:
<attribute name="sendertimestamp"
layout="${date:format=yyyy-MM-ddTHH\:mm\:ss.fff}" />
You can set the timezone in the Kibana web.
Setting-->Advanced---> DateFormat:tz
to get more info : https://www.elastic.co/guide/en/kibana/current/advanced-options.html

Dynamics - How to get all appointments that for a specific user attends by Web Api

In Dynamics CRM, I'm trying to get all the appointments where a specific user is an attendee, using Web API. I know that I have to deal with Appointment entity and ActivityParty with activitypartytypemask equals 9 but really cannot figure out how to make it. How can identify the attendee ?
You can use FetchXml for your purpose. Check following Fetch:
<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="true">
<entity name="appointment">
<attribute name="subject" />
<attribute name="statecode" />
<attribute name="scheduledstart" />
<attribute name="scheduledend" />
<attribute name="regardingobjectid" />
<attribute name="activityid" />
<link-entity name="activityparty" from="activityid" to="activityid" alias="aa">
<filter type="and">
<condition attribute="participationtypemask" operator="in">
<value>6</value>
<value>5</value>
</condition>
<condition attribute="partyid" operator="eq" value="{9CE2BF21-408B-E611-80F3-C4346BAC7ABC}" />
</filter>
</link-entity>
</entity>
</fetch>
Using provided FetchXml and WebApi you should get the result you wanted. Url should look like following:
[Server Base Url]/api/data/v8.2/appointments?fetchXml=%3Cfetch%20version%3D%221.0%22%20output-format%3D%22xml-platform%22%20mapping%3D%22logical%22%20distinct%3D%22true%22%3E%3Centity%20name%3D%22appointment%22%3E%3Cattribute%20name%3D%22subject%22%20%2F%3E%3Cattribute%20name%3D%22statecode%22%20%2F%3E%3Cattribute%20name%3D%22scheduledstart%22%20%2F%3E%3Cattribute%20name%3D%22scheduledend%22%20%2F%3E%3Cattribute%20name%3D%22regardingobjectid%22%20%2F%3E%3Cattribute%20name%3D%22activityid%22%20%2F%3E%3Clink-entity%20name%3D%22activityparty%22%20from%3D%22activityid%22%20to%3D%22activityid%22%20alias%3D%22aa%22%3E%3Cfilter%20type%3D%22and%22%3E%3Ccondition%20attribute%3D%22participationtypemask%22%20operator%3D%22in%22%3E%3Cvalue%3E6%3C%2Fvalue%3E%3Cvalue%3E5%3C%2Fvalue%3E%3C%2Fcondition%3E%3Ccondition%20attribute%3D%22partyid%22%20operator%3D%22eq%22%20value%3D%22%7B9CE2BF21-408B-E611-80F3-C4346BAC7ABC%7D%22%20%2F%3E%3C%2Ffilter%3E%3C%2Flink-entity%3E%3C%2Fentity%3E%3C%2Ffetch%3E
This article contains additional details.

Request URL Too Long for fetchXml query types

I'm using CRM 2016 web api with fetchxml query parameter, but my query is too long it's simulate the IN operator were the number of parameters passed in the IN list are 300 elements and some times will be more than that.
So my problem is the query are too big for a GET HTTP Request. I have tried to send the query in the http message body but that didn't work so what is the solution for this problem?
Here's a code snippet of the fetchxml query that I used:
<fetch mapping="logical" distinct="true">
<entity name="entity">
<attribute name="new_classopportunityid" />
<attribute name="new_trainingproduct" />
<attribute name="new_gtgstatus" />
<attribute name="new_scheduledstartdate" />
<attribute name="new_scheduledenddate" />
<attribute name="new_remainingnumberofseats" />
<attribute name="new_liveclassroom" />
<attribute name="new_maxlive" />
<attribute name="new_xavieruniversity" />
<attribute name="new_partnerlive" />
<attribute name="new_blended" />
<filter>
<condition attribute="new_classopportunityid" operator="in">
<value>001943ea-e263-e611-8158-00155d002810</value>
<value>0071e4ea-bd9b-e611-8163-00155d002810</value>
<value>00c32774-1c8f-e611-8161-00155d002810</value>
<value>00d513fa-f0bb-e611-8169-00155d002810</value>
<value>....</value>
<value>....</value>
<value>....</value>
</condition>
</filter>
</entity>
</fetch>
The CRM web api endpoint that I request is :
GET http://<org>/api/data/v8.0/<entity>?fetchXml=<fetch mapping="logical" distinct="true">
<entity name="entity">
<attribute name="new_classopportunityid" />
<attribute name="new_trainingproduct" />
<attribute name="new_gtgstatus" />
<attribute name="new_scheduledstartdate" />
<attribute name="new_scheduledenddate" />
<attribute name="new_remainingnumberofseats" />
<attribute name="new_liveclassroom" />
<attribute name="new_maxlive" />
<attribute name="new_xavieruniversity" />
<attribute name="new_partnerlive" />
<attribute name="new_blended" />
<filter>
<condition attribute="new_classopportunityid" operator="in">
<value>001943ea-e263-e611-8158-00155d002810</value>
<value>0071e4ea-bd9b-e611-8163-00155d002810</value>
<value>00c32774-1c8f-e611-8161-00155d002810</value>
<value>00d513fa-f0bb-e611-8169-00155d002810</value>
<value>....</value>
<value>....</value>
<value>....</value>
</condition>
</filter>
</entity>
</fetch>
This is the response I got from the api.
Error code: 414: HTTP/1.1 414 Request-URI Too Long Response : "<!DOCTYPE HTML PUBLIC \"-\/\/W3C\/\/DTD HTML 4.01\/\/EN\"\"http:\/\/www.w3.org\/TR\/html4\/strict.dtd\">\r\n<HTML><HEAD><TITLE>Request URL Too Long<\/TITLE>\r\n<META HTTP-EQUIV=\"Content-Type\" Content=\"text\/html; charset=us-ascii\"><\/HEAD>\r\n<BODY><h2>Request URL Too Long<\/h2>\r\n<hr><p>HTTP Error 414. The request URL is too long.<\/p>\r\n<\/BODY><\/HTML>\r\n" [] []
You'll need to use a Post, not a Get:
https://dreamingincrm.com/2017/01/15/executing-large-fetchxml-with-webapi/
Using the "in" operator with a big list of ids is probably not the best way to query, as you've seen. It would be better if you could filter on an attribute of the new_classopportunity entity by using a link-entity, like this:
<fetch mapping="logical" distinct="true" >
<entity name="entity" >
<!-- ... all your attributes ... -->
<link-entity name="new_classopportunity" from="new_classopportunityid" to="new_classopportunityid" >
<attribute name="new_name" />
<filter>
<condition attribute="statecode" operator="eq" value="0" />
</filter>
</link-entity>
</entity>
</fetch>
Notice you can pull in attributes from the link-entity as well. In this case I'm pulling in name and using a filter to only get new_classopportunity records that are active.
If you don't have a field on new_classopportunity that you can filter on to get the same list, add one! :)

Passing a bearer token in a 'Web Test' without Visual Studio?

I want to import a ".webtest" in Azure's Application Insights availability feature. I dont have a test edition of Visual Studio, but this MSDN article suggests using Fiddler as another option to creating web tests.
I need to perform 2 requests on a REST API:
Request a bearer token from the connect/token endpoint.
Perform a GET at api/resources with the bearer token (retrieved from the above request) in the header.
It's a typical client credentials OAuth 2 flow.
I cannot seem to figure out how to do this with Fiddler. Basically I need to extract a value from the response body of request 1 and use it as the header value in request 2.
This is what the web test looks like without passing the token:
<?xml version="1.0" encoding="utf-8"?>
<TestCase Name="FiddlerGeneratedWebTest" Id="" Owner="" Description="" Priority="0" Enabled="True" CssProjectStructure="" CssIteration="" DeploymentItemsEditable="" CredentialUserName="" CredentialPassword="" PreAuthenticate="True" Proxy="" RequestCallbackClass="" TestCaseCallbackClass="">
<Items>
<Request Method="POST" Version="1.1" Url="https://example.com/connect/token" ThinkTime="8" Timeout="60" ParseDependentRequests="True" FollowRedirects="True" RecordResult="True" Cache="False" ResponseTimeGoal="0" Encoding="utf-8">
<Headers>
<Header Name="Content-Type" Value="application/x-www-form-urlencoded" />
</Headers>
<FormPostHttpBody ContentType="application/x-www-form-urlencoded">
<FormPostParameter Name="client_id" Value="myclientid" UrlEncode="True" />
<FormPostParameter Name="client_secret" Value="password123" UrlEncode="True" />
<FormPostParameter Name="grant_type" Value="client_credentials" UrlEncode="True" />
<FormPostParameter Name="scope" Value="myscopes" UrlEncode="True" />
</FormPostHttpBody>
</Request>
<Request Method="GET" Version="1.1" Url="https://example.com/api/resources" ThinkTime="0" Timeout="60" ParseDependentRequests="True" FollowRedirects="True" RecordResult="True" Cache="False" ResponseTimeGoal="0" Encoding="utf-8">
<Headers>
<Header Name="Authorization" Value="Bearer {{token}}" />
</Headers>
</Request>
</Items>
</TestCase>
Assuming this comes back as the following example you can use a regex extraction to get it.
{"token_type":"Bearer","scope":"user_impersonation","expires_in":"3600 ... "access_token":"{{TOKEN}}", ...}
<?xml version="1.0" encoding="utf-8"?>
<TestCase Name="FiddlerGeneratedWebTest" Id="" Owner="" Description="" Priority="0" Enabled="True" CssProjectStructure="" CssIteration="" DeploymentItemsEditable="" CredentialUserName="" CredentialPassword="" PreAuthenticate="True" Proxy="" RequestCallbackClass="" TestCaseCallbackClass="">
<Items>
<Request Method="POST" Version="1.1" Url="https://example.com/connect/token" ThinkTime="8" Timeout="60" ParseDependentRequests="True" FollowRedirects="True" RecordResult="True" Cache="False" ResponseTimeGoal="0" Encoding="utf-8">
<ExtractionRules>
<ExtractionRule Classname="Microsoft.VisualStudio.TestTools.WebTesting.Rules.ExtractRegularExpression, Microsoft.VisualStudio.QualityTools.WebTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" VariableName="token" DisplayName="Extract Regular Expression" Description="Extract text from the response matching a regular expression and place it into the test context.">
<RuleParameters>
<RuleParameter Name="RegularExpression" Value=".*"access_token":"([^"]*)".*" />
<RuleParameter Name="IgnoreCase" Value="True" />
<RuleParameter Name="Required" Value="True" />
<RuleParameter Name="Index" Value="0" />
<RuleParameter Name="HtmlDecode" Value="True" />
<RuleParameter Name="UseGroups" Value="True" />
</RuleParameters>
</ExtractionRule>
</ExtractionRules>
<Headers>
<Header Name="Content-Type" Value="application/x-www-form-urlencoded" />
</Headers>
<FormPostHttpBody ContentType="application/x-www-form-urlencoded">
<FormPostParameter Name="client_id" Value="myclientid" UrlEncode="True" />
<FormPostParameter Name="client_secret" Value="password123" UrlEncode="True" />
<FormPostParameter Name="grant_type" Value="client_credentials" UrlEncode="True" />
<FormPostParameter Name="scope" Value="myscopes" UrlEncode="True" />
</FormPostHttpBody>
</Request>
<Request Method="GET" Version="1.1" Url="https://example.com/api/resources" ThinkTime="0" Timeout="60" ParseDependentRequests="True" FollowRedirects="True" RecordResult="True" Cache="False" ResponseTimeGoal="0" Encoding="utf-8">
<Headers>
<Header Name="Authorization" Value="Bearer {{token}}" />
</Headers>
</Request>
</Items>
</TestCase>
To compliment James Davis's answer, if you need to login to https://yourapp.com/auth/login by posting the JSON:
{
user: 'youruser',
password: 'yourpassword'
}
first base64 encode the json:
> echo "{user: 'youruser', password: 'yourpassword'}" | base64
e3VzZXI6ICd5b3VydXNlcicsIHBhc3N3b3JkOiAneW91cnBhc3N3b3JkJ30K
Then pass this base64 value in a StringHttpBody tag
<?xml version="1.0" encoding="utf-8"?>
<WebTest Name="login-healthcheck" Id="e91b6e1d-3fa0-475f-a18b-b694b463589c" Owner="" Priority="0" Enabled="True" CssProjectStructure="" CssIteration="" Timeout="0" WorkItemIds="" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010" Description="" CredentialUserName="" CredentialPassword="" PreAuthenticate="True" Proxy="default" StopOnError="False" RecordedResultFile="" ResultsLocale="">
<Items>
<Request Method="POST" Guid="ef9d1d00-5663-476a-a3cb-ccf49c4d2229" Version="1.1" Url="https://yourapp.com/auth/login" ThinkTime="8" Timeout="60" ParseDependentRequests="True" FollowRedirects="True" RecordResult="True" Cache="False" ResponseTimeGoal="0" Encoding="utf-8" ExpectedHttpStatusCode="0" ExpectedResponseUrl="" ReportingName="" IgnoreHttpStatusCode="False">
<Headers>
<Header Name="Content-Type" Value="application/json" />
</Headers>
<ExtractionRules>
<ExtractionRule Classname="Microsoft.VisualStudio.TestTools.WebTesting.Rules.ExtractRegularExpression, Microsoft.VisualStudio.QualityTools.WebTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" VariableName="token" DisplayName="Extract Regular Expression" Description="Extract text from the response matching a regular expression and place it into the test context.">
<RuleParameters>
<RuleParameter Name="RegularExpression" Value=".*"access_token":"([^"]*)".*" />
<RuleParameter Name="IgnoreCase" Value="True" />
<RuleParameter Name="Required" Value="True" />
<RuleParameter Name="Index" Value="0" />
<RuleParameter Name="HtmlDecode" Value="True" />
<RuleParameter Name="UseGroups" Value="True" />
</RuleParameters>
</ExtractionRule>
</ExtractionRules>
<StringHttpBody ContentType="application/json" InsertByteOrderMark="False">e3VzZXI6ICd5b3VydXNlcicsIHBhc3N3b3JkOiAneW91cnBhc3N3b3JkJ30K</StringHttpBody>
</Request>
<Request Method="GET" Guid="d566422f-af74-47bf-90aa-0c66db6ef567" Version="1.1" Url="https://yourapp.com/api/v1/healthcheck" ThinkTime="0" Timeout="60" ParseDependentRequests="True" FollowRedirects="True" RecordResult="True" Cache="False" ResponseTimeGoal="0" Encoding="utf-8" ExpectedHttpStatusCode="0" ExpectedResponseUrl="" ReportingName="" IgnoreHttpStatusCode="False">
<Headers>
<Header Name="Authorization" Value="Bearer {{token}}" />
</Headers>
</Request>
</Items>
</WebTest>
Worked for me on Azure Application Insights Availability checking

View Showing Accounts that don't have contact

I want to create two views.
- One view showing all accounts having contacts. It is easy. I don't have any issue with this.
- Second View Showing All Accounts don't have any contact.
As we can't specify such condition for second view in advance find. Is there any way we can achieve this using Views?
I don't want to create SSRS report or any custom Development.
Please let me know if this is achievable.
You can achieve this only by modifying the Account entity customization xml.
Create a new (system) view for Account and name it "Active Accounts without Contacts".
Create a (unmanaged) solution for export and add the Account entity without any dependencies.
Export the solution and unpack the zip archive.
Open the customization.xml with the editor of your choice.
Modify the views FetchXml as follows:
before
...
<fetchxml>
<fetch version="1.0" output-format="xml-platform" mapping="logical">
<entity name="account">
<attribute name="accountid" />
<order attribute="name" descending="false" />
</entity>
</fetch>
</fetchxml>
<IntroducedVersion>1.0.0.0</IntroducedVersion>
<LocalizedNames>
<LocalizedName description="Active Accounts without Contacts" languagecode="1033" />
</LocalizedNames>
<Descriptions>
<Description description="Active Accounts without Contacts" languagecode="1033" />
</Descriptions>
...
after
<fetchxml>
<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="true">
<entity name="account">
<attribute name="accountid" />
<order attribute="name" descending="false" />
<link-entity name="contact" from="parentcustomerid" to="accountid" link-type="outer"/>
<filter type="and">
<condition attribute="parentcustomerid" operator="null" />
</filter>
</entity>
</fetch>
</fetchxml>
<IntroducedVersion>1.0.0.0</IntroducedVersion>
<LocalizedNames>
<LocalizedName description="Active Accounts without Contacts" languagecode="1033" />
</LocalizedNames>
<Descriptions>
<Description description="Active Accounts without Contacts" languagecode="1033" />
</Descriptions>
...
Finally, re-package the solution, import and publish.
I could not get this to work, and after quite a bit of "tinkering" altered the fetchxml as follows and it works! I basically moved the filter to before the link-entity detail. This is on CRM2013 with Rollup 1.
<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="true" >
<entity name="account" >
<attribute name="address1_city" />
<filter type="and" >
<condition entityname="contact" attribute="parentcustomerid" operator="null" />
</filter>
<link-entity name="contact" from="parentcustomerid" to="accountid" link-type="outer" />
<attribute name="primarycontactid" />
<order attribute="name" descending="false" />
<attribute name="telephone1" />
<attribute name="accountid" />
</entity>
</fetch>

Resources