Difference between revisions of "Git, Apache and HTTPS with a free certificate"

From Wiki de Caballero
Jump to navigation Jump to search
Line 152: Line 152:
Notes:
Notes:
* default-ssl.conf configures a site using the certificate but you must be careful to show only what you want to show, for instance copy some of the configuration from the 000-default.conf like DocumentRoot and additional custom information.
* default-ssl.conf configures a site using the certificate but you must be careful to show only what you want to show, for instance copy some of the configuration from the 000-default.conf like DocumentRoot and additional custom information.
* This is the default default-ssl.conf file with the the changes made in the previous instructions:<div class="mw-collapsible mw-collapsed">
* This is the default default-ssl.conf file with the the changes made in the previous instructions:
<div class="mw-collapsible mw-collapsed">
/etc/apache2/sites-available/default-ssl.conf
/etc/apache2/sites-available/default-ssl.conf
<div class="mw-collapsible-content"><source lang="apache">

<div class="mw-collapsible-content"><source lang="apache">


Revision as of 19:27, 23 June 2017

Prerequisites

  • Ubuntu CLI understanding
  • Git knowledge
  • Ubuntu, this was tested using Ubuntu 16
  • Apache 2

Git using Apache

This is a basic setup to allow Git on a server to be accessible via HTTP (no HTTPS yet, read further).

  1.  Install Apache
    sudo apt-get install apache2 apache2-utils
  2. Enable necessary modules
    a2enmod cgi alias env
  3. (Optional) Add user(s) to the htpasswd file. This step is optional if this setup is going to serve only anonymous repository (pull/fetch). However if you want to push or if you want to allow to only obtain a repository using user/pass combo this step is necessary (see next step).
    # Create file and add a user
    # -c = create file
    # The file is stored in /git/ the git repository for this specific setup
    htpasswd -c /git/.htpasswd [user name]
    # This will ask for a password
    
    # Add a user to the file
    htpasswd /git/.htpasswd [user name]
  4. To allow to obtain a git repository using http, add the following to the apache2.conf
    # Path to the Git directory (inside the OS)
    SetEnv GIT_PROJECT_ROOT /git
    
    # Allows all projects to be served
    # If commented a file must exist in each available repository via Apache, file name: git-daemon-export-ok
    SetEnv GIT_HTTP_EXPORT_ALL
    
    # Defines the URL path where git is located, as seen via http
    # First param is path, second is os path to git-http-backend, don't forget the last slash
    ScriptAlias /git/ /usr/lib/git-core/git-http-backend/
    
    # Access configuration
    <Files "git-http-backend">
    	# Enable Basic HTTP Authentication
    	AuthType Basic
    	AuthName "Git Access"
    	AuthUserFile /git/.htpasswd
    	# The following line allows to obtain a repository (pull/fetch) without having a user/pass combo
    	# Comment it if user/pass are needed to obtain info as well
    	Require expr !(%{QUERY_STRING} -strmatch '*service=git-receive-pack*' || %{REQUEST_URI} =~ m#/git-receive-pack$#)
    	Require valid-user
    	# END Enable Basic HTTP Authentication
    </Files>

Additional info:

Self signed Certificate

How Certificates work

Here are some videos on how certificates and SSL (TLS) work:

Additional info:

Why certificates are needed

To allow git to be served using https the server must have a certificate. Now, this certificate can be signed by a root Certificate Authority (CA), an Intermediate Cerfificate Authority (validated by a root CA) or a self signed certificate. To get a root or intermediate CA Certificate you must contact a company to give you one and pay for it. You could also create your own root or intermediate CA but this outside the scope of this article.

How to create a Self-Signed Certificate

Disclaimer: I am not an expert in OpenSSL, these are my tests and I might have made wrong assumptions. Please read the OpenSSL docs.

This is done on an Ubuntu 16 but you could do this in another system, you do need OpenSSl. The process is actually very simple.

Here are three ways of creating a Self-Signed Certificate:

# Way 1 - One line
# ********************
# This command outputs two files, the private key and the certificate. The certificate will be valid for 1 year (use '-days [number]' to change this).
#
#
# -nodes = not encrypted, if you leave this out, Apache will ask for a password when using the private key
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout selfsigned.key -out selfsigned.crt


# Way 2 - Two steps
# ********************
# First the key is generated and second the certificate is generated using the generated key.
#
# Step 1: Generate the Private Key
# Step 1 - Option 1) -des3 encrypts the key, Apache will ask for a password when using the private key
openssl genrsa -des3 -out selfsigned.key 2048
# Step 1 - Option 2) No key encryption
openssl genrsa -out selfsigned.key 2048
#
# Step 2
# The certificate will be valid for 1 year (use '-days [number]' to change this).
openssl req -x509 -new -key selfsigned.key -out selfsigned.crt


# Way 3 - Three steps
# ********************
# First the key is generated, then a signing request is generated and finally the certificate is generated using the generated key and the signing request.
#
# Step 1: Generate the Private Key
# Step 1 - Option 1) -des3 encrypts the key, Apache will ask for a password when using the private key
openssl genrsa -des3 -out selfsigned.key 2048
# Step 1 - Option 2) No key encryption
openssl genrsa -out selfsigned.key 2048
#
# Step 2: Generate the Signing Request (.csr = Certificate Signing Request)
openssl req -new -key selfsigned.key -out selfsigned.csr
#
# Step 3: Generate the certificate using the Private Key and the Signing Request
# The certificate will be valid for 1 year (use '-days [number]' to change this).
openssl x509 -req -in selfsigned.csr -signkey selfsigned.key -out selfsigned.crt



# Check the certificate (a.k.a. see what's inside)
# ********************
openssl x509 -text -noout -in selfsigned.crt



Sources:

More info on how to create a root Certificate and how to create a Certificate Authority

Configuring Apache to use https

This are the steps to allow Apache to use https:

  1. Pick a location for the certificates and move them there (they could also be linked or copied), the location used in this example will be /etc/apache2/ssl.
  2. Enable SSL module for Apache:
    a2enmod ssl
  3. Edit /etc/apache2/sites-available/default-ssl.conf, change (or add) the following lines to point to the certificate and the private key:
    	# Certificate file
    	SSLCertificateFile	/etc/apache2/ssl/selfsigned.crt
    	# Private key
    	SSLCertificateKeyFile	/etc/apache2/ssl/selfsigned.key

  4. Enable the default ssl site:
    a2ensite default-ssl.conf
  5. Restart Apache:
    service apache2 restart

Notes:

  • default-ssl.conf configures a site using the certificate but you must be careful to show only what you want to show, for instance copy some of the configuration from the 000-default.conf like DocumentRoot and additional custom information.
  • This is the default default-ssl.conf file with the the changes made in the previous instructions:

/etc/apache2/sites-available/default-ssl.conf



<IfModule mod_ssl.c>
	<VirtualHost _default_:443>
		ServerAdmin webmaster@localhost

		DocumentRoot /var/www/html

		# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
		# error, crit, alert, emerg.
		# It is also possible to configure the loglevel for particular
		# modules, e.g.
		#LogLevel info ssl:warn

		ErrorLog ${APACHE_LOG_DIR}/error.log
		CustomLog ${APACHE_LOG_DIR}/access.log combined

		# For most configuration files from conf-available/, which are
		# enabled or disabled at a global level, it is possible to
		# include a line for only one particular virtual host. For example the
		# following line enables the CGI configuration for this host only
		# after it has been globally disabled with "a2disconf".
		#Include conf-available/serve-cgi-bin.conf

		#   SSL Engine Switch:
		#   Enable/Disable SSL for this virtual host.
		SSLEngine on

		#   A self-signed (snakeoil) certificate can be created by installing
		#   the ssl-cert package. See
		#   /usr/share/doc/apache2/README.Debian.gz for more info.
		#   If both key and certificate are stored in the same file, only the
		#   SSLCertificateFile directive is needed.
		SSLCertificateFile	/etc/apache2/ssl/selfsigned.crt
		SSLCertificateKeyFile /etc/apache2/ssl/selfsigned.key

		#   Server Certificate Chain:
		#   Point SSLCertificateChainFile at a file containing the
		#   concatenation of PEM encoded CA certificates which form the
		#   certificate chain for the server certificate. Alternatively
		#   the referenced file can be the same as SSLCertificateFile
		#   when the CA certificates are directly appended to the server
		#   certificate for convinience.
		#SSLCertificateChainFile /etc/apache2/ssl.crt/server-ca.crt

		#   Certificate Authority (CA):
		#   Set the CA certificate verification path where to find CA
		#   certificates for client authentication or alternatively one
		#   huge file containing all of them (file must be PEM encoded)
		#   Note: Inside SSLCACertificatePath you need hash symlinks
		#		 to point to the certificate files. Use the provided
		#		 Makefile to update the hash symlinks after changes.
		#SSLCACertificatePath /etc/ssl/certs/
		#SSLCACertificateFile /etc/apache2/ssl.crt/ca-bundle.crt

		#   Certificate Revocation Lists (CRL):
		#   Set the CA revocation path where to find CA CRLs for client
		#   authentication or alternatively one huge file containing all
		#   of them (file must be PEM encoded)
		#   Note: Inside SSLCARevocationPath you need hash symlinks
		#		 to point to the certificate files. Use the provided
		#		 Makefile to update the hash symlinks after changes.
		#SSLCARevocationPath /etc/apache2/ssl.crl/
		#SSLCARevocationFile /etc/apache2/ssl.crl/ca-bundle.crl

		#   Client Authentication (Type):
		#   Client certificate verification type and depth.  Types are
		#   none, optional, require and optional_no_ca.  Depth is a
		#   number which specifies how deeply to verify the certificate
		#   issuer chain before deciding the certificate is not valid.
		#SSLVerifyClient require
		#SSLVerifyDepth  10

		#   SSL Engine Options:
		#   Set various options for the SSL engine.
		#   o FakeBasicAuth:
		#	 Translate the client X.509 into a Basic Authorisation.  This means that
		#	 the standard Auth/DBMAuth methods can be used for access control.  The
		#	 user name is the `one line' version of the client's X.509 certificate.
		#	 Note that no password is obtained from the user. Every entry in the user
		#	 file needs this password: `xxj31ZMTZzkVA'.
		#   o ExportCertData:
		#	 This exports two additional environment variables: SSL_CLIENT_CERT and
		#	 SSL_SERVER_CERT. These contain the PEM-encoded certificates of the
		#	 server (always existing) and the client (only existing when client
		#	 authentication is used). This can be used to import the certificates
		#	 into CGI scripts.
		#   o StdEnvVars:
		#	 This exports the standard SSL/TLS related `SSL_*' environment variables.
		#	 Per default this exportation is switched off for performance reasons,
		#	 because the extraction step is an expensive operation and is usually
		#	 useless for serving static content. So one usually enables the
		#	 exportation for CGI and SSI requests only.
		#   o OptRenegotiate:
		#	 This enables optimized SSL connection renegotiation handling when SSL
		#	 directives are used in per-directory context.
		#SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire
		<FilesMatch "\.(cgi|shtml|phtml|php)$">
				SSLOptions +StdEnvVars
		</FilesMatch>
		<Directory /usr/lib/cgi-bin>
				SSLOptions +StdEnvVars
		</Directory>

		#   SSL Protocol Adjustments:
		#   The safe and default but still SSL/TLS standard compliant shutdown
		#   approach is that mod_ssl sends the close notify alert but doesn't wait for
		#   the close notify alert from client. When you need a different shutdown
		#   approach you can use one of the following variables:
		#   o ssl-unclean-shutdown:
		#	 This forces an unclean shutdown when the connection is closed, i.e. no
		#	 SSL close notify alert is send or allowed to received.  This violates
		#	 the SSL/TLS standard but is needed for some brain-dead browsers. Use
		#	 this when you receive I/O errors because of the standard approach where
		#	 mod_ssl sends the close notify alert.
		#   o ssl-accurate-shutdown:
		#	 This forces an accurate shutdown when the connection is closed, i.e. a
		#	 SSL close notify alert is send and mod_ssl waits for the close notify
		#	 alert of the client. This is 100% SSL/TLS standard compliant, but in
		#	 practice often causes hanging connections with brain-dead browsers. Use
		#	 this only for browsers where you know that their SSL implementation
		#	 works correctly.
		#   Notice: Most problems of broken clients are also related to the HTTP
		#   keep-alive facility, so you usually additionally want to disable
		#   keep-alive for those clients, too. Use variable "nokeepalive" for this.
		#   Similarly, one has to force some clients to use HTTP/1.0 to workaround
		#   their broken HTTP/1.1 implementation. Use variables "downgrade-1.0" and
		#   "force-response-1.0" for this.
		# BrowserMatch "MSIE [2-6]" \
		#		nokeepalive ssl-unclean-shutdown \
		#		downgrade-1.0 force-response-1.0

	</VirtualHost>
</IfModule>

# vim: syntax=apache ts=4 sw=4 sts=4 sr noet

Sources:

https://www.digicert.com/ssl-certificate-installation-apache.htm

Forcing the right protocol:

Other links:

Configuring Git to use the self signed certificate

More sites:

Client based authentication using certificates in Apache

Used links:

Other links:

(Possibly) Giving Git a Client Certificate

More (possibly useful) info

Further reading