About Me · Send mail to the author(s) E-mail · Twitter

At GROSSWEBER we practice what we preach. We offer trainings for modern software technologies like Behavior Driven Development, Clean Code and Git. Our staff is fluent in a variety of languages, including English.

Feed Icon


Open Source Projects


Blogs of friends

Now playing [?]

Error retrieving information from external service.


Page 1 of 3 in the Networking category Next Page

How To Set Up Secure LDAP Authentication with TeamCity

Posted in Build | Networking at Monday, February 02, 2009 5:35 PM W. Europe Standard Time

Last week we got a TeamCity Enterprise license at work. After using this great product for about a year we found ourselves running out of available build configurations. (There are 20 in the fully-functional free Professional edition which should be enough to evaluate the product. I recommend giving it a try.) There are a couple of advanced features in the TeamCity Enterprise edition we were looking forward to, for example authentication against a LDAP directory, an Active Directory in our case (AD = LDAP + DNS + a bunch of other stuff).

TeamCity uses LDAP to determine if a user should be able to access the TeamCity web interface. It does that through the LDAP bind operation, asking LDAP to validate the username and password combination entered at the login page.

TeamCity Login Dialog

After hitting the login button TeamCity will connect to the LDAP server, basically taking the text entered in the dialog above passing it to the LDAP bind operation. If the server accepts the username/password combination this means that access is granted. Some things to take into consideration when using LDAP authentication are:

  • TeamCity does not authenticate against an organizational unit in Active Directory (X.500 address). It just determines if the user (authenticated by username and password) exists anywhere in the directory. You can vote on this ticket to get that fixed.
  • Because TeamCity does not try to get additional information on the user’s groups memberships it is currently (as of TeamCity 4.0) not possible to automatically assign TeamCity roles to an LDAP user.
  • If you use the default LDAP configuration settings as shown in the TeamCity documentation, the LDAP connection will be unsecured, making the username and password vulnerable to eavesdropping by anyone who knows how to use packet sniffer.
  • Specific to Windows: You do not need an Active Directory infrastructure with a Domain Controller in place. Windows also supports Active Directory Application Mode (ADAM) on Windows Server 2003, renamed to Active Directory Lightweight Directory Services (AD LDS) in Windows Server 2008.

Given the things above, what are your options to secure the LDAP connection? You could change the authentication scheme to not use "simple” LDAP authentication, but choose from a variety of SASL options. I didn’t go down that road, because when I started to configure LDAP for TeamCity I basically knew nothing about neither LDAP nor SASL.

Using LDAPS (LDAP over SSL), which is also supported by Windows servers running some AD mode, appeared to be a viable option to enforce secure communication between TeamCity and the LDAP server.

Installing The LDAP Server

Setting Up LDAPS with Active Directory (Domain Controller mode)

There’s not much set up needed with this configuration. When you install Active Directory in Domain Controller mode you should also get an instance of Certificate Services that will create a self-signed certificate for your domain controller. This certificate will be used for LDAPS connections to the directory server, which is typically the domain controller.

As an aside, I’m not expert in setting up AD, please refer to your network administrator.

Setting Up LDAPS with Active Directory Application Mode (ADAM) or Active Directory Lightweight Directory Services (AD LDS)

As noted above, this setup is supported on any Windows Server and does not require the full-blown “Domain Controller” version of Active Directory. ADAM/LDS supports user authentication either against the ADAM/LDS instance (users created in the directory) or a against local Windows accounts (through a user proxy, see below)

Installing ADAM or AD LDS

Installing ADAM/LDS differs depending on which Windows Server version you have. I did it with Windows Server 2003:

  1. Navigate to the Control Panel and open up the Software control panel applet, appwiz.cpl
  2. Click “Add or remove Windows features”
  3. Select Active Directory Services, click on the Details… button and select Active Directory Application Mode. Close the window.
  4. Scroll down to Certificate Services entry and check it. (IIS will also be installed as part of Certificate Services to support web registrations.)
  5. Click Next.
  6. On the next dialog, you will be asked what type of Root Certificate Authority (CA) to install. Select “stand-alone“ CA and also check the “Create key pair” option.
  7. The next dialogs allows to select different options for the Root CA keys and the CA itself. I went with the defaults.
  8. Certificate Services and ADAM will be installed.
  9. Under Programs in the Start Menu there will be a new folder named “ADAM”. Click on the “Create ADAM instance” link.
  10. The ADAM wizard pops up, click Next.
  11. Choose “Create new unique instance” and click Next.
  12. Enter the name of the ADAM instance. I chose “TeamCity”, because we’re using ADAM to authenticate TeamCity users. Click Next.
  13. Write down the ports that are presented in the next step. The default LDAP port is 389, and the port for LDAPS is 636. Click Next.
  14. In the next step, choose to create a directory partition. Mine is called CN=TeamCity, DC=test, DC=local. Click Next until you reach the “Import LDIF files” dialog.
  15. Import at least the MS-User.ldf and MS-UserProxy.ldf schemas to enable the creation of local directory users and user proxies for Windows accounts.
  16. Click Next and wait for ADAM to be configured.
Setting Up ADAM or AD LDS to Accept SSL Connections

There are two good tutorials that I used to enable SSL on ADAM, so I won’t reiterate them here. I suppose the process of enabling SSL on LDS is similar.

User Management

You now have a LDAP server running that will serve requests for the LDAP and LDAPS protocols. Next, you would have to add users to the directory, which could either be

  • Local directory users: user and password stored in the directory; used with “simple” bindings, or
  • Windows users: users password stored by the local Windows account manager or in a full-blown AD domain; used with “proxied” bindings (from the outside, these also appear as “simple” bindings).

Windows users require a user proxy in the directory, linking the proxy to a Windows account SID. The link between the proxy and the Windows account is established though the Windows account’s Security Identifier (SID) which must be supplied when the proxy is created. Setting up user proxies is a bit complicated and well worth another post.

Please note that by default authenticating users through their respective proxies (proxied binding) requires a secure connection, unless you explicitly disable it. Unfortunately the attribute to change is not given in the linked article: it is msDS-Other-Settings. You can either require security for simple or proxied bindings by setting RequireSecureProxyBind (defaults to 1) and RequireSecureSimpleBind (defaults to 0) to either 0 or 1.

The net result of the default ADAM configuration (RequireSecureProxyBind=1) together with the default TeamCity configuration (ldap://some-server, which is unsecured) is that authentication requests for user proxies will always fail.

Setting Up TeamCity

Setting Up TeamCity to Use The LDAP Server

The easiest way is to start with the default TeamCity configuration in <TeamCity data directory>/config/


Unless you want to require your users to enter their login in the DOMAIN\username format I recommend adding the loginFilter property:


Now we need to set up the correct "user name" string to present it to the LDAP server. This string is created from the text entered in the "Username" text box on the login screen ($login$) and differs depending on whether you use LDAP with AD or ADAM/LDS:


# AD - authenticate against the TEST domain

# ADAM and presumably AD LDS - users will have to reside in the CN=Users,CN=TeamCity,DC=test,DC=local container

Setting Up LDAPS Security

Enabling LDAPS is pretty easy from a TeamCity perspective. You just have to change line 2 of the configuration above to use the secure LDAP protocol:

formatDN=<some value>

Changing the protocol to use ldaps:// will not instantly work and users would not be authenticated. Why?

Trusting The Certificate

What does LDAPS mean from a Java perspective? If you work on a domain (AD) or use ADAM/LDS with SSL you are very likely to work with self-signed SSL certificates. Such certificates are inherently untrusted as they are not issued by some trusted party (and this trusted party will charge money). Nevertheless they are perfectly okay for your environment.

When TeamCity establishes the SSL connection to your LDAP server, it is first presented with that untrusted certificate – and bails. Here’s a snippet from the TeamCity log files:

[2009-01-27 16:14:39,864]  ERROR - Side.impl.auth.LDAPLoginModule - 
javax.naming.CommunicationException: simple bind failed: ldap.test.local:636
[Root exception is PKIX path building failed: unable to find valid certification path to requested target]

To establish LDAPS connections successfully, you have to tell Java to trust your LDAP server’s certificate. Andreas Sterbenz has created a little Java utility called InstallCert that helps in that regard. Unfortunately you will have to compile it yourself against the Java 1.5 runtime, so here’s a compiled version that works with TeamCity.

Place the files from the ZIP in your <TeamCity root>\jre\bin directory. Open a command prompt and enter

java InstallCert ldap.test.local:636

Following the procedure described in Andreas' post, the utility will create a file called jssecacerts in the same directory. Overwrite <TeamCity root>\jre\lib\security\cacerts with that file.

After re-starting the TeamCity web server, it is now able to establish secured connections to the LDAP server. The user names and passwords transmitted over these connections will not be visible to outsiders.

Wrapping It Up

In this article I’ve shown you how to enable and secure TeamCity’s LDAP authentication in any Windows environment, be it an Active Directory domain or a couple of stand-alone Windows Servers. For both scenarios user management is centralized, either though the AD console or LDAP console in combination with the Windows user management console.

Figuring out all that has taken a considerable amount of time for me and hopefully saves you a couple of minutes that you can spend outside in the sun.

General Considerations For Securing Windows Servers On The Internet (And Anywhere Else)

Posted in IIS | Networking | PowerShell | Security | SQL Server | Windows at Friday, February 08, 2008 5:04 PM W. Europe Standard Time

By now there are a couple of Windows Servers that I actively manage, or, in the case of projects, I touched while moving the project forward. Most of these servers have an Internet connection. Since I've been asked how to make servers more secure and manageable, here are a couple of management rules I applied. Consider it a checklist.

  • Use a firewall and configure it accordingly.
  • Enable automatic Windows Updates and upgrade to Microsoft Update to receive updates of other Microsoft products like SQL Server.

Okay, the two above should have been obvious.

  • Keep the machine clean.
    Don't install any unnecessary software and don't leave any temporary files on the server. I've seen certificate requests lingering on drive C: and "test" folder remnants. A clean system might reveal hacker activity early in case they leave unfamiliar files behind.
  • Leverage the principle of least privilege.
    All users and service accounts should only have the minimum rights they need. Configure the file system such that system services can only access the files and folders they are in charge of. Typical example: Use a dedicated service account for SQL Server. (Setting this up on SQL 2005 is even more simple.)
  • Rename the Administrator account.
    Rename the Administrator account and make it match your preferred user naming scheme (i. e. agross). You might apply this to your whole organization if you use Active Directory. This is another hurdle to guess the Administrator account from a list of user accounts and works good with account lockout enabled (see below).
  • Create a new "Administrator" account
    and give it a very strong throw-away password. I typically use two or three concatenated GUIDs that I immediately forget. Disallow this user to change his password, remove all group memberships and disable the account.
  • Audit the hell out of the machine.
    Windows uses the Security event log to record security-related events. Configure auditing using secpol.msc and enable success and failure logging at least for
    • Account logon events,
    • Logon events and
    • Policy change.
    The last option is for tracking changes to the policy you just set.
  • Enable complexity criteria for passwords and account lockout.
    To be found in the same MMC snap-in as above. For account lockout I often go with the default values of 5 attempts and 30 minutes of threshold and duration.
  • Deactivate file sharing/Microsoft Networking on the WAN connection.
    Because it's most likely unneeded.
  • Secure RDP sessions using a certificate.
    Torsten has a nice write-up on how to leverage SSL to secure the RDP handshaking/authentication phase to overcome man-in-the-middle and ARP spoofing attacks. His article is available in German only so here's two-sentence recap: On the server's RDP security tab, enable SSL and choose the same certificate you use for HTTPS encryption. On the client side, enable server authentication.
  • Extra: Allow RDP sessions only from white-listed workstations.
    For a server that was hacked a while ago using an ARP spoofing attack (see bullet above) I wrote a Powershell script forces RDP session to originate from a list of known workstations. Each RDP user can have multiple allowed workstations. If a logon attempt occurs from another machine that RDP session is killed immediately.
    # Alert.ps1
    # Logon script for users with known RDP client names.
    # Array of users with known workstations.
    $userWorkstations = @{
    	"user2" = @("VALIDCOMPUTERNAME3")
    # Logoff executable.
    $logoffCommand = $Env:SystemRoot + "\system32\logoff.exe"
    # Trim the user name.
    $currentUser = $Env:UserName.Trim()
    # Cancel if a user that's not contained in $userWorkstations logs on.
    if ($userWorkstations.Keys -inotcontains $currentUser)
    # Send alert e-mail and log off if the user logs on from an unknown workstation.
    if ($userWorkstations[$currentUser] -inotcontains $Env:ClientName.Trim())
    	$subject = $("Unknown RDP client '{0}' for user '{1}'" -f $Env:ClientName.Trim(), $currentUser)
    	$message = New-Object System.Net.Mail.MailMessage
    	$message.From = ""
    	$message.IsBodyHtml = $false
    	$message.Priority = [System.Net.Mail.MailPriority]::High
    	$message.Subject = $subject
    	$message.Body = $subject
    	$smtp = New-Object System.Net.Mail.SmtpClient
    	$smtp.Host = "localhost"
    	# Force logoff.
    Set the script as a logon script for your users using the Alert.cmd helper script below.
    rem Alert.cmd - runs the Alert.ps1 Powershell script.
    @powershell.exe -noprofile -command .\Alert.ps1
  • Enable SQL Server integrated authentication.
    I don't see a need for SQL Server Authentication in most scenarios, especially if you're running/hosting .NET applications. However, in some projects I've worked on there seems to be a tendency towards SQL Server Authentication for no special reason.
  • Configure IIS log detail and directories.
    I tend to enable full IIS logs, that is, all information regarding a request should be logged. Also, I like my logs residing in "speaking" folders, so instead of %windir%\system32\LogFiles\W3SVC<Some number> they should be placed in %windir%\system32\LogFiles\IIS <Site name>\W3SVC<Some number>. This makes it easy to find the logs you're interested in.
  • Use SSH to connect remotely.
    There's a little free SSH server out there that should fit most user's needs. Besides a secure shell environment freeSSHd offers SFTP and port tunneling capabilities to tunnel insecure protocols. Authentication works natively against Windows accounts.
  • Deploy a server monitoring tool.
    I like to use the free MRTG tool, of course any other tool allowing you quickly view any uncommon activity to will do.
  • Use a dedicated management network interface, if possible.
    You should configure strict firewall rules for that interface. Allow access only from a known management subnet.

What rules do you apply to make your servers more secure and manageable?

Now Playing [?]: MorcheebaDive DeepEnjoy the ride (feat. Judy Tzuke)

Wow, what a mouthful of a title.

What do we have here? We've got a Site-To-Site VPN to be established from a ISA Server with a dynamic IP address. Dynamic IP addresses are assigned by ISPs for consumer cable and DSL internet connections and will be renewed at least each 24 hours. That is, every time your internet connection is established, your public IP changes. This prevents you from hosting internet servers on top of your cheapo DSL service.

Site-To-Site VPNs basically connect two private networks over a secured internet tunnel. ISA Server supports Site-To-Site VPNs but requires a static IP address for the local VPN gateway. Since the local VPN gateway is your ISA Server that has a dynamic IP address, you have to either purchase a static IP address (expensive) or update the local endpoint's IP address every time your internet connection is established. A pitfall I ran into when I was setting up the VPN connection together with my very helpful colleague Timo from Synexus was that we were able to successfully connect to the remote site until the DSL connection dropped. All further VPN connection attempts failed because due to the reconnect, ISA Server's public IP changed. This isn't reflected by the remote site configuration, the dropdown box is just emptied:

Local Endpoint IP is empty after reconnects

Now you'll either have to change the local endpoint address using the ISA Server management console every time your DSL line is connected or you could automate that using ISA's rich COM object model.

Scripting the ISA Server COM objects with Windows PowerShell is easy. It actually takes just six lines of code to set the new public IP for all Site-To-Site VPN connections.

param([string] $newIP = $(throw "Update-IsaServerIPSecPublicIp: New IP address is missing"))

$root = New-Object -comObject "FPC.Root" -strict
$server = $root.Arrays | Select-Object -first 1
$publicNetwork = $server.NetworkConfiguration.Networks | Where-Object { $_.NetworkType -eq 3 }
$ipSecSite2SiteNetworks = $server.NetworkConfiguration.Networks | Where-Object { $_.NetworkConnectionType -eq 4 }

$ipSecSite2SiteNetworks | ForEach-Object { $_.VpnConfiguration.IPSecSettings.LocalServerAddress = $newIP; $_.VpnConfiguration.IPSecSettings.Save() }

The next step will be to integrate this script to an application that detects changes to IP address of certain network interfaces – we use DirectUpdate to keep our domains current. But any other tool like the free DynDNS Updater that is able to spawn a process when a new IP is detected will certainly do.

C:\WINDOWS\system32\WindowsPowerShell\v1.0\powershell.exe -noprofile -command C:\Tools\Update-IsaServerIPSecPublicIp.ps1 <new IP address>

If you didn't use PowerShell until now, take a look at Scott Hanselman's most recent dnrTV webcast. Scott has recorded a really nice piece where he starts downloading the PowerShell bits and walks you though the basic concepts and some more interesting details.

The Case Of The Negative Ping

Posted in Networking at Wednesday, June 06, 2007 12:29 AM W. Europe Daylight Time

Light Speed Recently I've got a new server that will host this blog an other web sites. I hope you'll experience a more stable and faster The Right Stuff since we're still having problems with our DSL line at home. Basically, the attenuation is way too big which causes the occassional disconnect resulting in weird error messages for you, Dear Reader. Downgrading to DSL 3000 wasn't an option until now because we wanted our web sites to be served as fast as possible. But this is all over now, at least for you, and we're just having problems with our internet connection dropping in the middle of a Skype call. Murphy's Law, that's nice.

Today, I was moving Torsten's blog over to the new server (we're sharing the machine and the bills) since I'm kinda of the dasBlog guy here – that's what you become when you've added a bunch of features.

After copying dasBlog's files to the the new machine, I was testing to see if Torsten has already updated the DNS record for the host and ran a ping on the server console. See what I got:

Ping wird ausgeführt für [] mit 32 Bytes Daten:

Antwort von Bytes=32 Zeit=-7ms TTL=128
Antwort von Bytes=32 Zeit=-7ms TTL=128
Antwort von Bytes=32 Zeit=-7ms TTL=128
Antwort von Bytes=32 Zeit=-7ms TTL=128

Ping-Statistik für
    Pakete: Gesendet = 4, Empfangen = 4, Verloren = 0 (0% Verlust),
Ca. Zeitangaben in Millisek.:
    Minimum = -7ms, Maximum = -7ms, Mittelwert = 1073741817ms

Negative ping times and an average roundtrip of 12 hours. Normally you would argue about slow ping times, but this one has been faster than the light. Google to the rescue! A little search revealed that this behaviour is caused by some weird timing issue with the AMD dual core CPU that's built into the server. Because Torsten is a strong advocate of AMD nitpicking on my Intel CPU all the time, I am glad to see that AMD isn't perfect. ;-)

Like this posts suggest one has to update the AMD CPU Windows driver (at the time of writing, it's the last but one download in the list). No big deal after all, but updating critical drivers over a Remote Desktop connection was kinda scary. Some minutes with a heavily-beating heart later, you get ping times you're used to:

Ping wird ausgeführt für [] mit 32 Bytes Daten:

Antwort von Bytes=32 Zeit<1ms TTL=128
Antwort von Bytes=32 Zeit<1ms TTL=128
Antwort von Bytes=32 Zeit<1ms TTL=128
Antwort von Bytes=32 Zeit<1ms TTL=128

Ping-Statistik für
    Pakete: Gesendet = 4, Empfangen = 4, Verloren = 0 (0% Verlust),
Ca. Zeitangaben in Millisek.:
    Minimum = 0ms, Maximum = 0ms, Mittelwert = 0ms

Now Playing [?]: Zero 7Simple things – In the waiting line

Monitoring Servers

Posted in Networking at Friday, April 06, 2007 5:18 PM W. Europe Daylight Time

In case you own a server that is located in your apartment or is hosted at a professional data center, you might find it interesting to know how the server's tasks and services affect the overall load. Load is what you pay for in regard to the hosting provider and it's desirable to have an eye on the server performance.

Of course you could RDP into the server and start up the task manager or the performance monitor. However, this will only give you an impression of the current load. Perfmon is able to record statistics of various performance counters, but downloading the logs and analyzing them locally is quite a hassle. Also, you will have to repeatedly download and analyze logs in order to get an impression how the counter values evolve over time.

What about a easy solution that leverages standards and renders nice graphs? I use MRTG by Tobi Oetiker to monitor some performance counters of the (two) servers I'm in charge of. MRTG, a mature and free addition to the administrator's toolbox, uses SNMP and is able to generate graphs and web sites. Needless to say that MRTG is not targeted to replace advanced approaches to server management like SMS or MOM.

In order to give you an impression what can be achieved with MRTG, take a look at the following screenshot of a web site. The aggregated graphs you see show the activity of our home server over the last 24 hours.

MRTG Aggregate View

A click on any of daily graphs reveal a detailed view depicting the values of the selected counter up to over the last year. See how memory consumption steadily rises?

MRTG Detail View

MRTG is also good for finding temporary problems with server services. If you monitor HTTP connections and find that they come to a grinding halt, chances are that the web server has been running into problems. Of course, an enterprise-ready server monitoring solution would have sent out a notification about the problem in this case.

As said above, MRTG uses SNMP to get its data. However, finding the right SNMP OIDs for the counters you're interested in can be a complicated task because of the hierarchical nature of OIDs. MRTG can also run custom scripts (Batch, WSH, PowerShell, …) to acquire counter data, so you could query WMI (thus, also Windows performance counters), custom log files or any other data source. In this respect, MRTG is pretty powerful.

Data points are stored in log files that virtually newer grow because old data will be coalesced over time. The files take up about 55 KB for each counter on the machine above. Of course, this results in less accuracy for data from weeks ago, but generating 10000-foot-level graphs from these values is perfectly okay.

One tenable drawback of MRTG is that it's only able to acquire data points in 5-minute intervals. To get a higher temporal resolution choose RRDtool by the same author along with any supported application.

In order to get you started with MRTG here are some useful links for installing MRTG on your server:

Now Playing [?]: KoopKoop IslandsLet's elope

Page 1 of 3 in the Networking category Next Page