Extend a Custom Apache Knox Service to query multiple HBase tables - apache

I'm currently working on extending the functionality of Apache Knox interacting with HBase on HDP 2.3.2. I've created a new gateway on Apache Knox called Decode, to query HBase. The Decode Gateway was built using the HBase gateway as a template. Topologies have been edited such that the following query:
curl -ku admin:admin-password -H "Accept: application/json" https://sandbox.hortonworks.com:8443/gateway/default/decode/hbase/MyHBaseTable/HBaseRowKey123*
Will return the data from Row 123 (In Base 64)
Is there way to change the Decode gateway's rewrite.xml and service.xml so that the query would not need to go through Hbase, e.g:
curl -ku admin:admin-password -H "Accept: application/json" https://sandbox.hortonworks.com:8443/gateway/default/decode/MyHBaseTable/HBaseRowKey123*
I understand this may sound strange to not use in inbuilt HBase gateway but the overall aim is to extend the Decode gateway such that It would be able to query multiple tables and/or multiple rows of data from HBase, rather than one row at a time.
Currently my Decode rewrite.xml is:
<rules>
<rule dir="IN" name="DECODE/decode/inbound" pattern="*://*:*/**/decode/{path=**}?{**}">
<rewrite template="{$serviceUrl[DECODE]}/{path=**}?{**}"/>
</rule>
<rule dir="IN" name="DECODE/decode/inbound" pattern="*://*:*/**/decode{**}">
<rewrite template="{$serviceUrl[DECODE]}/{path=**}?{**}"/>
</rule>
<filter name="WEBHBASE/webhbase/status/outbound">
<content type="*/json">
<apply path="$[LiveNodes][*][name]" rule="WEBHBASE/webhbase/address/outbound"/>
</content>
<content type="*/xml">
<apply path="/ClusterStatus/LiveNodes/Node/#name" rule="WEBHBASE/webhbase/address/outbound"/>
</content>
</filter>
</rules>
and the service.xml:
<service role="DECODE" name="decode" version="0.0.1">
<routes>
<route path="/decode/**"/>
<route path="/decode/?**">
<rewrite apply="WEBHBASE/webhbase/headers/outbound" to="response.headers"/>
</route>
<route path="/decode/**?**">
<rewrite apply="WEBHBASE/webhbase/headers/outbound" to="response.headers"/>
</route>
<route path="/decode/status/cluster?**">
<rewrite apply="WEBHBASE/webhbase/status/outbound" to="response.body"/>
</route>
<route path="/decode/*/regions?**">
<rewrite apply="WEBHBASE/webhbase/regions/outbound" to="response.body"/>
</route>
</routes> <dispatch classname="org.apache.hadoop.gateway.hbase.HBaseDispatch"/> </service>

Just like #lmccay I don't see anything necessarily wrong with what you have shown so I decided to try it for myself.
In the default topology file I copied the WEBHBASE service to a DECODE service as shown.
/usr/hdp/current/knox-server/conf/topologies/default.xml
<service>
<role>WEBHBASE</role>
<url>http://my-hbase-hostname:60080</url>
</service>
<service>
<role>DECODE</role>
<url>http://my-hbase-hostname:60080</url>
</service>
I then copied the hbase service.xml and rewrite.xml from
/usr/hdp/current/knox-server/data/services/hbase/0.98.0
to a new directory
/usr/hdp/current/knox-server/data/services/decode/0.0.1
and modified them to look like the versions shown below. I basically just replaced all occurrences of hbase with decode using the matching case.
/usr/hdp/current/knox-server/data/services/decode/0.0.1/service.xml
<service role="DECODE" name="decode" version="0.0.1">
<routes>
<route path="/decode/?**">
<rewrite apply="DECODE/decode/headers/outbound" to="response.headers"/>
</route>
<route path="/decode/**?**">
<rewrite apply="DECODE/decode/headers/outbound" to="response.headers"/>
</route>
<route path="/decode/status/cluster?**">
<rewrite apply="DECODE/decode/status/outbound" to="response.body"/>
</route>
<route path="/decode/*/regions?**">
<rewrite apply="DECODE/decode/regions/outbound" to="response.body"/>
</route>
</routes>
<dispatch classname="org.apache.hadoop.gateway.hbase.HBaseDispatch"/>
<testURLs>
<testURL>/decode/version</testURL>
<testURL>/decode/version/cluster</testURL>
<testURL>/decode/status/cluster</testURL>
<testURL>/decode</testURL>
</testURLs>
</service>
/usr/hdp/current/knox-server/data/services/decode/0.0.1/rewrite.xml
<rules>
<rule dir="IN" name="DECODE/decode/root/inbound" pattern="*://*:*/**/decode/?{**}">
<rewrite template="{$serviceUrl[DECODE]}/?{**}"/>
</rule>
<rule dir="IN" name="DECODE/decode/path/inbound" pattern="*://*:*/**/decode/{path=**}?{**}">
<rewrite template="{$serviceUrl[DECODE]}/{path=**}?{**}"/>
</rule>
<rule name="DECODE/decode/location/outbound">
<match pattern="*://*:*/{path=**}?{**}"/>
<rewrite template="{$frontend[url]}/decode/{path=**}?{**}"/>
</rule>
<rule name="DECODE/decode/address/outbound">
<match pattern="{host}:{port}"/>
<rewrite template="{$frontend[url]}/hbase-region?host={host}?port={port}"/>
<encrypt-query/>
</rule>
<filter name="DECODE/decode/headers/outbound">
<content type="application/x-http-headers">
<apply path="Location" rule="DECODE/decode/location/outbound"/>
</content>
</filter>
<filter name="DECODE/decode/status/outbound">
<content type="*/json">
<apply path="$[LiveNodes][*][name]" rule="DECODE/decode/address/outbound"/>
</content>
<content type="*/xml">
<apply path="/ClusterStatus/LiveNodes/Node/#name" rule="DECODE/decode/address/outbound"/>
</content>
</filter>
<filter name="DECODE/decode/regions/outbound">
<content type="*/json">
<apply path="$[Region][*][location]" rule="DECODE/decode/address/outbound"/>
</content>
<content type="*/xml">
<apply path="/TableInfo/Region/#location" rule="DECODE/decode/address/outbound"/>
</content>
</filter>
</rules>
I was then able to query a table with the curl command below. This does not contain hbase in the URL I believe answering your question.
curl -k -u guest:******** -H 'Accept: application/json' https://localhost:8443/gateway/default/decode/t1/*
{"Row":[{"key":"ZjE6djE=","Cell":[{"column":"ZjI6djI=","timestamp":1453139991995,"$":"ZjM6djM="}]}]}

Related

Reverse Proxy to HTTP server via IIS with SSL

web.config
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="ReverseProxyApi" stopProcessing="true">
<match url="api/(.*)" />
<action type="Rewrite" url="http://localhost:3000/{R:1}" />
</rule>
<rule name="ReverseProxyClient" enabled="true" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{CACHE_URL}" pattern="^(.+)://" />
</conditions>
<action type="Rewrite" url="{C:1}://localhost:3001/{R:1}" />
<serverVariables>
<set name="HTTP_SEC_WEBSOCKET_EXTENSIONS" value="" />
</serverVariables>
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
I have successfully created a reverse proxy from http://localhost:9999 to my http://localhost:3000 (NestJS api server) and http://localhost:3001 (NextJS client server) using the above config in rewrite url.
My problem is that I am geting an error when I tried to bind https://localhost:8888 to the same site. I made sure that the https url is in the site bindings. I also have a self signed ssl certificate with it.
This is the error I am getting:
As you can see here https://localhost:8888 is in the site bindings
This is self signed certificate that I am using
I have no idea what is wrong in my setup. I have tried to restart both the website and the whole IIS server but I am getting the same error.
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="ReverseProxyApi" stopProcessing="true">
<match url="api/(.*)" />
<action type="Rewrite" url="http://localhost:3000/{R:1}" />
</rule>
<rule name="ReverseProxyClient" enabled="true" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{CACHE_URL}" pattern="^(.+)://" />
</conditions>
<action type="Rewrite" url="{MapProtocol:{C:1}}://localhost:3001/{R:1}" />
<serverVariables>
<set name="HTTP_SEC_WEBSOCKET_EXTENSIONS" value="" />
</serverVariables>
</rule>
</rules>
<rewriteMaps>
<rewriteMap name="MapProtocol">
<add key="https" value="http" />
<add key="wss" value="ws" />
</rewriteMap>
</rewriteMaps>
</rewrite>
</system.webServer>
</configuration>
This web config works. I think what was wrong in my previous config is that https://localhost:8888 is redirected to https://localhost:3001 which does not exist (because of the {C:1}).
With this new config:
ws:// or wss:// -> ws://
http:// or https:// -> http://

signalR Core + ARR3 Reverse Proxy: Handshake Timeouts

Im using .net core 3.1 in an docker environment pointing an IIS Reverse Proxy with ARR installed to it.
Update
I managed to get the rewriting running. BNut since I dont know why it works this way Im unable to answer this question.
I changed the rewrite rules from localhost: to 127.0.0.1:
Now the handshake works. But it seems not work with websocket protocol only with ServerSentEvents.
Error: Failed to start the transport 'WebSockets': Error: WebSocket failed to connect. The connection could not be found on the server, either the endpoint may not be a SignalR endpoint, the connection ID is not present on the server, or there is a proxy blocking WebSockets. If you have multiple servers check that sticky sessions are enabled.
But Websockets are installed. Im using ARR3.
So the last 2 questions in this for me are:
Why did it work with the IP instead of localhost? (Full config below)
Why does it throw this error even WS is installed?
Full Rewrite config:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<urlCompression doStaticCompression="false" doDynamicCompression="false" />
<rewrite>
<rules>
<rule name="ReverseProxyInboundRule1" stopProcessing="true">
<match url="wss://(.*)" />
<action type="Rewrite" url="wss://127.0.0.1:3101/{R:1}" />
</rule>
<rule name="ReverseProxyInboundRule2" stopProcessing="true">
<match url="(.*)" />
<action type="Rewrite" url="https://127.0.0.1:3101/{R:1}" />
</rule>
</rules>
<outboundRules>
<rule name="ReverseProxyOutboundRule1" preCondition="ResponseIsHtml1">
<match filterByTags="A, Form, Img" pattern="^http(s)?://127.0.0.1:3101/(.*)" />
<action type="Rewrite" value="http{R:1}://sub.example.com/{R:2}" />
</rule>
<preConditions>
<preCondition name="ResponseIsHtml1">
<add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/html" />
</preCondition>
</preConditions>
</outboundRules>
</rewrite>
</system.webServer>
</configuration>
EDIT
Thanks to Bruce Zhang I got to the source of the problem but still not Idea how to fix it.
Ive got an docker environment running via docker compose on a windows server.
There I use IIS10 with UrlRewrite and ARR3 together with an .net core 3.1 app and signalR core.
As Client I use the typescript version of #microsoft/signalr (latest)
For some reasons I dont know the Connection is ok but the handshake call ends in an timeout.
I looked at the net for some solutions and applied this so far:
Added URL Rewrite Inbound Rules for wss:// and ws://
Increased the timeouts for signalR
Configured the response buffer in ARR (see picture below)
Enabled failed request tracing
The docker env is running on the same server as the IIS with enabled ARR and Websockets Feature.
The Web-App container exposes port 6652 mapping it to port 443 in the docker container.
My rewrite rule are defined as below:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<urlCompression doStaticCompression="false" doDynamicCompression="false" />
<rewrite>
<rules>
<rule name="WS reverse proxy" stopProcessing="true">
<match url="ws://devlocal.example.com" />
<conditions>
<add input="{CACHE_URL}" pattern="^(.+)://" />
</conditions>
<action type="Rewrite" url="{C:1}://127.0.0.1:6652" />
</rule>
<rule name="WSS reverse proxy" stopProcessing="true">
<match url="wss://devlocal.example.com" />
<conditions>
<add input="{CACHE_URL}" pattern="^(.+)://" />
</conditions>
<action type="Rewrite" url="{C:1}://127.0.0.1:6652" />
</rule>
<rule name="_Inbound_devlocal.example.com.com" stopProcessing="true">
<match url="(.*)" />
<action type="Rewrite" url="{C:1}://localhost:6652/{R:1}" logRewrittenUrl="true" />
<conditions logicalGrouping="MatchAny">
<add input="{CACHE_URL}" pattern="^(.+)://" />
<add input="{HTTP_HOST}" pattern="^devlocal\.example.com\.com$" />
</conditions>
</rule>
</rules>
<outboundRules>
<rule name="_Outboundund_devlocal.example.com.com" stopProcessing="true">
<match filterByTags="A, Form, Img, Link, Script" pattern="^http(s)?://localhost:6652/(.*)" />
<action type="Rewrite" value="http{R:1}://devlocal.example.com.com/{R:2}" />
</rule>
</outboundRules>
</rewrite>
</system.webServer>
</configuration>
SignalR configured as:
services.AddSignalR(hubOptions =>
{
hubOptions.ClientTimeoutInterval = TimeSpan.FromSeconds(240);
hubOptions.HandshakeTimeout = TimeSpan.FromSeconds(120);
hubOptions.KeepAliveInterval = TimeSpan.FromSeconds(60);
hubOptions.EnableDetailedErrors = true;
hubOptions.MaximumReceiveMessageSize = 200;
hubOptions.StreamBufferCapacity = 300;
});
// Mappig hub like:
app.UseEndpoints(api =>
{
api.MapControllers();
api.MapHub<CommentsHub>("/sockR/hub");
}
);
The ARR Config:
The trace log of the signalR client shows that its the handshake call thats ends in an timeout:
[2022-01-13T18:29:07.232Z] Information: Normalizing '/sockR/hub' to 'https://devlocal.example.com/sockR/hub'.
Utils.js:151 [2022-01-13T18:29:07.233Z] Debug: Starting HubConnection.
Utils.js:151 [2022-01-13T18:29:07.233Z] Debug: Starting connection with transfer format 'Text'.
Utils.js:147 [2022-01-13T18:29:07.342Z] Information: WebSocket connected to wss://devlocal.example.com/sockR/hub.
Utils.js:151 [2022-01-13T18:29:07.342Z] Debug: The HttpConnection connected successfully.
Utils.js:151 [2022-01-13T18:29:07.342Z] Debug: Sending handshake request.
Utils.js:147 [2022-01-13T18:29:07.342Z] Information: Using HubProtocol 'json'.
... After 3 minutes:
ERROR Error: Uncaught (in promise): Error: Server timeout elapsed without receiving a message from the server. Error: Server timeout elapsed without receiving a message from the server.
Is there any way to debug why the request is ending in an timeout? The strange thing is Ive got also an jira instance on the server.Also bound via revers proxy with same settings and the WSS/WS calls there dont fail.
Apperently it works now by removing:
Startup.cs
app.UseWebSockets();
And after changing my rewrite config to:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<urlCompression doStaticCompression="false" doDynamicCompression="false" />
<rewrite>
<rules>
<rule name="ReverseProxyInboundRule1" stopProcessing="true">
<match url="wss://(.*)" />
<action type="Rewrite" url="wss://127.0.0.1:3101/{R:1}" />
</rule>
<rule name="ReverseProxyInboundRule2" stopProcessing="true">
<match url="(.*)" />
<action type="Rewrite" url="https://127.0.0.1:3101/{R:1}" />
</rule>
</rules>
<outboundRules>
<rule name="ReverseProxyOutboundRule1" preCondition="ResponseIsHtml1">
<match filterByTags="A, Form, Img" pattern="^http(s)?://127.0.0.1:3101/(.*)" />
<action type="Rewrite" value="http{R:1}://sub.example.com/{R:2}" />
</rule>
<preConditions>
<preCondition name="ResponseIsHtml1">
<add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/html" />
</preCondition>
</preConditions>
</outboundRules>
</rewrite>
</system.webServer>
</configuration>

React to IIS always doing redirect

export default ({ childProps }) => (
<Switch>
<AuthenticatedRoute exact path={'/'} component={Home} props={childProps} />
<UnauthenticatedRoute exact path={'/login'} component={Login} props={childProps} />
<UnauthenticatedRoute path={"/autolink/:userId/:tempKey"} component={AutoLink} props={childProps} />
</Switch>
);
<rewrite>
<rules>
<rule name="React Routes" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<add input="{REQUEST_URI}" pattern="^/(api)" negate="true" />
</conditions>
<action type="Rewrite" url="/merchant-client" />
</rule>
</rules>
</rewrite>
Whenever I try to go to the autolink/:userId/:tempKey route it always redirects me to the home which by default loads the /merchant-client/login page.
It's weird because it works fine when I run this locally in WebStorm and GoLand, but once I had to move this to IIS it doesn't work. I had to add the URL Rewrite rule for it resolved the issue when you refresh the page it caused it to crash.

Shibboleth Errors When Authenticating Through a Reverse Proxy

I am attempting to configure a new Shibboleth based SP that will authenticate via my SAML iDP (Duo Access Gateway).
My Shibboleth SP is running behind an IIS-based reverse proxy that rewrites the URL's to the SP. The SP and Shibboleth itself are running on Apache on a Windows Server.
The issue with this configuration is that my SP (Shibboleth) believes it's running on, let's call it "sp.mycompany.com". However my iDP is delivering the assertion to the reverse proxy address "proxy.mycompany.com" which then rewrites the request to "sp.mycompany.com". This results in Sibboleth throwing the error "SAML message delivered with POST to incorrect server URL" to the user, and logging an error of "POST targeted at (https://proxy.mycompany.com/Shibboleth.sso/SAML2/POST), but delivered to (http://sp.mycompany.com/Shibboleth.sso/SAML2/POST)" in the Shibd log.
I've been searching but have only found fixes for this that apply to different situations than mine.
EDIT: Reverse Proxy Config Added Below
`<configuration>
<system.webS<rewrite>
<outboundRules>
<clear />
<rule name="Duo" enabled="true" stopProcessing="true">
<match filterByTags="None" pattern="^Shibboleth.sso/(.*)" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="true" />
<action type="Rewrite" value="https://proxy.mycompany.com/{R:0}" />
</rule>
<rule name="ReverseProxyOutboundRule1" preCondition="ResponseIsHtml1" enabled="true">
<match filterByTags="A, Form, Img" pattern="^http(s)?://sp.mycompany.com/(.*)" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="true" />
<action type="Rewrite" value="http{R:1}://proxy.mycompany.com/{R:2}" />
</rule>
<preConditions>
<preCondition name="ResponseIsHtml1">
<add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/html" />
</preCondition>
</preConditions>
</outboundRules>
<rules>
<clear />
<rule name="Duo" enabled="true" stopProcessing="true">
<match url="^dag/(.*)" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
<action type="Rewrite" url="https://duo.mycompany.com/{R:0}" appendQueryString="true" logRewrittenUrl="true" />
</rule>
<rule name="ReverseProxyInboundRule1" enabled="true" stopProcessing="true">
<match url="(.*)" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
<action type="Rewrite" url="http://sp.mycompany.com/{R:1}" logRewrittenUrl="true" />
</rule>
</rules>
<rewriteMaps>
<rewriteMap name="test" />
</rewriteMaps>
</rewrite>
<httpRedirect enabled="false" destination="https://proxy.mycompany.com/dag" />
</system.webServer>
</configuration>`

FxCop, exclude a rule from an assembly (but use it for the other assemblies)

I would like to exclude CA1822:MarkMembersAsStatic from the CoreTest assembly as the NUnit test methods cannot be converted to static methods as NUnit won´t execute them if I do. In the other assemblies I would like to have this rule as I have found it valuable.
If it is possible I do not like to add a SuppressMessage to each test methods, as I have a lot of them and it just clutters up the file.
This is the FxCop rule XML-file:
<?xml version="1.0" encoding="utf-8"?>
<FxCopProject Version="1.35" Name="Foo, Release">
<ProjectOptions>
<SharedProject>True</SharedProject>
<Stylesheet Apply="False">http://www.gotdotnet.com/team/fxcop//xsl/1.35/FxCopReport.xsl</Stylesheet>
<SaveMessages>
<Project Status="None" NewOnly="False" />
<Report Status="Active" NewOnly="False" />
</SaveMessages>
<ProjectFile Compress="True" DefaultTargetCheck="True" DefaultRuleCheck="True" SaveByRuleGroup="" Deterministic="True" />
<EnableMultithreadedLoad>True</EnableMultithreadedLoad>
<EnableMultithreadedAnalysis>True</EnableMultithreadedAnalysis>
<SourceLookup>True</SourceLookup>
<AnalysisExceptionsThreshold>10</AnalysisExceptionsThreshold>
<RuleExceptionsThreshold>1</RuleExceptionsThreshold>
<Spelling Locale="en-us" />
<VersionAware>False</VersionAware>
<OverrideRuleVisibilities>False</OverrideRuleVisibilities>
<CustomDictionaries SearchFxCopDir="True" SearchUserProfile="True" SearchProjectDir="True" />
<SearchGlobalAssemblyCache>False</SearchGlobalAssemblyCache>
<DeadlockDetectionTimeout>120</DeadlockDetectionTimeout>
</ProjectOptions>
<Targets>
<AssemblyReferenceDirectories>
<Directory>$(ProjectDir)/Library/EPiServer CMS/5.2.375.7/</Directory>
<Directory>$(ProjectDir)/Foo.Plugin/bin/Release/</Directory>
</AssemblyReferenceDirectories>
<Target Name="$(ProjectDir)/Foo.Core/bin/Release/Foo.Core.dll" Analyze="True" AnalyzeAllChildren="True" />
<Target Name="$(ProjectDir)/Foo.CoreTest/bin/Release/Foo.CoreTest.dll" Analyze="True" AnalyzeAllChildren="True" />
<Target Name="$(ProjectDir)/Foo.Example/bin/Foo.Example.dll" Analyze="True" AnalyzeAllChildren="True" />
<Target Name="$(ProjectDir)/Foo.Web.WebForms/bin/Release/Foo.Web.WebForms.dll" Analyze="True" AnalyzeAllChildren="True" />
</Targets>
<Rules>
<RuleFiles>
<RuleFile Name="$(FxCopDir)\Rules\DesignRules.dll" Enabled="True" AllRulesEnabled="True" />
<RuleFile Name="$(FxCopDir)\Rules\GlobalizationRules.dll" Enabled="True" AllRulesEnabled="False">
<Rule Name="AvoidDuplicateAccelerators" Enabled="True" />
<Rule Name="DoNotHardcodeLocaleSpecificStrings" Enabled="True" />
<Rule Name="SetLocaleForDataTypes" Enabled="True" />
<Rule Name="SpecifyCultureInfo" Enabled="True" />
<Rule Name="SpecifyIFormatProvider" Enabled="True" />
<Rule Name="SpecifyMessageBoxOptions" Enabled="True" />
</RuleFile>
<RuleFile Name="$(FxCopDir)\Rules\InteroperabilityRules.dll" Enabled="True" AllRulesEnabled="True" />
<RuleFile Name="$(FxCopDir)\Rules\MobilityRules.dll" Enabled="True" AllRulesEnabled="True" />
<RuleFile Name="$(FxCopDir)\Rules\NamingRules.dll" Enabled="True" AllRulesEnabled="True" />
<RuleFile Name="$(FxCopDir)\Rules\PerformanceRules.dll" Enabled="True" AllRulesEnabled="True" />
<RuleFile Name="$(FxCopDir)\Rules\PortabilityRules.dll" Enabled="True" AllRulesEnabled="True" />
<RuleFile Name="$(FxCopDir)\Rules\SecurityRules.dll" Enabled="True" AllRulesEnabled="True" />
<RuleFile Name="$(FxCopDir)\Rules\UsageRules.dll" Enabled="True" AllRulesEnabled="True" />
</RuleFiles>
<Groups />
<Settings />
</Rules>
<FxCopReport Version="1.35" />
</FxCopProject>
Any ideas on how this can be done in the most convenient way?
There's no way to use separate rule sets within a single FxCop run. For dealing with the CA1822 test method issue, I usually create two separate FxCop projects: one that includes CA1822 for normal assemblies, and one that excludes CA1822 for test assemblies.
If you're using the code analysis feature integrated into some of the "developer" team edition of Visual Studio, you can apply a different rule set to each assembly. This is supported because the tool ends up running fxcopcmd.exe seperately for each assembly, not because it uses some more complex configuration to support multiple rule sets within a single run.