From d1022a24852f89872487b91cb4478dae8bed10c6 Mon Sep 17 00:00:00 2001 From: mg Date: Wed, 9 Dec 2020 10:21:40 +0100 Subject: [PATCH] Jenkins Integration (#1) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Keepass Info entfernt Bugfix-Pfad Pfad KeepassDB angepasst KeyFile Var entfernt Pluginpfad in ansible.cfg angegeben Rolle mgrote.ansible aus Playbooks entfernt Keepass-Lookup-Plugin in repo gepackt Rolle mgrote.ansible entfernt Playbook mgrote.ansible eingefügt Bugfix Jenkins-Plugins test für jenkins test für jenkins Pfade in ansible.cfg angepasst Plugins und Options Port 80 --> 8080 Housekeeping Java in Playbook geerlingguy.java als submodule Vars ansible und pip Rolle mit become Playbbok und Vars - WIP Variablen ACNG in GroupVars verschoben jenkins admin_name und admin_passwort hinzugefügt in keepass https://github.com/geerlingguy/ansible-role-jenkins als submodule ceph und k8s raus jenkins in inventory Co-authored-by: Michael Grote <38253905+quotengrote@users.noreply.github.com> Reviewed-on: https://git.mgrote.net/mg/ansible/pulls/1 --- .gitmodules | 6 ++ ansible.cfg | 19 +++- group_vars/acng.yml | 3 + group_vars/all.yml | 5 +- group_vars/ansible.yml | 1 - group_vars/jenkins.yml | 30 +++++++ inventory | 23 ++--- keepass_db.kdbx | Bin 11630 -> 11870 bytes playbooks/service/acng.yml | 4 - playbooks/service/ansible.yml | 1 - playbooks/service/jenkins.yml | 7 ++ plugins/lookup/keepass.py | 119 +++++++++++++++++++++++++ roles/geerlingguy.java | 1 + roles/geerlingguy.jenkins | 1 + roles/mgrote.ansible/README.md | 8 -- roles/mgrote.ansible/defaults/main.yml | 0 roles/mgrote.ansible/handlers/main.yml | 0 roles/mgrote.ansible/meta/main.yml | 14 --- roles/mgrote.ansible/tasks/main.yml | 14 --- 19 files changed, 194 insertions(+), 62 deletions(-) create mode 100644 group_vars/jenkins.yml create mode 100644 playbooks/service/jenkins.yml create mode 100644 plugins/lookup/keepass.py create mode 160000 roles/geerlingguy.java create mode 160000 roles/geerlingguy.jenkins delete mode 100644 roles/mgrote.ansible/README.md delete mode 100644 roles/mgrote.ansible/defaults/main.yml delete mode 100644 roles/mgrote.ansible/handlers/main.yml delete mode 100644 roles/mgrote.ansible/meta/main.yml delete mode 100644 roles/mgrote.ansible/tasks/main.yml diff --git a/.gitmodules b/.gitmodules index 89140586..59938208 100644 --- a/.gitmodules +++ b/.gitmodules @@ -31,3 +31,9 @@ [submodule "roles/geerlingguy.dotfiles"] path = roles/geerlingguy.dotfiles url = https://github.com/geerlingguy/ansible-role-dotfiles +[submodule "roles/geerlingguy.jenkins"] + path = roles/geerlingguy.jenkins + url = https://github.com/geerlingguy/ansible-role-jenkins +[submodule "roles/geerlingguy.java"] + path = roles/geerlingguy.java + url = https://github.com/geerlingguy/ansible-role-java diff --git a/ansible.cfg b/ansible.cfg index a53c9f27..5581fb0d 100644 --- a/ansible.cfg +++ b/ansible.cfg @@ -1,9 +1,22 @@ [defaults] -inventory = ~/ansible +inventory = ./inventory nocows = 1 retry_files_enabled = False -roles_path = ~/ansible/roles -vault_password_file = ~/ansible/vault-pass.yml +roles_path = ./roles + +#action_plugins = /usr/share/ansible/plugins/action +#become_plugins = /usr/share/ansible/plugins/become +#cache_plugins = /usr/share/ansible/plugins/cache +#callback_plugins = /usr/share/ansible/plugins/callback +#connection_plugins = /usr/share/ansible/plugins/connection +lookup_plugins = ./plugins/lookup +#inventory_plugins = /usr/share/ansible/plugins/inventory +#vars_plugins = /usr/share/ansible/plugins/vars +#filter_plugins = /usr/share/ansible/plugins/filter +#test_plugins = /usr/share/ansible/plugins/test +#terminal_plugins = /usr/share/ansible/plugins/terminal +#strategy_plugins = /usr/share/ansible/plugins/strategy + [inventory] [privilege_escalation] diff --git a/group_vars/acng.yml b/group_vars/acng.yml index 3836448d..a7a2df93 100644 --- a/group_vars/acng.yml +++ b/group_vars/acng.yml @@ -8,3 +8,6 @@ - rule: allow to_port: 9999 comment: 'acng' + ### mgrote.acng + acng_server_port: 9999 + apt_cacher_ng_exthreshold: "60" #hebt Pakete 60 Tage auf diff --git a/group_vars/all.yml b/group_vars/all.yml index 9ba317a9..522c8805 100644 --- a/group_vars/all.yml +++ b/group_vars/all.yml @@ -66,13 +66,12 @@ ### python3 # https://docs.ansible.com/ansible/latest/reference_appendices/python_3_support.html ansible_python_interpreter: "/usr/bin/python3" - ansible_ssh_private_key_file: /home/mg/ansible/id_rsa_ansible_user # Ansible Plugin Variablen ### Keepass # https://github.com/viczem/ansible-keepass - # liegt unter /home/mg/ansible/.ansible/plugins/keepass.py - keepass_dbx: "/home/mg/ansible/keepass_db.kdbx" + # liegt unter ./plugins/lookup/keepass.py + keepass_dbx: "./keepass_db.kdbx" keepass_psw: !vault | $ANSIBLE_VAULT;1.1;AES256 62383737623066396239383336646164616537646630653964313532383130343533346561633039 diff --git a/group_vars/ansible.yml b/group_vars/ansible.yml index f03558bd..0550bfe4 100644 --- a/group_vars/ansible.yml +++ b/group_vars/ansible.yml @@ -2,7 +2,6 @@ ### geerlingguy.pip pip_package: python3-pip pip_install_packages: - # Specify names and versions. - name: pykeepass - name: Jinja2 - name: markupsafe diff --git a/group_vars/jenkins.yml b/group_vars/jenkins.yml new file mode 100644 index 00000000..3c676990 --- /dev/null +++ b/group_vars/jenkins.yml @@ -0,0 +1,30 @@ +--- + ### geerlingguy.jenkins + jenkins_package_state: latest + jenkins_http_port: 8080 + jenkins_admin_username: "{{ lookup('keepass', 'jenkins_admin_name', 'password') }}" + jenkins_admin_password: "{{ lookup('keepass', 'jenkins_admin_password', 'password') }}" +# jenkins_plugins: +# - name: ansible +# - name: docker + jenkins_plugins_install_dependencies: true + jenkins_plugins_state: latest + jenkins_java_options: "-Djenkins.install.runSetupWizard=true" + ### geerlingguy.pip + pip_package: python3-pip + pip_install_packages: + - name: pykeepass + - name: Jinja2 + - name: markupsafe + ### geerlingguy.ansible + ansible_install_method: pip + ansible_install_version_pip: '2.10' + ### oefenweb.ufw + ufw_rules: + - rule: allow + to_port: 22 + protocol: tcp + comment: 'ssh' + - rule: allow + to_port: 8080 + comment: 'jenkins' diff --git a/inventory b/inventory index 8141c613..22e45b73 100644 --- a/inventory +++ b/inventory @@ -15,6 +15,11 @@ all: fileserver2.grote.lan: fileserver-staging.grote.lan: fileserver-test.grote.lan: + jenkins: + hosts: + jenkins.grote.lan: + jenkins-staging.grote.lan: + jenkins-test.grote.lan: dns: hosts: pi.hole: @@ -53,20 +58,7 @@ all: # qmk: # hosts: # qmk.grote.lan: -# ceph: -# hosts: -# ceph-1.grote.lan: -# ceph-2.grote.lan: -# ceph-3.grote.lan: -# ceph-4.grote.lan: -# ceph-5.grote.lan: -# ceph-6.grote.lan: -# ceph-7.grote.lan: -# k8s: -# hosts: -# k8s-1.grote.lan: -# k8s-2.grote.lan: -# k8s-3.grote.lan: + production: @@ -79,6 +71,7 @@ all: ansible.grote.lan: docker.grote.lan: pve2.grote.lan: + jenkins.grote.lan: staging: hosts: wireguard-staging.grote.lan: @@ -89,6 +82,7 @@ all: ansible-staging.grote.lan: docker-staging.grote.lan: pve-staging.grote.lan: + jenkins-staging.grote.lan: test: hosts: wireguard-test.grote.lan: @@ -101,3 +95,4 @@ all: vm-test.grote.lan: lxc-test.grote.lan: pve-test.grote.lan: + jenkins-test.grote.lan: diff --git a/keepass_db.kdbx b/keepass_db.kdbx index a3894a87cb3de0e4167dc3f09b5a82818bfb93a3..639d05491edc0b0a027587deaba9214b5441f4d7 100644 GIT binary patch literal 11870 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 literal 11630 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 diff --git a/playbooks/service/acng.yml b/playbooks/service/acng.yml index 2765af03..2dc9134a 100644 --- a/playbooks/service/acng.yml +++ b/playbooks/service/acng.yml @@ -2,7 +2,3 @@ - hosts: acng roles: - { role: mgrote.acng, tags: "acng" } - vars: - ### mgrote.acng - acng_server_port: 9999 - apt_cacher_ng_exthreshold: "60" #hebt Pakete 60 Tage auf diff --git a/playbooks/service/ansible.yml b/playbooks/service/ansible.yml index b97700e9..1edb291a 100644 --- a/playbooks/service/ansible.yml +++ b/playbooks/service/ansible.yml @@ -3,4 +3,3 @@ roles: - { role: geerlingguy.pip, tags: "pip", become: true } - { role: geerlingguy.ansible, tags: "ansible", become: true } - - { role: mgrote.ansible, tags: "ansible-mg" } diff --git a/playbooks/service/jenkins.yml b/playbooks/service/jenkins.yml new file mode 100644 index 00000000..c5cdb782 --- /dev/null +++ b/playbooks/service/jenkins.yml @@ -0,0 +1,7 @@ +--- +- hosts: jenkins + roles: + - { role: geerlingguy.pip, tags: "pip", become: true } + - { role: geerlingguy.ansible, tags: "ansible", become: true } + - { role: geerlingguy.java, tags: "java", become: true } + - { role: geerlingguy.jenkins, tags: "jenkins", become: true } diff --git a/plugins/lookup/keepass.py b/plugins/lookup/keepass.py new file mode 100644 index 00000000..c30e480b --- /dev/null +++ b/plugins/lookup/keepass.py @@ -0,0 +1,119 @@ +# -*- coding: utf-8 -*- + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +try: + from __main__ import display +except ImportError: + from ansible.utils.display import Display + display = Display() + +import os +import json +import socket +import tempfile +from pykeepass import PyKeePass +from construct.core import ChecksumError +from ansible.errors import AnsibleError +from ansible.plugins.lookup import LookupBase + + +DOCUMENTATION = """ + lookup: keepass + author: Victor Zemtsov + version_added: '0.2' + short_description: fetch data from KeePass file + description: + - This lookup returns a value of a property of a KeePass entry + - which fetched by given path + options: + _terms: + description: + - first is a path to KeePass entry + - second is a property name of the entry, e.g. username or password + required: True + notes: + - https://github.com/viczem/ansible-keepass + + example: + - "{{ lookup('keepass', 'path/to/entry', 'password') }}" +""" + + +class LookupModule(LookupBase): + keepass = None + + def run(self, terms, variables=None, **kwargs): + if not terms or len(terms) < 2 or len(terms) > 3: + raise AnsibleError('Wrong request format') + entry_path = terms[0].strip('/') + entry_attr = terms[1] + enable_custom_attr = False + + if len(terms) == 3: + enable_custom_attr = terms[2] + + kp_dbx = variables.get('keepass_dbx', '') + kp_dbx = os.path.realpath(os.path.expanduser(kp_dbx)) + if os.path.isfile(kp_dbx): + display.v(u"Keepass: database file %s" % kp_dbx) + + kp_soc = "%s/ansible-keepass.sock" % tempfile.gettempdir() + if os.path.exists(kp_soc): + display.v(u"Keepass: fetch from socket") + return self._fetch_socket(kp_soc, entry_path, entry_attr) + + kp_psw = variables.get('keepass_psw', '') + kp_key = variables.get('keepass_key') + display.v(u"Keepass: fetch from kdbx file") + return self._fetch_file( + kp_dbx, str(kp_psw), kp_key, entry_path, entry_attr, enable_custom_attr) + + def _fetch_file(self, kp_dbx, kp_psw, kp_key, entry_path, entry_attr, enable_custom_attr): + if kp_key: + kp_key = os.path.realpath(os.path.expanduser(kp_key)) + if os.path.isfile(kp_key): + display.vvv(u"Keepass: database keyfile: %s" % kp_key) + + try: + if not LookupModule.keepass: + LookupModule.keepass = PyKeePass(kp_dbx, kp_psw, kp_key) + entry = LookupModule.keepass.\ + find_entries_by_path(entry_path, first=True) + if entry is None: + raise AnsibleError(u"Entry '%s' is not found" % entry_path) + display.vv( + u"KeePass: attr: %s in path: %s" % (entry_attr, entry_path)) + entry_val = None + if enable_custom_attr: + entry_val = entry.get_custom_property(entry_attr) + if entry_val is not None: + return [entry_val] + else: + raise AnsibleError(AttributeError(u"'No custom field property '%s'" % (entry_attr))) + else: + return [getattr(entry, entry_attr)] + except ChecksumError: + raise AnsibleError("Wrong password/keyfile {}".format(kp_dbx)) + except (AttributeError, FileNotFoundError) as e: + raise AnsibleError(e) + + def _fetch_socket(self, kp_soc, entry_path, entry_attr): + display.vvvv(u"KeePass: try to socket connect") + sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + sock.connect(kp_soc) + display.vvvv(u"KeePass: connected") + sock.send(json.dumps({'attr': entry_attr, 'path': entry_path}).encode()) + display.vv(u"KeePass: attr: %s in path: %s" % (entry_attr, entry_path)) + try: + msg = json.loads(sock.recv(1024).decode()) + except json.JSONDecodeError as e: + raise AnsibleError(str(e)) + finally: + sock.close() + display.vvvv(u"KeePass: disconnected") + + if msg['status'] == 'error': + raise AnsibleError(msg['text']) + return [msg['text']] diff --git a/roles/geerlingguy.java b/roles/geerlingguy.java new file mode 160000 index 00000000..2091e47c --- /dev/null +++ b/roles/geerlingguy.java @@ -0,0 +1 @@ +Subproject commit 2091e47c2512415e9ccc84ba269a936e23cc9fc1 diff --git a/roles/geerlingguy.jenkins b/roles/geerlingguy.jenkins new file mode 160000 index 00000000..43ce4e46 --- /dev/null +++ b/roles/geerlingguy.jenkins @@ -0,0 +1 @@ +Subproject commit 43ce4e4608030dd35fbeda0865d779a43e6d9cdb diff --git a/roles/mgrote.ansible/README.md b/roles/mgrote.ansible/README.md deleted file mode 100644 index da1f405a..00000000 --- a/roles/mgrote.ansible/README.md +++ /dev/null @@ -1,8 +0,0 @@ -## mgrote.ansible - -### Beschreibung -Installiert ansible und konfiguriert es damit "cowsay" nicht benutzt wird. - -### Funktioniert auf -- [x] Ubuntu (>=18.04) -- [ ] Debian diff --git a/roles/mgrote.ansible/defaults/main.yml b/roles/mgrote.ansible/defaults/main.yml deleted file mode 100644 index e69de29b..00000000 diff --git a/roles/mgrote.ansible/handlers/main.yml b/roles/mgrote.ansible/handlers/main.yml deleted file mode 100644 index e69de29b..00000000 diff --git a/roles/mgrote.ansible/meta/main.yml b/roles/mgrote.ansible/meta/main.yml deleted file mode 100644 index 97888f33..00000000 --- a/roles/mgrote.ansible/meta/main.yml +++ /dev/null @@ -1,14 +0,0 @@ ---- -dependencies: - - role: geerlingguy.pip -galaxy_info: - author: mgrote - description: configures an ansible-host - min_ansible_version: 2.0 - license: GPLv3 - platforms: - - name: Ubuntu - versions: - - all - galaxy_tags: - - system diff --git a/roles/mgrote.ansible/tasks/main.yml b/roles/mgrote.ansible/tasks/main.yml deleted file mode 100644 index b1067204..00000000 --- a/roles/mgrote.ansible/tasks/main.yml +++ /dev/null @@ -1,14 +0,0 @@ - # pykeepass wird durch geerlingguy.pip mit installiert - # https://github.com/viczem/ansible-keepass#readme - - name: create ~/.ansible/plugins/lookup - become: yes - ansible.builtin.file: - path: /home/mg/.ansible/plugins/lookup - state: directory - - - name: Download keepass.py - become: yes - ansible.builtin.get_url: - url: https://raw.githubusercontent.com/viczem/ansible-keepass/master/keepass.py - dest: /home/mg/.ansible/plugins/lookup/keepass.py - backup: yes