How to use RabbitMQ list of hosts connection parameter - c#

I'm trying to use the IList<string> parameter when creating a connection in the C# rabbitMQ library:
IConnection CreateConnection(IList hostnames)
My code is as follows:
private IConnection CreateConnection()
{
var connectionFactory = new ConnectionFactory
{
UserName = _userName,
Password = _password,
VirtualHost = _vhost,
AutomaticRecoveryEnabled = DEFAULT_AUTO_RECOVER,
RequestedHeartbeat = HEARTBEAT_TIMEOUT_SECONDS,
Port = AmqpTcpEndpoint.UseDefaultPort,
};
// _hosts contains valid IPs "###.###.###.###"
return connectionFactory.CreateConnection(_hosts);
}
But regardless of what I suppose for the hosts parameter it doesn't seem to connect (I get "None of the specified endpoints were reachable")
Even if my list contains only one element.
Now, if I use the single host implementation like this, it works correctly:
private IConnection CreateConnection()
{
var connectionFactory = new ConnectionFactory
{
UserName = _userName,
Password = _password,
VirtualHost = _vhost,
AutomaticRecoveryEnabled = DEFAULT_AUTO_RECOVER,
RequestedHeartbeat = HEARTBEAT_TIMEOUT_SECONDS,
Port = AmqpTcpEndpoint.UseDefaultPort,
HostName = _hosts.First() // or just one string
};
return connectionFactory.CreateConnection();
}
I recognize that RabbitMQ suggests not storing the set of hosts on the client but I'm just trying to get their provided method to work.

I think you might need to set a value for the HostnameSelector property of the connection factory
private IConnection CreateConnection()
{
var connectionFactory = new ConnectionFactory
{
UserName = _userName,
Password = _password,
VirtualHost = _vhost,
AutomaticRecoveryEnabled = DEFAULT_AUTO_RECOVER,
RequestedHeartbeat = HEARTBEAT_TIMEOUT_SECONDS,
Port = AmqpTcpEndpoint.UseDefaultPort,
HostnameSelector = new RandomHostnameSelector()
};
// _hosts contains valid IPs "###.###.###.###"
return connectionFactory.CreateConnection(_hosts);
}
RabbitMQ provides a RandomHostnameSelector
class RandomHostnameSelector : IHostnameSelector
{
string IHostnameSelector.NextFrom(IList<string> options)
{
return options.RandomItem();
}
}
Or you could create your own implementation of IHostnameSelector to have your own host selection strategy.

Related

LDAPs query for cross domains in AD forest trust

I have two domains(DomainA and DomainB) each in their own AD forests and I have established a forest trust between them,. I am now trying to connect and bind to DomainA and query DomainA for certain attributes of a DomainB user, which is basically a cross domain query.
I am using DirectoryServices.Protocols.LdapConnection and I have set the port to be 636(SSL port) and set the Referral Chasing to ReferralChasingOption.All in C# code. Yet, when the code executes to search the response, I see this error message -
"A referral was returned by the server"
private static LdapConnection getLdapsConnection()
{
LdapConnection connection;
LdapDirectoryIdentifier identifier;
NetworkCredential credential;
try
{
credential = getAdminCredential();
identifier = new LdapDirectoryIdentifier("DomainA.local", 636);
connection = new LdapConnection(identifier, credential)
{
AuthType = AuthType.Basic,
SessionOptions =
{
ProtocolVersion = 3,
SecureSocketLayer = true,
VerifyServerCertificate = new VerifyServerCertificateCallback(true)
}
};
connection.SessionOptions.ReferralChasing = ReferralChasingOptions.All;
return connection;
}
catch (Exception exc)
{
return null;
}
}
public static SearchResponse retrieveUserAttributes(string userName(DomainB_User), List<string> attributesToReturn, LdapConnection connObj)
{
try
{
String filter = "(&(objectCategory=person)(sAMAccountName=" + userName + "))";
String target = "CN=userName,CN=Users,DC=DomainB,DC=local";
SearchRequest searchRequest = new SearchRequest(target, filter, System.DirectoryServices.Protocols.SearchScope.Subtree, attributesToReturn.ToArray());
SearchResponse response = (SearchResponse)connObj.SendRequest(searchRequest);
return response;
}
catch (Exception exc)
{
return null;
}
}
Not sure why the referral error is seen even though referral chasing option is set.
Note:
The same code works perfectly fine for LDAP over 389, this is an issue only for LDAP over ssl for cross domain

How to apply basic authentication in WCF?

I'm implementing a WcfClientFactory
public class WcfClientFactory : IDisposable
{
internal const string WildcardConfigurationName = "*";
//We track all channels created by this instance so they can be destroyed
private readonly List<WeakReference<IDisposable>> _disposableItems = new List<WeakReference<IDisposable>>();
public T CreateClient<T>(string configurationName = WildcardConfigurationName, string address=null)
{
var factory = new ChannelFactory<T>(configurationName);
if (!string.IsNullOrWhiteSpace(address))
{
factory.Endpoint.Address = new EndpointAddress(address);
}
var channel = factory.CreateChannel();
var clientChannel = (IClientChannel)channel;
clientChannel.Open();
_disposableItems.Add(new WeakReference<IDisposable>(clientChannel,false));
return channel;
}
void IDisposable.Dispose()
{
//No finalizer is implemented as there are no directly held scarce resources.
//Presumably the finalizers of items in disposableItems will handle their own teardown
//if it comes down to it.
foreach (var reference in _disposableItems)
{
IDisposable disposable;
if (reference.TryGetTarget(out disposable))
{
disposable.Dispose();
}
}
}
}
So I can create a WCF clientChannel
var client = _wcfClientFactory.CreateClient<ICrmService>(address);
It works fine if the WCF does not have any authentication. Now, we want to add authentication to this factory. How can I do it? I tried below code
public T CreateClientWithBasicAuthentication<T>(string address)
{
WSHttpBinding myBinding = new WSHttpBinding();
myBinding.Security.Mode = SecurityMode.Transport;
myBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
var factory = new ChannelFactory<T>(myBinding, new EndpointAddress(address));
var channel = factory.CreateChannel();
var clientChannel = (IClientChannel)channel;
////CrmServiceClient csc = (CrmServiceClient)channel;
////csc.ClientCredentials.UserName.UserName = _UserName;
////csc.ClientCredentials.UserName.Password = _Password;
clientChannel.Open();
_disposableItems.Add(new WeakReference<IDisposable>(clientChannel, false));
return channel;
}
But it generates exception and asks for UserName and Password. How can I set the password and username?
The variable factory has a member of Credential, but it is get only. That's why I think it has to be a way to set credential before call CreateChannel
Thanks
There may be a problem with the description here, your idea is right, here we can set the client authentication credentials.
var factory = new ChannelFactory<T>(myBinding, new EndpointAddress(address));
//for HttpClientCredentialType.Basic
factory.Credentials.UserName.UserName = "administrator";
factory.Credentials.UserName.Password = "abcd1234!";
//for window credentials
//factory.Credentials.Windows.ClientCredential.UserName = "adminsitrator";
//factory.Credentials.Windows.ClientCredential.Password = "abcd1234!";
var channel = factory.CreateChannel();
Besides, please note that the binding type that the channel factory uses should be consistent with the binding type on the server-side.
Feel free to let me know if the problem still exists.

Azure Virtual Machine has no endpoint

Im trying to create VM's from a template in my ASP.NET MVC web application. So I wrote an action is structured in 4 steps (I added some comments to make it more understandable)
[HttpPost]
public ActionResult QuickCreateVM(string VirtualMachineName, string OSImage, string Username, string Password)
{
string Location = "North Europe";
string StorageAccountName = "azuremanagersharepoint";
try
{
ComputeManagementClient client = new ComputeManagementClient(cloudCredentials);
string vmName = VirtualMachineName;
//STEP1:Create Hosted Service
//Azure VM must be hosted in a hosted cloud service.
createCloudService(vmName, Location);
//STEP2:Construct VM Role instance
var vmRole = new Role();
vmRole.RoleType = VirtualMachineRoleType.PersistentVMRole.ToString();
vmRole.RoleName = vmName;
vmRole.Label = vmName;
vmRole.RoleSize = VirtualMachineRoleSize.Small;
vmRole.ConfigurationSets = new List<ConfigurationSet>();
vmRole.OSVirtualHardDisk = new OSVirtualHardDisk()
{
MediaLink = getVhdUri(string.Format("{0}.blob.core.windows.net/uploads", StorageAccountName)),
SourceImageName = OSImage
};
ConfigurationSet configSet = new ConfigurationSet
{
ConfigurationSetType = ConfigurationSetTypes.WindowsProvisioningConfiguration,
EnableAutomaticUpdates = true,
ResetPasswordOnFirstLogon = false,
ComputerName = vmName,
AdminUserName = Username,
AdminPassword = Password,
InputEndpoints = new BindingList<InputEndpoint>
{
new InputEndpoint { LocalPort = 3389, Port = 3389, Name = "Remote Desktop", Protocol = "TCP", EnableDirectServerReturn = true }
}
};
vmRole.ConfigurationSets.Add(configSet);
vmRole.ResourceExtensionReferences = null;
//STEP3: Add Role instance to Deployment Parmeters
List<Role> roleList = new List<Role>() { vmRole };
VirtualMachineCreateDeploymentParameters createDeploymentParams = new VirtualMachineCreateDeploymentParameters
{
Name = vmName,
Label = vmName,
Roles = roleList,
DeploymentSlot = DeploymentSlot.Production
};
//STEP4: Create a Deployment with VM Roles.
client.VirtualMachines.CreateDeployment(vmName, createDeploymentParams);
}
catch (CloudException e)
{
throw e;
}
catch (Exception ex)
{
throw ex;
}
return View("Panel");
}
My problem: It seems like my VM has no endpoint. Although the ConfigurationSet was configured correctly. So, in my code I say
new InputEndpoint { LocalPort = 3389, Port = 3388, Name = "Remote Desktop", Protocol = "TCP", EnableDirectServerReturn = true }
But in the azure portal
So I'm not able to start the Vm.
Has anyone an idea what I'm missing? Or are there any good tutorials to this topic?
Thank you in advance
Ok, so I had the exact same issue and figured out the problem.
You need to create an additional ConfigurationSet with a ConfigurationSetType of ConfigurationSetTypes.NetworkConfiguration, and then add your endpoints in there.
Something like this:
ConfigurationSet networkConfigSet = new ConfigurationSet
{
ConfigurationSetType = ConfigurationSetTypes.NetworkConfiguration,
InputEndpoints = new BindingList<InputEndpoint>
{
new InputEndpoint { LocalPort = 3389, Port = 3389, Name = "Remote Desktop", Protocol = "TCP", EnableDirectServerReturn = true }
}
};
vmRole.ConfigurationSets.Add(networkConfigSet);
See here:
https://msdn.microsoft.com/en-us/library/azure/jj157194.aspx
...specifically the ConfigurationSets section.

Active directory listing groups - LdapConnection works, PrincipalContext does not

Creating a web service which talks to Active Directory to verify users and determine which groups they belong to.
I started out with the verification process, and got this working:
public bool AuthenticateAdUser(string username, string password)
{
//in the real code, these come from config
string domain = "TestDomain";
string server = 666.666.666.666;
string authType = "Basic";
string useSsl = "false";
AuthType atype = (AuthType)Enum.Parse(typeof(AuthType), authType);
using (var ldapConnection = new LdapConnection(server))
{
var networkCredential = new NetworkCredential(username, password, domain);
ldapConnection.SessionOptions.SecureSocketLayer = Convert.ToBoolean(useSsl);
ldapConnection.AutoBind = false;
ldapConnection.AuthType = atype;
ldapConnection.Bind(networkCredential);
}
// If the bind succeeds, the credentials are valid
return true;
}
However, I'm not clear on how I can use that LdapConnection object to work with groups. The documentation and examples suggest you use PrinicpalContext for that purpose. So I tried this.
string domain = "TestDomain";
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, domain))
{
using (PrincipalSearchResult<Principal> src = UserPrincipal.FindByIdentity(pc, username).GetGroups(pc))
{
src.ToList().ForEach(sr => result.Add(sr.SamAccountName));
}
}
This fails, claiming it can't contact the Active Directory server. Using a DNS style name ("TestDomain.local") doesn't seem to help.
This does at least spin up a network principal:
string server = "666.666.666.666";
using (PrincipalContext pc = new PrincipalContext(ContextType.Machine, server))
{
using (PrincipalSearchResult<Principal> src = UserPrincipal.FindByIdentity(pc, username).GetGroups(pc))
{
src.ToList().ForEach(sr => result.Add(sr.SamAccountName));
}
}
But when you try and do anything with it, it fails with "Network path not found".
Any ideas on why the Principal won't work, or how I can use the LdapConnection to query groups?

Chilkat connection exception in FTP2 in c#

I am getting the following message in the chilkat exception
calling ConnectSocket2
IPV6 enabled connect with NO heartbeat.
Cannot connect, hostname is zero length
ConnectFailReason: 1
Failed to connect to FTP server.
Failed. --ConnectOnly_Ftp2
--ChilkatLog
I am trying to connect to FTP server using chilkat's Ftp2 class(using c#), using Connect method.
Following is my class which I am using to connect with the FTP2
public class FTPClient
{
private Ftp2 m_FtpInfo;
const int FTP_DEFAULT_PORT = 21;
public FTPClient()
{
m_FtpInfo = null;
}
public FTPClient(string userName, string password, string hostName, int port)
{
m_FtpInfo = new Ftp2();
m_FtpInfo.Account = userName;
m_FtpInfo.ClientIpAddress = hostName;
m_FtpInfo.Password = password;
//m_FtpInfo.Port = port;
}
public Ftp2 FTPInfo
{
get
{
if (m_FtpInfo == null)
m_FtpInfo = new Ftp2();
return m_FtpInfo;
}
set { m_FtpInfo = value; }
}
public void Connect()
{
lock (this)
{
if (m_FtpInfo == null)
{
m_FtpInfo = new Ftp2();
}
AppConfiguration appConfiguration = AppConfiguration.Instance;
/*
* Steps to connect to FTP site using Chilkat
* 1. Unlock the component by passing the code provided by Chilkat
* 2. Connect to the Site by specifying the hostname and port
*/
// Unlock the component.
if (!m_FtpInfo.UnlockComponent("AnythingWorksFor30DayTrial"))
{
throw new FTPConnectionExceptions(CommunicationError.UnlockFailed, m_FtpInfo.LastErrorText);
}
// Connect to the FTP server. (use a domain name or IP address)
if (!m_FtpInfo.Connect())
{
throw new FTPConnectionExceptions(CommunicationError.ConnectionFailed, m_FtpInfo.LastErrorText);
}
}
}
public void DisposeConnection()
{
lock (this)
{
if (m_FtpInfo == null) return;
if (m_FtpInfo.IsConnected)
m_FtpInfo.Disconnect();
m_FtpInfo = null;
}
}
Can anyone please tell where am I going wrong?
The line m_FtpInfo.ClientIpAddress = hostName; isn't required. The actual host to connect to isn't set.
Edit:
The Chilkat example page sets the hostname like this:
ftp.Hostname = "ftp.chilkatsoft.com";
So instead of setting ClientIpAddress (the local PC's ip), use Hostname.
Edit 2:
Try this:
public FTPClient(string userName, string password, string hostName, int port)
{
m_FtpInfo = new Ftp2();
m_FtpInfo.Account = userName;
m_FtpInfo.Hostname = hostName;
m_FtpInfo.Password = password;
//m_FtpInfo.Port = port;
}

Categories

Resources