How to configure Rebus manualy to use external server - rebus

I've got a app.config configuration for Rebus and it works:
<configuration>
<configSections>
<section name="rebus" type="Rebus.Configuration.RebusConfigurationSection, Rebus" />
</configSections>
<rebus address="192.168.10.100" inputQueue="a.messages" errorQueue="a.error" workers="1" maxRetries="10">
<endpoints>
<add messages="ESB_Model" endpoint="a.messages#MyRemoteMachine" />
</endpoints>
</rebus>
</configuration>
After now I want to set the address and endpoint in code instead of configfile:
_adapter = new BuiltinContainerAdapter();
_bus = Configure.With(_adapter)
.Logging(l => l.None())
.Transport(t => t.UseMsmq("a.messages#MyRemoteMachine", "a.error"))
.MessageOwnership(d => d.FromRebusConfigurationSection())
.CreateBus()
.Start();
This is not accepted and I'm not sure how to set the IP-address. Any help would be welcome!

I can see a couple of issues with your code, first one being that the two configurations are not equivalent.
The issue with the second configuration is that Rebus does not allow you to use a remote queue as your endpoint's input queue. Therefore, the #-syntax should not be used when defining the input queue.
Also, it seems you're mixing something up - a.messages seems to be your input queue, but it also seems that you want to use it (granted: on another machine) as the owner of all messages from ESB_Model. It might be correct, but it seems you're mixing it up a little bit.
Usually, each endpoint should have its own unique input queue, and endpoints should always receive their messages from a local queue. And you should probably never have two endpoints receiving messages from the same queue.
Lastly: Unless you really know what you're doing, please don't explicitly specify the IP address of your endpoint - Rebus will automatically use the input queue in combination with the machine name as the address - e.g. if an endpoint a.messages running on SomeMachine sends a message to another endpoint, the return address will automatically be set as a.messages#SomeMachine.
If you'd like some more inspiration, you can check out the samples: https://github.com/mookid8000/Rebus/tree/master/samples/Rebus.Samples - the pub/sub sample has some simple configurations that work fine and don't over-specify.
Hope that clears it up a little bit - please let me know if you need more help :)

Related

Disable Only HealthCheck Related Logging

I'm trying to figure out a way to disable any health-check related ILogger logging. I am aware of LogLevel filtering, but that will not work here.
As an example, I have a healthcheck that makes an outbound call to a RabbitMQ metrics API. This results in an outbound http call with every inbound call to /health. In general, I want to log all outbound calls made using the HttpClient, but that log is now full of this particular log entry:
[2021.06.15 13:57:04] info: System.Net.Http.HttpClient.Default.LogicalHandler[101] => ConnectionId:0HM9FV5PFFL5K => RequestPath:/health RequestId:0HM9FV5PFFL5K:00000001, SpanId:|6726c52-4217ec92de4df5fb., TraceId:6726c52-4217ec92de4df5fb, ParentId: => Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckLogScope => HTTP GET http://rabbitmq/api/queues/MyVHost/MyQueue?msg_rates_age=60&msg_rates_incr=60
: End processing HTTP request after 4.6355ms - OK
So, I could apply a warning filter to the HttpClient/LogicalHandler to remove those entries, but then I'd be removing all the info logs of other outbound Http requests, which I don't want.
So, basically, I need a smarter filter that can look at the scopes (or even the text in certain cases), and can filter out based on "Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckLogScope". That doesn't seem to be possible though, as the filter callback doesn't provide those details.
Does anyone have any idea how to do more specific log filtering for cases like this?
I have looked at .net core log filtering on certain requests, but extending every ILoggerProvider I use isn't possible, since some are not public classes.
You could use Serilog for logging, as it also provides great filtering, enriching, and formatting capabilities with Serilog.Expressions Nuget package.
There is even a simple example provided in the link above for filtering health checks, which fulfilled my needs to fully filter out health check logging based on the request path '/health'. Following the guide, it only required adding appsettings.json configuration, after the serilog was configured as the application logger to make it work:
{
"Serilog": {
"Using": ["Serilog.Expressions"],
"Filter": [
{
"Name": "ByExcluding",
"Args": {
"expression": "RequestPath like '/health%'"
}
}
]
}
}
To filter out those requests you can try using the Log4Net StringMatchFilter filter with the value of the health URL.
Here is the code for the configuration file if health URL is just localhost/health:
<filter type="log4net.Filter.StringMatchFilter">
<stringToMatch value="/health" />
<acceptOnMatch value="false" />
</filter>

Routing of incoming calls by called number

I have two phone numbers registered with the same sip provider. I would like Asterisk/PJSIP to route phone #1 (18005551212) differently than phone #2 (18005551313).
[sipprovider-18005551212]
type=registration
client_uri=sip:18005551212#sip.provider.com:5060
[sipprovider-18005551313]
type=registration
client_uri=sip:18005551313#sip.provider.com:5060
The Contact provided by Asterisk during registration is the same for both (using default extension 's').
Contact: <sip:s#10.1.1.1:5060>;expires=120
Can I do any of the following:
1) When registering, provide an extension other than 's'? Allowing inbound calls to hit unique extensions in the dialplan.
2) Route to unique context based on the To: Header on the INVITE? (which holds the unique phone number called). I have tried using 'context=' in the pjsip.conf endpoint block, but no luck; routing is either by IP (which is the same for both phone numbers), or by name (which is based on the From: Header).
Any help or pointers would be appreciated.
You could try this from my extensions.conf
[inbound-sip]
exten => 3215445,1,Goto(sip-in-1,s,1)
exten => 2544221,1,Goto(sip-in-2,s,1)
[sip-in-1]
exten => s,1,Goto(internal-ext,6881,1)
Calls then end up in the relevant context for further processing and alerting etc. sip-in-1 or sip-in-2 in this case.
In your sip.conf or pjsip.conf you need to specify the inbound context for both numbers you have - in this case context = inbound-sip
You should enable sip debug and see if calls have anything like destination number.
If it have no - you have no way get info which not present.
If you have, you should create extension s and parse number info using SIP_HEADER function from sip request body.

Using a third party web service in vb.net

I am trying to build an app in VS Pro 2012 (VB.NET) that will invoke RoyalMail's MailMark WSDL which has methods such as RetrieveActiveSupplyChains which are expecting a single parameter (request).
I have used svcutil with the /l:vb switch to download the WSDL and referenced it in my project and I can see methods being exposed once I have done
Dim client As PosterUploadClient = New PosterUploadClient()
Now typing client. brings up all the methods I expect to see and I can pass authentication and see the state change when I do client.open() but what I can't figure out is how to provide the parameters the actual methods need. According to their documentation, RetrieveActiveSupplyChains doesn't need a parameter but they have provided an xml example of the request structure so my assumption is that I'd need to construct this as xml with the appropriate values and send it as "request"?
Does this sound right? I know this is probably meat and veg for a web programmer but not something I have attempted before. The xml they supplied as an example looks like the below:
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<s:Header>
<a:Action s:mustUnderstand="1">http://rm-manifest.com/2014/01/service/IPosterUpload/RetrieveAllActiveSupplyChains</a:Action>
<a:MessageID>urn:uuid:ab5e32a3-812e-4d91-97a8-de00a08874e9</a:MessageID>
<a:ReplyTo>
<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
</a:ReplyTo>
<a:To s:mustUnderstand="1">https://rm-manifest.com/PosterUpload2/PosterUpload.svc/service</a:To>
<o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<u:Timestamp u:Id="_0">
<u:Created>2014-10-03T14:32:58.480Z</u:Created>
<u:Expires>2014-10-03T14:37:58.480Z</u:Expires>
</u:Timestamp>
<o:UsernameToken u:Id="uuid-dfaaf0b0-3823-4f75-b607-33f7434295dc-1">
<o:Username>NetworkAccess</o:Username>
<o:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">p1</o:Password>
</o:UsernameToken>
</o:Security>
</s:Header>
<s:Body>
<RetrieveAllActiveSupplyChains xmlns="http://rm-manifest.com/2014/01/service">
<request xmlns:b="http://rm-manifest.com/2014/01/messages" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"/>
</RetrieveAllActiveSupplyChains>
</s:Body>
</s:Envelope>
But I'm still not sure how it actually needs to be submitted, certainly if I read that sample one in with a new xmltextreader it doesn't like it with the following error message
Value of type 'System.Xml.XmlTextReader' cannot be converted to 'MM_TEST.Mosaic.EIB.PosterUploadService.Core.Messages.RetrieveActiveSupplyChainsRequest'
My assumption was the WSDL replaces the need to actually create a "New HttpRequest" in my code but not sure. I've done a lot of googling but not getting anything that quite works like this
The WSDL is here if this helps:
https://customertest.rm-manifest.com/PosterUpload/PosterUpload.svc
Just call the method. The provided XML is what is actually sent to the server by the WCF proxy when you call the method. You don't need to use it at all.
If you use a tool like Fiddler, you'll see that simply calling client.RetrieveAllActiveSupplyChains will send an HTTP request with a body similar to the XML sample.
In fact, everything outside the RetrieveAllActiveSupplyChains tag isn't related to the method at all - it's security and addressing data used to establish and execute a connection with a web service in general. All of this is handled by WCF.

ADFS Skip Home Realm Discovery using integrated auth

My scenario:
I've got a .net web application where people log into the app with forms authentication, and my forms authentication code sends certain users off to ADFS to be verified. I have multiple federations, including my own Active Directory server for internal users. So, for users that need to be sent to ADFS for authentication, I do something like this:
WSFederationAuthenticationModule instance = FederatedAuthentication.WSFederationAuthenticationModule;
SignInRequestMessage request = instance.CreateSignInRequest(Guid.NewGuid().ToString(), instance.Realm, true);
request.AuthenticationType = "urn:federation:authentication:windows";
//maybe you just don't need to specify the homerealm for ad, because there can only be one AD (integrated) trust?
//request.HomeRealm = "I-no-idea-what-to-put-here-for-AD";
Response.Redirect(request.WriteQueryString());
When you do this, you set the .HomeRealm property which populates the whr attribute for you on the query string. This should make AD FS skip the HRD (Home Realm Discovery) page. For most of my federations (remote STSs) it's very clear what value I need to put in the property, you can pull the value from the dropdown box on the HRD page itself, or you can go into the AD FS management tool and pull the value from the trust properties. For the AD trust, however, there is no value in the dropdown list (empty string), and you can't go to properties in the management console. So the question is really this: if I want to preselect the AD trust through the whr parameter, what do I set the HomeRealm Property to?
P.S. you'll see the comment there: "maybe you just don't need to specify the homerealm for ad, because there can only be one AD (integrated) trust?" I think this might be the case, but I haven't proved it yet. I will answer this later if my guess is correct.
From the code in the original question:
request.AuthenticationType = "urn:federation:authentication:windows";
That particular line didn't appear to have any effect. Also, the hope that no HomeRealm need be specified was also in vain. It turns out that you must, in fact, specify the HomeRealm. After searching google for some time, I found many statements hinting that the Active Directory trust was the same as trusting the ADFS server itself. So as a wild shot in the dark I tried putting in the URI of the ADFS server, and, much to my pleasure and surprise, this worked.
So, to be more clear, if you go to the web.config of the relying party you should have something set up similar to this:
<issuerNameRegistry type="System.IdentityModel.Tokens.ValidatingIssuerNameRegistry, System.IdentityModel.Tokens.ValidatingIssuerNameRegistry">
<authority name="http://testadfs.test.com/adfs/services/trust">
<keys>
<add thumbprint="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" />
</keys>
<validIssuers>
<add name="http://testadfs.test.com/adfs/services/trust" />
</validIssuers>
</authority>
</issuerNameRegistry>
I ended up setting the value of request.HomeRealm to the value that you see there in the validIssuers and authority elements. This gave me the desired effect of causing ADFS to automatically select the Active Directory claims provider trust.
I should be clear that my ADFS server is NOT the domain controller, and yet this still works.

BizTalk SOAP port password in binding file

I've inherited a BizTalk 2006 application that uses several SOAP ports to request data from a 3rd party web service. The web service is secured by "basic" authentication - username / password. After making a few enhancements to the application I deployed to an integration test server which has access to the 3rd party web service. The BizTalk app was unable to retrieve the data and I soon realised that I had forgotten to set the username / password on the SOAP send ports. I wanted the make deployment of the BizTalk app as automated as possible because I may not be present when it is deployed to the live server. I opened up the binding file, located the 1st of the problem SOAP send ports and looked for the * that BizTalk uses to replace the password - except that it doesn't! It seems that the password for SOAP ports is set to NULL rather than *, see here for more details:
http://msdn.microsoft.com/en-us/library/aa547319.aspx
I proceeded to update the binding but when I came to test, after importing my amended binding file, I found that I had the same problem as before. I've double checked and can confirm that the correct password is now present in the binding file but, although BizTalk doesn't complain during the import, when I run the app I get the following exception:
Details:"ArgumentNullException: String reference not set to an instance of a String.
Parameter name: s
".
If I then manually amend the password through the BizTalk admin console everything work fine.
Has anyone else had a similar problem with the bindings for a SOAP port - does anyone have a solution?
I've been bit by something like this in the past. The password is either put in as '****'. This is ok. I wouldn't want all of my secrets exported with the binding file. What does get you is when you export the bindings and you leave the password NULL. The Variable Type (vt) attribute on the XML element for the password is set to vt="1" which is the same as NULL. It won't matter what you put in for the password. It may even cause the error you described. I would suggest you include a copy of the binding XML for review.
I've never seen this problem before - I'm doing exactly what you are trying to do and it works perfectly.
I've included the <TransportTypeData> element from one of my BizTalk bindings that works. Hopefully having something to compare against helps.
<TransportTypeData>
<CustomProps>
<AuthenticationScheme vt="8">Basic</AuthenticationScheme>
<AssemblyName vt="8">WebService.ProxyClass, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=xyz</AssemblyName>
<Username vt="8">soapUser</Username>
<UseProxy vt="11">0</UseProxy>
<UseSoap12 vt="11">0</UseSoap12><UsingOrchestration vt="11">0</UsingOrchestration>
<UseSSO vt="11">0</UseSSO>
<Password vt="8">MYPASSWORD</Password>
<ProxyPort vt="3">80</ProxyPort><AssemblyPath
vt="8">C:\ProxyClass\bin\Debug\ProxyClass.dll</AssemblyPath>
<TypeName vt="8">ProxyClass.Webservice.servicesService</TypeName>
<MethodName vt="8">PickupRequest</MethodName>
<UseHandlerSetting vt="11">-1</UseHandlerSetting>
</CustomProps>
</TransportTypeData>

Resources