finish vagrant configuration
- ignore collected assets - setup virtualenv and environment variables - import additional salt state modules
This commit is contained in:
		
							parent
							
								
									f5945b9849
								
							
						
					
					
						commit
						1ae6c1e855
					
				
					 9 changed files with 357 additions and 4 deletions
				
			
		|  | @ -27,7 +27,6 @@ EOF | |||
| 
 | ||||
| cat >/etc/salt/grains <<EOF | ||||
| roles: | ||||
|   - webserver | ||||
|   - gnuviechadmin.database | ||||
|   - gnuviechadmin.queues | ||||
|   - gnuviechadmin.webinterface | ||||
|  |  | |||
|  | @ -7,8 +7,7 @@ gnuviechadmin: | |||
|   adminemail: admin@gnuviech-server.de | ||||
|   sitename: Gnuviech Customer Self Service | ||||
|   domainname: localhost | ||||
|   checkout: /srv/www/gnuviechadmin | ||||
|   virtualenv: /home/gva/.virtualenvs/gnuviechadmin | ||||
|   virtualenv: /home/vagrant/gva-venv | ||||
|   devinstance: True | ||||
|   minosuid: 10000 | ||||
|   minosgid: 10000 | ||||
|  |  | |||
							
								
								
									
										117
									
								
								roots/_states/rsa_key.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								roots/_states/rsa_key.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,117 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| # | ||||
| # some internal functions are copied from salt.states.file | ||||
| 
 | ||||
| from Crypto.PublicKey import RSA | ||||
| import os | ||||
| 
 | ||||
| 
 | ||||
| def _check_user(user, group): | ||||
|     ''' | ||||
|     Checks if the named user and group are present on the minion | ||||
|     ''' | ||||
|     err = '' | ||||
|     if user: | ||||
|         uid = __salt__['file.user_to_uid'](user) | ||||
|         if uid == '': | ||||
|             err += 'User {0} is not available '.format(user) | ||||
|     if group: | ||||
|         gid = __salt__['file.group_to_gid'](group) | ||||
|         if gid == '': | ||||
|             err += 'Group {0} is not available'.format(group) | ||||
|     return err | ||||
| 
 | ||||
| 
 | ||||
| def _error(ret, err_msg): | ||||
|     ret['result'] = False | ||||
|     ret['comment'] = err_msg | ||||
|     return ret | ||||
| 
 | ||||
| 
 | ||||
| def _calculate_umask(mode): | ||||
|     mode = str(mode).lstrip('0') | ||||
|     if not mode: | ||||
|         mode = '0' | ||||
|     modeint = int(mode, 8) | ||||
|     return modeint ^ 0777 | ||||
| 
 | ||||
| 
 | ||||
| def valid_key(name, bits=2048, user=None, group=None, mode='0700'): | ||||
|     """ | ||||
|     Make sure that the given key file exists and contains a valid RSA key. | ||||
| 
 | ||||
|     name | ||||
|         The name of the key file to check | ||||
| 
 | ||||
|     bits | ||||
|         Minimum bits for the RSA key | ||||
| 
 | ||||
|     user | ||||
|         The user to own the file, this defaults to the user salt is running as | ||||
|         on the minion | ||||
| 
 | ||||
|     group | ||||
|         The group ownership set for the file, this defaults to the group salt | ||||
|         is running on the minion | ||||
| 
 | ||||
|     mode | ||||
|         The permissions set on the file, this defaults to 0600 | ||||
|     """ | ||||
| 
 | ||||
|     mode = __salt__['config.manage_mode'](mode) | ||||
| 
 | ||||
|     ret = { | ||||
|         'name': name, | ||||
|         'changes': {}, | ||||
|         'result': None, | ||||
|         'comment': ''} | ||||
|     if not os.path.isfile(name) and __opts__['test']: | ||||
|         ret['comment'] = 'would create RSA key in file {0}'.format(name) | ||||
|         return ret | ||||
| 
 | ||||
|     u_check = _check_user(user, group) | ||||
|     if u_check: | ||||
|         return _error(ret, u_check) | ||||
|     if not os.path.isabs(name): | ||||
|         return _error( | ||||
|             ret, 'Specified file {0} is not an absolute path'.format(name)) | ||||
|     if os.path.isdir(name): | ||||
|         return _error( | ||||
|             ret, 'Specified target {0} is a directory'.format(name)) | ||||
|     if os.path.exists(name): | ||||
|         ret, perms = __salt__['file.check_perms']( | ||||
|             name, ret, user, group, mode) | ||||
|         if __opts__['test']: | ||||
|             ret['comment'] = 'File {0} not updated'.format(name) | ||||
|             return ret | ||||
| 
 | ||||
|     if not os.path.isfile(name): | ||||
|         rsa = RSA.generate(bits) | ||||
|         oldumask = os.umask(_calculate_umask(mode)) | ||||
|         with open(name, 'w') as rsafile: | ||||
|             rsafile.write(rsa.exportKey()) | ||||
|         os.umask(oldumask) | ||||
|         ret['comment'] = 'created new RSA key and saved PEM file {0}'.format( | ||||
|             name) | ||||
|         ret['changes']['created'] = name | ||||
|         ret['result'] = True | ||||
|         return ret | ||||
|     try: | ||||
|         with open(name, 'r') as rsafile: | ||||
|             rsa = RSA.importKey(rsafile.read()) | ||||
|     except Exception as e: | ||||
|         ret['comment'] = 'error loading RSA key from file {0}: {1}'.format( | ||||
|             name, e) | ||||
|         ret['result'] = False | ||||
|         return ret | ||||
|     keysize = rsa.size() + 1 | ||||
|     if keysize < bits: | ||||
|         ret['comment'] = ( | ||||
|             'RSA key in {0} is only {1} bits, which is less than the ' | ||||
|             'required {2} bits'.format(name, keysize, bits)) | ||||
|         ret['result'] = False | ||||
|     else: | ||||
|         ret['comment'] = 'RSA key in file {0} is ok ({1} bits)'.format( | ||||
|             name, keysize) | ||||
|         ret['result'] = True | ||||
|     return ret | ||||
							
								
								
									
										61
									
								
								roots/_states/x509_certificate.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								roots/_states/x509_certificate.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,61 @@ | |||
| # -*- coding: utf8 -*- | ||||
| ''' | ||||
| Manage X.509 certificate life cycle | ||||
| =================================== | ||||
| 
 | ||||
| This state is useful for managing X.509 certificates' life cycles. | ||||
| 
 | ||||
| Copyright (c) 2014 Jan Dittberner <jan@dittberner.info> | ||||
| ''' | ||||
| 
 | ||||
| from M2Crypto import X509 | ||||
| from datetime import datetime | ||||
| import os | ||||
| 
 | ||||
| 
 | ||||
| def _error(ret, err_msg): | ||||
|     ret['result'] = False | ||||
|     ret['comment'] = err_msg | ||||
|     return ret | ||||
| 
 | ||||
| 
 | ||||
| def valid_certificate( | ||||
|     name, mindays=14, keyfile=None, | ||||
|     checkchain=False, trustedcerts=None): | ||||
|     ''' | ||||
|     Checks whether the given certificate file is valid. | ||||
| 
 | ||||
|     name | ||||
|         The name of the certificate file to check | ||||
|     mindays | ||||
|         Mark the certificate as invalid if it is valid for less then this many | ||||
|         days | ||||
|     ''' | ||||
|     ret = { | ||||
|         'name': name, | ||||
|         'changes': {}, | ||||
|         'result': None, | ||||
|         'comment': ''} | ||||
|     if not os.path.isfile(name): | ||||
|         return _error( | ||||
|             ret, 'certificate file {0} does not exist'.format(name)) | ||||
|     try: | ||||
|         cert = X509.load_cert(name) | ||||
|     except Exception as e: | ||||
|         return _error( | ||||
|             ret, | ||||
|             'error loading certificate {0}: {1}'.format(name, e)) | ||||
|     notafter = cert.get_not_after().get_datetime() | ||||
|     delta = notafter - datetime.now(notafter.tzinfo) | ||||
|     if delta.days < mindays: | ||||
|         return _error( | ||||
|             ret, | ||||
|             'certificate {0} is only valid for {1} more day(s)'.format( | ||||
|                 name, delta.days)) | ||||
|     # TODO: check keyfile match | ||||
|     # TODO: check trust chain | ||||
|     ret['comment'] = ( | ||||
|         'certificate {0} is ok and still valid for {1} days'.format( | ||||
|             name, delta.days)) | ||||
|     ret['result'] = True | ||||
|     return ret | ||||
							
								
								
									
										27
									
								
								roots/gnuviechadmin/gnuviechadmin.nginx
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								roots/gnuviechadmin/gnuviechadmin.nginx
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,27 @@ | |||
| server { | ||||
|   server_name www.{{ domainname }}; | ||||
|   listen 443 ssl; | ||||
| 
 | ||||
|   ssl_certificate {{ ssl_certdir }}/{{ domainname }}.crt.pem; | ||||
|   ssl_certificate_key {{ ssl_keydir }}/{{ domainname }}.key.pem; | ||||
| 
 | ||||
|   if ( $host != '{{ domainname }}') { | ||||
|     return 301 https://{{ domainname }}$request_uri; | ||||
|   } | ||||
| 
 | ||||
|   client_max_body_size 1M; | ||||
|   gzip on; | ||||
|   gzip_types text/javascript application/x-javascript text/css; | ||||
| 
 | ||||
|   location /media { | ||||
|     alias /vagrant/gnuviechadmin/media; | ||||
|   } | ||||
| 
 | ||||
|   location /static { | ||||
|     alias /vagrant/gnuviechadmin/assets; | ||||
|   } | ||||
| 
 | ||||
|   location / { | ||||
|     proxy_pass http://localhost:8000; | ||||
|   } | ||||
| } | ||||
							
								
								
									
										24
									
								
								roots/gnuviechadmin/gvasettings.sh
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								roots/gnuviechadmin/gvasettings.sh
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,24 @@ | |||
| #!/bin/sh | ||||
| 
 | ||||
| export DJANGO_SETTINGS_MODULE="gnuviechadmin.settings.production" | ||||
| export GVA_ADMIN_NAME="Jan Dittberner" | ||||
| export GVA_ADMIN_EMAIL="{{ salt['pillar.get']('gnuviechadmin:adminemail') }}" | ||||
| export GVA_PGSQL_DATABASE="{{ salt['pillar.get']('gnuviechadmin-database:database') }}" | ||||
| export GVA_PGSQL_USER="{{ salt['pillar.get']('gnuviechadmin-database:owner:user') }}" | ||||
| export GVA_PGSQL_PASSWORD="{{ salt['pillar.get']('gnuviechadmin-database:owner:password') }}" | ||||
| export GVA_PGSQL_HOSTNAME="{{ salt['pillar.get']('gnuviechadmin-database:hostname') }}" | ||||
| export GVA_PGSQL_PORT={{ salt['pillar.get']('gnuviechadmin-database:port') }} | ||||
| export GVA_DOMAIN_NAME="{{ salt['pillar.get']('gnuviechadmin:domainname') }}" | ||||
| export GVA_SITE_NAME="{{ salt['pillar.get']('gnuviechadmin:sitename') }}" | ||||
| export GVA_SITE_SECRET="{{ salt['grains.get_or_set_hash']('gnuviechadmin:SECRET_KEY', 50) }}" | ||||
| export GVA_SITE_ADMINMAIL="{{ salt['pillar.get']('gnuviechadmin:adminemail') }}" | ||||
| export GVA_MIN_OS_UID={{ salt['pillar.get']('gnuviechadmin:minosuid') }} | ||||
| export GVA_MIN_OS_GID={{ salt['pillar.get']('gnuviechadmin:minosgid') }} | ||||
| export GVA_OSUSER_PREFIX="{{ salt['pillar.get']('gnuviechadmin:osuserprefix') }}" | ||||
| export GVA_OSUSER_HOME_BASEPATH="{{ salt['pillar.get']('gnuviechadmin:osuserhomedirbase') }}" | ||||
| export GVA_OSUSER_DEFAULT_SHELL="{{ salt['pillar.get']('gnuviechadmin:osuserdefaultshell') }}" | ||||
| export GVA_BROKER_URL="{{ broker_url }}" | ||||
| export GVA_OSUSER_UPLOADSERVER="{{ salt['pillar.get']('gnuviechadmin:uploadserver') }}" | ||||
| export GVA_WEBMAIL_URL="{{ salt['pillar.get']('gnuviechadmin:webmail_url') }}" | ||||
| export GVA_PHPMYADMIN_URL="{{ salt['pillar.get']('gnuviechadmin:phpmyadmin_url') }}" | ||||
| export GVA_PHPPGADMIN_URL="{{ salt['pillar.get']('gnuviechadmin:phppgadmin_url') }}" | ||||
|  | @ -0,0 +1,97 @@ | |||
| include: | ||||
|   - webserver | ||||
| 
 | ||||
| gnuviechadmin-packages: | ||||
|   pkg.installed: | ||||
|     - names: | ||||
|       - libpq-dev | ||||
|       - libyaml-dev | ||||
|       - python-virtualenv | ||||
|       - python-dev | ||||
|       - python-pip | ||||
| 
 | ||||
| {% import "webserver/sslcert.macros.sls" as sslcert %} | ||||
| 
 | ||||
| {% set venv = salt['pillar.get']('gnuviechadmin:virtualenv') %} | ||||
| {% set domainname = salt['pillar.get']('gnuviechadmin:domainname') %} | ||||
| {{ sslcert.key_cert(domainname) }} | ||||
| 
 | ||||
| {{ venv }}: | ||||
|   file.directory: | ||||
|     - user: vagrant | ||||
|     - group: vagrant | ||||
|     - require: | ||||
|       - cmd: gnuviechadmin-venv | ||||
| 
 | ||||
| /home/vagrant/gvasettings.sh: | ||||
|   file.managed: | ||||
|     - user: vagrant | ||||
|     - group: vagrant | ||||
|     - mode: 0640 | ||||
|     - source: salt://gnuviechadmin/gvasettings.sh | ||||
|     - template: jinja | ||||
|     - context: | ||||
|         broker_url: amqp://{{ salt['pillar.get']('gnuviechadmin-queues:owner:user') }}:{{ salt['pillar.get']('gnuviechadmin-queues:owner:password') }}@mq/{{ salt['pillar.get']('gnuviechadmin-queues:vhost') }} | ||||
| 
 | ||||
| gnuviechadmin-venv: | ||||
|   cmd.run: | ||||
|     - name: virtualenv {{ venv }} | ||||
|     - user: vagrant | ||||
|     - group: vagrant | ||||
|     - unless: test -f {{ venv }}/bin/pip | ||||
| 
 | ||||
| gnuviechadmin-requires: | ||||
|   cmd.run: | ||||
|     - name: {{ venv }}/bin/pip install -U -r requirements/local.txt && touch {{ venv }}/lastinstall | ||||
|     - user: vagrant | ||||
|     - group: vagrant | ||||
|     - cwd: /vagrant | ||||
|     - require: | ||||
|       - file: {{ venv }} | ||||
|       - pkg: python-dev | ||||
|       - pkg: libpq-dev | ||||
|     - unless: test -e {{ venv }}/lastinstall && test /vagrant/requirements/local.txt -ot {{ venv }}/lastinstall && test /vagrant/requirements/base.txt -ot {{ venv }}/lastinstall | ||||
| 
 | ||||
| gnuviechadmin-dbschema: | ||||
|   cmd.wait: | ||||
|     - name: . /home/vagrant/gvasettings.sh ; {{ venv }}/bin/python manage.py migrate --noinput | ||||
|     - user: vagrant | ||||
|     - group: vagrant | ||||
|     - cwd: /vagrant/gnuviechadmin | ||||
|     - watch: | ||||
|       - cmd: gnuviechadmin-requires | ||||
|       - file: /home/vagrant/gvasettings.sh | ||||
| 
 | ||||
| gnuviechadmin-locale-data-compile: | ||||
|   cmd.wait: | ||||
|     - name: . /home/vagrant/gvasettings.sh ; find /vagrant/gnuviechadmin -type d -name 'locale' | while read dir; do cd $(dirname "$dir") ; {{ venv }}/bin/python /vagrant/gnuviechadmin/manage.py compilemessages ; done | ||||
|     - user: vagrant | ||||
|     - group: vagrant | ||||
|     - cwd: /vagrant/gnuviechadmin | ||||
|     - require: | ||||
|       - file: /home/vagrant/gvasettings.sh | ||||
|       - file: {{ venv }} | ||||
| 
 | ||||
| /etc/nginx/sites-available/{{ domainname }}: | ||||
|   file.managed: | ||||
|     - user: root | ||||
|     - group: root | ||||
|     - mode: 0640 | ||||
|     - source: salt://gnuviechadmin/gnuviechadmin.nginx | ||||
|     - template: jinja | ||||
|     - context: | ||||
|         domainname: {{ domainname }} | ||||
|         ssl_keydir: {{ salt['pillar.get']('nginx:sslkeydir', '/etc/nginx/ssl/private') }} | ||||
|         ssl_certdir: {{ salt['pillar.get']('nginx:sslcertdir', '/etc/nginx/ssl/certs') }} | ||||
|     - require: | ||||
|       - pkg: nginx | ||||
|     - watch_in: | ||||
|       - service: nginx | ||||
| 
 | ||||
| /etc/nginx/sites-enabled/{{ domainname }}: | ||||
|   file.symlink: | ||||
|     - target: /etc/nginx/sites-available/{{ domainname }} | ||||
|     - require: | ||||
|       - file: /etc/nginx/sites-available/{{ domainname }} | ||||
|     - watch_in: | ||||
|       - service: nginx | ||||
|  | @ -4,7 +4,7 @@ ssl_ciphers kEECDH+AESGCM:kEECDH+AES:kEECDH:EDH+AESGCM:kEDH+AES:kEDH:AESGCM:ALL: | |||
| ssl_prefer_server_ciphers on; | ||||
| ssl_session_cache shared:SSL:10m; | ||||
| 
 | ||||
| ssl_dhparam {{ salt['pillar.get']('nginx:sslcertdir') }}/dhparams.pem; | ||||
| ssl_dhparam {{ salt['pillar.get']('nginx:sslcertdir', '/etc/nginx/ssl/certs') }}/dhparams.pem; | ||||
| 
 | ||||
| # OCSP stapling | ||||
| ssl_stapling on; | ||||
|  |  | |||
							
								
								
									
										29
									
								
								roots/webserver/sslcert.macros.sls
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								roots/webserver/sslcert.macros.sls
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,29 @@ | |||
| {%- macro key_cert(domain_name) %} | ||||
| {% set nginx_ssl_keydir = salt['pillar.get']('nginx:sslkeydir', '/etc/nginx/ssl/private') %} | ||||
| {% set nginx_ssl_certdir = salt['pillar.get']('nginx:sslcertdir', '/etc/nginx/ssl/certs') %} | ||||
| {% set keyfile = nginx_ssl_keydir + '/' + domain_name + '.key.pem' %} | ||||
| {% set certfile = nginx_ssl_certdir + '/' + domain_name + '.crt.pem' %} | ||||
| 
 | ||||
| {{ keyfile }}: | ||||
|   rsa_key.valid_key: | ||||
|     - bits: {{ salt['pillar.get']('nginx:keylength:' + domain_name, 2048) }} | ||||
|     - require: | ||||
|       - file: {{ nginx_ssl_keydir }} | ||||
|     - require_in: | ||||
|       - file: /etc/nginx/sites-available/{{ domain_name }} | ||||
|       - service: nginx | ||||
| 
 | ||||
| {{ certfile }}: | ||||
|   cmd.run: | ||||
|     - name: openssl req -new -x509 -key {{ keyfile }} -subj '/CN={{ domain_name }}' -days 730 -out {{ certfile }} | ||||
|     - require: | ||||
|       - rsa_key: {{ keyfile }} | ||||
|     - creates: {{ certfile }} | ||||
|   x509_certificate.valid_certificate: | ||||
|     - require: | ||||
|       - file: {{ nginx_ssl_certdir }} | ||||
|       - cmd: {{ certfile }} | ||||
|     - require_in: | ||||
|       - file: /etc/nginx/sites-available/{{ domain_name }} | ||||
|       - service: nginx | ||||
| {% endmacro %} | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue