Task for today was making the NuGet repository of TeamCity available in our local network. Sounds easier as it was as our TeamCity instance is available from the Internet but you can only access the rontend with valid domain credentials (LDAP/Active Directory authentication). Enabling the guest account feature in TeamCity would have mean a small security break in our concept.
Here is the success-story how to enable the NuGet repository for local accesss without authentication and without enabling the TeamCity guest account:
Creating a new proxy instance
One of our Apache servers got the order to act as reverse proxy for the NuGet repository. The reverse proxy was running inside an own virtual host (nuget.mydomain.local) and was registered in our local DNS.
The configuration looked like this:
<VirtualHost *:443> SSLEngine on SSLProxyEngine on ServerAdmin admin@mydomain.local ServerName nuget.mydomain.local ServerAlias nuget.mydomain.de LogLevel warn ErrorLog logs/nuget.mydomain.local-error_log CustomLog logs/nuget.mydomain.local-access_log combined # Map other source to FeedService URL ProxyPass / https://teamcity.mydomain.local:443/guestAuth/app/nuget/v1/FeedService.svc/ ProxyPassReverse / https://teamcity.mydomain.local:443/guestAuth/app/nuget/v1/FeedService.svc/ </VirtualHost>
Adding a domain proxy user
With the configuration above we still have the problem that there is no user who can access the repository without credentials. So we need to add a domain user, let me call it teamcity-nugetfeed-proxy-user. For security reasons this account has a very long random generated password and is only used for providing the NuGet feed.
Using the domain proxy user in our Apache configuration
We have to add a Basic Authorization header in our Apache configuration so that every access between the proxy and TeamCity is authenticated.
RequestHeader set Authorization "Basic <Base64(teamcity-nugetfeed-proxy-user:$password)>"
The phrase <Base64(teamcity-nugetfeed-proxy-user:$password)> must be replaced by an base64-encoded string with format $username:$password.
After restarting the Apache you should be able to use the NuGet stream in Visual Studio. Look at the Apache logs for occuring errors.
TeamCity is failing – NuGet return “File contains corrupted data”
Till yet you are able read the stream but TeamCity will fail downloading your repository files. The reason is easy: The FeedService.svc returns an XML file which contains absolute pathes mapping to teamcity.mydomain.local and not nuget.mydomain.local. So again we have no authorization and the error File contains corrupted data occurs because of the TeamCity login dialogue.
We have to rewrite the content of the FeedService.svc replacing every occurence of teamcity.mydomain… with nuget.mydomain…
At first I tried mod_proxy_html but in the end using mod_substitute was the only solution that worked.
# Rewrite FeedService URL Substitute "s|https://teamcity.mydomain.local/guestAuth/app/nuget/v1/FeedService.svc|https://nuget.mydomain.local|i" # Rewrite repository access Substitute "s|https://teamcity.mydomain.local/guestAuth/repository|https://nuget.mydomain.local/repository|i" # Execute every substitution only for XML/HTML AddOutputFilterByType SUBSTITUTE text/html AddOutputFilterByType SUBSTITUTE text/xml AddOutputFilterByType SUBSTITUTE application/atom+xml # Map local repository path to remote repository ProxyPass /repository https://teamcity.mydomain.local:443/guestAuth/repository ProxyPassReverse /repository https://teamcity.mydomain.local:443/guestAuth/repository # Unset gziped accepted encoding RequestHeader unset Accept-Encoding
After restarting everything should work fine.
The complete configuration is now
<VirtualHost *:443> SSLEngine on SSLProxyEngine on ServerAdmin admin@mydomain.local ServerName nuget.mydomain.local ServerAlias nuget.mydomain.de LogLevel warn ErrorLog logs/nuget.mydomain.local-error_log CustomLog logs/nuget.mydomain.local-access_log combined # Rewrite FeedService URL Substitute "s|https://teamcity.mydomain.local/guestAuth/app/nuget/v1/FeedService.svc|https://nuget.mydomain.local|i" # Rewrite repository access Substitute "s|https://teamcity.mydomain.local/guestAuth/repository|https://nuget.mydomain.local/repository|i" # Map local repository path to remote repository ProxyPass /repository https://teamcity.mydomain.local:443/guestAuth/repository ProxyPassReverse /repository https://teamcity.mydomain.local:443/guestAuth/repository # Map other source to FeedService URL ProxyPass / https://teamcity.mydomain.local:443/guestAuth/app/nuget/v1/FeedService.svc/ ProxyPassReverse / https://teamcity.mydomain.local:443/guestAuth/app/nuget/v1/FeedService.svc/ # Execute every substitution only for XML/HTML AddOutputFilterByType SUBSTITUTE text/html AddOutputFilterByType SUBSTITUTE text/xml AddOutputFilterByType SUBSTITUTE application/atom+xml RequestHeader set Authorization "Basic <Base64(teamcity-nugetfeed-proxy-user:$password)>" # Unset gziped accepted encoding RequestHeader unset Accept-Encoding </VirtualHost>
0 Comments