Apr 10
Artifactory meets VPS
If your using Maven/Gradle/Lein/Buildr to build your projects than you must have stumbled upon one common issue which
is where to host your artifacts,
syncing your local repository between machines is impossible without a proxy, a nice solution is to host it on
a VPS.
I didn't find a single clear source of information on how to do so in a safe manner so ill try to cover the main
points in
this post.
Before going further please take note to the following disclaimer:
Im not a security expert, any damage cause by following these steps is your responsibility.
Lets start with the main components that we are going to use, first is Artifactory my favorite maven proxy that
runs on an embedded jetty server out of the box, its common to place a reverse proxy in front of Java server in order to gain performance (mainly for static
content) and enhanced security.
Iv chosen to deploy Nginx as our proxy since its very lite on resources, offers good performance and has
excellent documentation.
server {
server_name example.com;
listen 80;
location ~ ^/artifactory/(.*)$ {
access_log /var/log/nginx_67_log;
proxy_pass http://127.0.0.1:8081;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
Now that we proxy the traffic from Nginx to Artifactory we need to start thinking on how to protect Artifactory from the outside world, one of the simplest forms of protecting online resources is using basic authentication, in this configuration the user has to provide user name & password in order to access a url:
server {
server_name example.com;
listen 80;
location ~ ^/artifactory/(.*)$ {
auth_basic "Restricted";
auth_basic_user_file /some/path/htpass;
access_log /var/log/nginx_67_log;
proxy_pass http://127.0.0.1:8081;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
We added two new lines to the configuration, the htpass file is the file that contains the user details which are required for authentication, in order to generate this file:
$ sudo aptitude install apache2-utils $ pwgen -s 50 # make sure to use strong passwords! $ htpasswd -c htpass username
Now we should be set to access Artifactory using the credentials we created above, in order to enable maven to use these credentials we can set the following in the settings.xml file (on our client machine):
Artifactory
username
password
username
password
*
repo
http://example.com/artifactory/repo
Artifactory
Wait!, while all this should work it is totally insecure!
Basic authentication is nothing more than a formalized method of sending user name and password out on the clear via
http, its very easy to intercept.
We must make sure that the authentication info is send on an encrypted channel using ssl, in order to enable that we
have to:
- Create a self signed certificate for our server (or buy one from a CA).
- Configure Nginx to use the certificate and change the protocol to ssl on the Artifactory urls.
- Import the certificate to our client (Java or a browser in our case).
Will start with the certificate creation, ill go ahead with the self signed one, this is quite the standard procedure with the only exception of using AES256 instead of DES3:
$ cd /usr/local/nginx/conf
$ openssl genrsa -aes256 -out server.key 1024 # generating a private rsa key
$ openssl req -new -key server.key -out server.csr # create a certificate based upon the key, when asked "Common Name (eg, YOUR name) []:" make sure to use your proper domain name!
$ cp server.key server.key.org # see next
$ openssl rsa -in server.key.org -out server.key # removing the pass phrase of the key
$ openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt # sign certificate with private key (clients use it).
Now lets go ahead & make Nginx use ssl:
server {
server_name example.com;
listen 443;
ssl on;
ssl_certificate /usr/local/nginx/conf/server.crt;
ssl_certificate_key /usr/local/nginx/conf/server.key;
access_log /var/log/nginx/ssl.access.log;
error_log /var/log/nginx/ssl.error.log;
location ~ ^/artifactory/(.*)$ {
auth_basic "Restricted";
auth_basic_user_file /some/path/htpass;
access_log /var/log/nginx_67_log;
proxy_pass http://127.0.0.1:8081;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_read_timeout 500;
proxy_send_timeout 600;
}
}
server { # making sure that the redirects that artifactory makes will remain under https
listen 80;
server_name example.com;
location ~ ^/artifactory/(.*)$ {
rewrite ^(.*) https://$server_name$1 permanent;
}
}
Now all that is left is to import the certificate to our clients, in the case of a browser just add an exception & import it, in the case of Java based tools like Maven we need to import the certificate using Java keytool:
sudo keytool -import -alias example.com -file /some/path/server.crt -keystore /usr/lib/jvm/java-6-sun/jre/lib/security/cacerts
Note that since all Artifactory related traffic is now https so we need to adjust our settings file as well:
*
repo
https://example.com/artifactory/repo
Artifactory
Now that we feel secure & fuzzy all round there is still one issue to consider which is brute force attacks, nothing
stops any one from pounding our server to death using tools like John the
Ripper.
A tool to fight such attacks is fail2ban, this tool polls log files after patterns & triggers iptable drop instructions upon matches, lets go ahead & install it:
$ sudo aptitude install fail2ban
$ sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
Add the following defenition to the jail.local file:
[artifactory] enabled = true port = https filter = nginx-auth logpath = /var/log/nginx/ssl.error.log maxretry = 3 bantime = -1Now lets add the filter to a new file under /etc/fail2ban/filter.d/nginx-auth.conf:
[Definition] failregex = no user/password.*client\: <HOST> user.*authentication failure.*client\: <HOST> user.*not found.*client\: <HOST> user.*password mismatch.*client\: <HOST>Thats a lot of configuration mayham, let me know if you found it useful!

Follow me online