Cranspassword integration

certbot_on_virtu
Alexandre Iooss 2019-07-30 10:17:07 +02:00
parent 47c8f27682
commit d425f154f5
No known key found for this signature in database
GPG Key ID: 6C79278F3FCDCC02
6 changed files with 129 additions and 41 deletions

2
.gitignore vendored
View File

@ -1 +1,3 @@
*.retry
scripts/inventory_re2o.ini
__pycache__

View File

@ -5,7 +5,8 @@
# Do not create .retry files
retry_files_enabled = False
# Use inventory
# Generate inventory
#inventory = ./scripts/inventory_re2o.py
inventory = ./hosts
# Custom header in templates

View File

@ -1,40 +0,0 @@
$ANSIBLE_VAULT;1.1;AES256
37373933363563303566623732633165343839663164663535316638633462626636326135316534
3839346634623331363336663863353363376665613764390a383866613635363238323637386235
61623963366463636561346162616532626133306165343161393333616363656339643933393531
6662343239653361320a633064306238363836346166653931356334376537636266646237323438
65316261636463336261643831653661383863346633323764346339373834363433373730383861
64613139366566653035656531363933313234343265653535636464323839336165653637323432
61386236383830663230613335303437633737346232316135353262396433376439643562353438
62393431396262383965303436663431326239626666353735636465656530333236326137313062
38323866346433646261633633373031346334396561323536376563363035633565643137346137
33393930326166303439623463623631333339383566383565363536333036626630303130633432
32646364336665363966626665323465346363346137636536303362663935643831326536633739
34353361656635623965383332643936336663373330653563353837353230326531366238353035
32356465653966643831633963623239666136393436663932353366633231343534626234336539
32663133616162366238323635616531373335383535653732373432613938396535343339383037
37376461646438383434633364373339303137333134333138323630633731366533633061373634
38353034356332373134373833393431346539306265313965623663343433343361613634646563
35383234623362633935383362393763363938643864373266336339373265353933336232303965
61666133356430663764323437373632643533333066616232336236633164363965356339326161
63626437663736666536373965316230303239653764356338613638623233643835383637386661
38616330623739306338396639323739383661363431396531613963393732396433346363616438
33303030663231313263616163346563336631643563316465373866383162356562653165333766
33333966303932396336393263363039383930353334313061316335313238363564313639646637
34316562386366306238376465326631336539643936663264306631303335346131343939663965
62316566393236643938633731356465373435646238646661333935323563333231363361663638
31313832613032636466316263386561363665333432653931393835346535653837303937363764
65353561326162313831303865393665353732346536653262316131643863373039636336616132
38666362363137663266306634346438636430353036616536613332376535633662326432383431
66353539376132373165633634376230393738393831313831663535613430633937383732356163
32356639626237303861336364376663306465393130373136366461666233626333346437316563
65616132326637313134656665323439366362613634376536373631656234343934396532333539
62306163313062393365613338326464633136376562383130303638616364366139373734346236
36333665306666633465396437633161356664643235326665633537666366316662643339626430
66393335343463663662363561626534386435373636626131393263626664336164633062393239
39613737383834363661343662323436326236326464343732326232316264303135613035323039
62313539363532333738343664663830373163346436636533663164333438623338623332303136
37633065336162326361333430363464656662626237366530343765643937333866373831666336
36333363633830343836383235613562633435663166386264343936666264323561343938393232
38323235636266616266333535376661663063363562376461336437376661633734633165326661
326437613235333261643465663663343838

View File

@ -0,0 +1,7 @@
# Ansible Re2o Inventory settings
#
[Re2o]
hostname = re2o.example.net
username = my_api_username
password = my_api_password

View File

@ -0,0 +1,6 @@
# Ansible Vault CransPassword settings
#
[cranspassword]
#: Commande exécutée sur le client pour appeler le script sur le serveur distant.
server_cmd=/usr/bin/ssh odlyd.crans.org sudo -n /usr/local/bin/cranspasswords-server

View File

@ -0,0 +1,112 @@
#!/usr/bin/env python
# (c) 2019 Cr@ns <roots@crans.org>
# Authors : Alexandre IOOSS <erdnaxe@crans.org>
# Based on cranspasswords by : Daniel Stan <daniel.stan@crans.org>
# Vincent Le Gallic <legallic@crans.org>
#
# This file is part of Cr@ns ansible deploiement
"""
Ansible Vault CransPassword script.
========================================
Returns Ansible vault from CransPassword.
Configuration is read from `vault_cranspassword.ini`.
"""
import json
import os
import subprocess
import sys
from ansible.module_utils.six.moves import configparser
from ansible.plugins.vars import BaseVarsPlugin
class VarsModule(BaseVarsPlugin):
@staticmethod
def gpg_decrypt(crypt_text):
full_command = ['gpg', '-d']
proc = subprocess.Popen(full_command,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=sys.stderr,
close_fds=True)
proc.stdin.write(crypt_text.encode())
proc.stdin.close()
clear_text = proc.stdout.read().decode()
return clear_text
def getfile_command(self, filename):
"""Exécute la commande distante, et retourne la sortie de cette
commande"""
# Get full command from settings file
command = self.config.get('cranspassword', 'server_cmd').split(" ")
command.append("getfiles")
proc = subprocess.Popen(
command,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=sys.stderr,
close_fds=True
)
proc.stdin.write(json.dumps([filename]).encode())
proc.stdin.flush()
raw_out, raw_err = proc.communicate()
ret = proc.returncode
if ret != 0:
print("Mauvais code retour côté serveur", file=sys.stderr)
sys.exit(ret)
try:
answer = json.loads(raw_out.strip())
except ValueError:
print("Impossible de parser le résultat", file=sys.stderr)
sys.exit(42)
return answer[0]
def get_encrypted(self, filename):
"""
Get encrypted content of a cranspassword file
"""
gotit, value = self.getfile_command(filename)
if not gotit:
print(value, file=sys.stderr) # value contient le message d'erreur
else:
crypt_text = value['contents']
return crypt_text
def __init__(self):
super().__init__()
# Load config
self.config = configparser.ConfigParser()
self.config.read(os.path.dirname(os.path.realpath(__file__))
+ '/vault_cranspassword.ini')
def get_vars(self, loader, path, entities, cache=True):
"""
Get all vars for entities, called by Ansible
"""
super().get_vars(loader, path, entities)
# We do not want to request N time the same file from cranspassword
# But VarsModule object get instanced each time
# So the hack is to use loader._FILE_CACHE that *should* be private
# Sorry for this, don't judge me on this please <3
if 'cranspassword' not in loader._FILE_CACHE:
# Get text then decrypt and return
crypt_text = self.get_encrypted('ansible_vault')
clear_text = self.gpg_decrypt(crypt_text)
data = loader.load(clear_text)
loader._FILE_CACHE['cranspassword'] = data
else:
data = loader._FILE_CACHE['cranspassword']
return data