Remove convertsecrets script, we're done with that
This commit is contained in:
parent
3b74376191
commit
2bbf540945
1 changed files with 0 additions and 217 deletions
217
convertsecrets
217
convertsecrets
|
@ -1,217 +0,0 @@
|
||||||
#!/usr/bin/env nix-shell
|
|
||||||
#!nix-shell -i python3 -p "python3.withPackages(ps: [ ps.pip ps.consul ps.ldap ps.passlib ps.requests ps.six ])"
|
|
||||||
|
|
||||||
# DEPENDENCY: python-consul
|
|
||||||
import consul
|
|
||||||
|
|
||||||
# DEPENDENCY: python-ldap
|
|
||||||
import ldap
|
|
||||||
|
|
||||||
# DEPENDENCY: passlib
|
|
||||||
from passlib.hash import ldap_salted_sha1
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import glob
|
|
||||||
import subprocess
|
|
||||||
import getpass
|
|
||||||
import base64
|
|
||||||
from secrets import token_bytes
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
|
||||||
TODO: this will be a utility to handle secrets in the Consul database
|
|
||||||
for the various components of the Deuxfleurs infrastructure
|
|
||||||
|
|
||||||
Functionnalities:
|
|
||||||
- check that secrets are correctly configured
|
|
||||||
- help user fill in secrets
|
|
||||||
- create LDAP service users and fill in corresponding secrets
|
|
||||||
- maybe one day: manage SSL certificates and keys
|
|
||||||
|
|
||||||
It uses files placed in <module_name>/secrets/* to know what secrets
|
|
||||||
it should handle. These secret files contain directives for what to do
|
|
||||||
about these secrets.
|
|
||||||
|
|
||||||
Example directives:
|
|
||||||
|
|
||||||
USER <description>
|
|
||||||
(a secret that must be filled in by the user)
|
|
||||||
|
|
||||||
USER_LONG <description>
|
|
||||||
(the same, indicates that the secret fits on several lines)
|
|
||||||
|
|
||||||
CMD <command>
|
|
||||||
(a secret that is generated by running this command)
|
|
||||||
|
|
||||||
CMD_ONCE <command>
|
|
||||||
(same, but value is not changed when doing a regen)
|
|
||||||
|
|
||||||
CONST <constant value>
|
|
||||||
(the secret has a constant value set here)
|
|
||||||
|
|
||||||
CONST_LONG
|
|
||||||
<constant value, several lines>
|
|
||||||
(same)
|
|
||||||
|
|
||||||
SERVICE_DN <service name> <service description>
|
|
||||||
(the LDAP DN of a service user)
|
|
||||||
|
|
||||||
SERVICE_PASSWORD <service name>
|
|
||||||
(the LDAP password for the corresponding service user)
|
|
||||||
|
|
||||||
SSL_CERT <cert name> <list of domains>
|
|
||||||
(a SSL domain for the given domains)
|
|
||||||
|
|
||||||
SSL_KEY <cert name>
|
|
||||||
(the SSL key going with corresponding certificate)
|
|
||||||
|
|
||||||
RSA_PUBLIC_KEY <key name> <key description>
|
|
||||||
(a public RSA key)
|
|
||||||
|
|
||||||
RSA_PRIVATE_KEY <key name>
|
|
||||||
(the corresponding private RSA key)
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
# Parameters
|
|
||||||
LDAP_URL = "ldap://localhost:1389"
|
|
||||||
SERVICE_DN_SUFFIX = "ou=services,ou=users,dc=deuxfleurs,dc=fr"
|
|
||||||
consul_server = consul.Consul()
|
|
||||||
|
|
||||||
|
|
||||||
# ----
|
|
||||||
|
|
||||||
USER = "USER"
|
|
||||||
USER_LONG = "USER_LONG"
|
|
||||||
CMD = "CMD"
|
|
||||||
CMD_ONCE = "CMD_ONCE"
|
|
||||||
CONST = "CONST"
|
|
||||||
CONST_LONG = "CONST_LONG"
|
|
||||||
SERVICE_DN = "SERVICE_DN"
|
|
||||||
SERVICE_PASSWORD = "SERVICE_PASSWORD"
|
|
||||||
SSL_CERT = "SSL_CERT"
|
|
||||||
SSL_KEY = "SSL_KEY"
|
|
||||||
RSA_PUBLIC_KEY = "RSA_PUBLIC_KEY"
|
|
||||||
RSA_PRIVATE_KEY = "RSA_PRIVATE_KEY"
|
|
||||||
|
|
||||||
class bcolors:
|
|
||||||
HEADER = '\033[95m'
|
|
||||||
OKBLUE = '\033[94m'
|
|
||||||
OKCYAN = '\033[96m'
|
|
||||||
OKGREEN = '\033[92m'
|
|
||||||
WARNING = '\033[93m'
|
|
||||||
FAIL = '\033[91m'
|
|
||||||
ENDC = '\033[0m'
|
|
||||||
BOLD = '\033[1m'
|
|
||||||
UNDERLINE = '\033[4m'
|
|
||||||
|
|
||||||
def read_secret(key, file_path):
|
|
||||||
lines = [l.strip() for l in open(file_path, "r")]
|
|
||||||
if len(lines) == 0:
|
|
||||||
print(bcolors.FAIL, "ERROR:", bcolors.ENDC, "Empty file in", file_path)
|
|
||||||
sys.exit(-1)
|
|
||||||
l0 = lines[0].split(" ")
|
|
||||||
stype = l0[0]
|
|
||||||
secret = {"type": stype, "key": key}
|
|
||||||
if stype in [USER, USER_LONG]:
|
|
||||||
secret["desc"] = " ".join(l0[1:])
|
|
||||||
elif stype in [CMD, CMD_ONCE]:
|
|
||||||
secret["cmd"] = " ".join(l0[1:])
|
|
||||||
elif stype == CONST:
|
|
||||||
secret["value"] = " ".join(l0[1:])
|
|
||||||
elif stype == CONST_LONG:
|
|
||||||
secret["value"] = "\n".join(lines[1:])
|
|
||||||
elif stype in [SERVICE_DN, SERVICE_PASSWORD]:
|
|
||||||
secret["service"] = l0[1]
|
|
||||||
if stype == SERVICE_DN:
|
|
||||||
secret["service_desc"] = " ".join(l0[2:])
|
|
||||||
elif stype in [SSL_CERT, SSL_KEY]:
|
|
||||||
secret["cert_name"] = l0[1]
|
|
||||||
if stype == SSL_CERT:
|
|
||||||
secret["cert_domains"] = l0[2:]
|
|
||||||
elif stype in [RSA_PUBLIC_KEY, RSA_PRIVATE_KEY]:
|
|
||||||
secret["key_name"] = l0[1]
|
|
||||||
if stype == RSA_PUBLIC_KEY:
|
|
||||||
secret["key_desc"] = " ".join(l0[2:])
|
|
||||||
else:
|
|
||||||
print(bcolors.FAIL, "ERROR:", bcolors.ENDC, "Invalid secret type", stype, "in", file_path)
|
|
||||||
sys.exit(-1)
|
|
||||||
|
|
||||||
return secret
|
|
||||||
|
|
||||||
def read_secrets(module_list):
|
|
||||||
secrets = {}
|
|
||||||
for mod in module_list:
|
|
||||||
for file_path in glob.glob(mod.strip('/') + "/secrets/**", recursive=True):
|
|
||||||
if os.path.isfile(file_path):
|
|
||||||
key = '/'.join(file_path.split("/")[1:])
|
|
||||||
secrets[key] = read_secret(key, file_path)
|
|
||||||
return secrets
|
|
||||||
|
|
||||||
def convert_secrets(module_list):
|
|
||||||
for mod in module_list:
|
|
||||||
print("converting module: ", mod)
|
|
||||||
secrets = read_secrets([mod])
|
|
||||||
with open(os.path.join(mod.strip('/'), "secrets.toml"), "w") as file:
|
|
||||||
for (secret_key, secret) in secrets.items():
|
|
||||||
file.write("[secrets.\"{}\"]\n".format("/".join(secret_key.split("/")[1:])))
|
|
||||||
ty = secret["type"]
|
|
||||||
if ty in [CMD, CMD_ONCE]:
|
|
||||||
newsecret = {
|
|
||||||
"type": "command",
|
|
||||||
"rotate": ty != "CMD_ONCE",
|
|
||||||
"command": secret["cmd"],
|
|
||||||
}
|
|
||||||
elif ty in [USER, USER_LONG]:
|
|
||||||
newsecret = {
|
|
||||||
"type": "user",
|
|
||||||
"multiline": ty == "USER_LONG",
|
|
||||||
"description": secret["desc"],
|
|
||||||
}
|
|
||||||
elif ty in [CONST, CONST_LONG]:
|
|
||||||
newsecret = {
|
|
||||||
"type": "constant",
|
|
||||||
"value": secret["value"],
|
|
||||||
}
|
|
||||||
else:
|
|
||||||
newsecret = {
|
|
||||||
"type": secret["type"],
|
|
||||||
}
|
|
||||||
if "service_desc" in secret:
|
|
||||||
newsecret["description"] = secret["service_desc"]
|
|
||||||
if "key_desc" in secret:
|
|
||||||
newsecret["description"] = secret["key_desc"]
|
|
||||||
if "cert_name" in secret:
|
|
||||||
newsecret["name"] = secret["cert_name"]
|
|
||||||
if "key_name" in secret:
|
|
||||||
newsecret["name"] = secret["key_name"]
|
|
||||||
for k in ["service", "cert_domains"]:
|
|
||||||
if k in secret:
|
|
||||||
newsecret[k] = secret[k]
|
|
||||||
for (k, v) in newsecret.items():
|
|
||||||
if type(v) == bool:
|
|
||||||
if v:
|
|
||||||
file.write("{} = true\n".format(k))
|
|
||||||
elif type(v) == str:
|
|
||||||
file.write("{} = {}\n".format(k, repr(v)))
|
|
||||||
else:
|
|
||||||
print("warning: invalid value: ", v)
|
|
||||||
print("secret to fix: ", k)
|
|
||||||
file.write("{} = {}\n".format(k, repr(repr(v))))
|
|
||||||
file.write("\n")
|
|
||||||
|
|
||||||
|
|
||||||
# ---- MAIN ----
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
for i, val in enumerate(sys.argv):
|
|
||||||
if val == "convert":
|
|
||||||
convert_secrets(sys.argv[i+1:])
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
print("Usage:")
|
|
||||||
print(" convertsecrets convert <module name>...")
|
|
||||||
|
|
||||||
|
|
||||||
# vim: set sts=4 ts=4 sw=4 tw=0 ft=python et :
|
|
Loading…
Reference in a new issue