def _self_signed_crt(j2_ctx, host): from rsconf.pkcli import tls from rsconf import db b = db.secret_path( j2_ctx, _TLS_CA_BASENAME, visibility='host', qualifier=host, ) ca = _crt_create( b, # certificate cannot match host so we just create an arbitrary name lambda: tls.gen_ca_crt('root-ca.' + host, basename=str(b)), ) b = db.secret_path( j2_ctx, _TLS_BASENAME, visibility='host', qualifier=host, ) c = _crt_create( b, lambda: tls.gen_signed_crt(ca.key, str(b), host), ) return c, ca
def _pop_users_flattened(self): jc = self.j2_ctx z = jc.dovecot pw_f = db.secret_path( jc, _PASSWORD_SECRET_JSON_F, visibility=_PASSWORD_VISIBILITY, ) pw_modified = False if pw_f.check(): with pw_f.open() as f: pw_db = pkjson.load_any(f) else: pw_db = pkcollections.Dict() res = [] for u, v in z.pop_users.items(): if not isinstance(v, dict): v = pkcollections.Dict(password=v, username=u) if not v.username in pw_db: pw_modified = True pw_db[v.username] \ = '{' + z.passdb_scheme + '}' + _sha512_crypt(v.password) i = z.base_users.user_spec(u) i.pw_hash = pw_db[v.username] i.username = v.username i.home_d = db.user_home_path(jc, u) res.append(i) self._setup_procmail(i) self.install_access(mode='700', owner=i.uid, group=i.gid) self.install_directory(i.home_d.join(z.user_mail_d)) if pw_modified: pkjson.dump_pretty(pw_db, filename=pw_f) return sorted(res, key=lambda x: x.username)
def _gen_keys(self, jc, z, host): from rsconf import db res = pkcollections.Dict() b = db.secret_path( jc, self.name + '/' + z.user, visibility='channel', ) pkio.mkdir_parent(b) res.host_key_f = b.join('host_key') res.host_key_pub_f = res.host_key_f + '.pub' res.identity_f = b.join('identity') res.identity_pub_f = b.join('identity') + '.pub' for f in res.host_key_f, res.identity_f: if f.exists(): continue subprocess.check_call( [ 'ssh-keygen', '-q', '-t', 'ed25519', '-N', '', '-C', jc.rsconf_db.host, '-f', str(f), ], stderr=subprocess.STDOUT, shell=False, ) return res
def install_crt_and_login(compt, j2_ctx): from rsconf.pkcli import tls if not update_j2_ctx(j2_ctx): return jf = db.secret_path(j2_ctx, _PASSWD_SECRET_JSON_F, visibility=_PASSWD_VISIBILITY) with jf.open() as f: y = pkjson.load_any(jf) u = j2_ctx.rsconf_db.host p = y.get(u, None) if not p: return j2_ctx.docker.auths[j2_ctx.docker_registry.http_addr] = dict( auth=pkcompat.from_bytes( base64.b64encode( pkcompat.to_bytes(u + ':' + pkcompat.from_bytes(p))), ), ) compt.install_access(mode='700', owner=j2_ctx.docker_registry.run_u) crt = component.tls_key_and_crt(j2_ctx, j2_ctx.docker_registry.host).crt if not tls.is_self_signed_crt(crt): return compt.install_directory(_CERTS_D) d = _CERTS_D.join(j2_ctx.docker_registry.http_addr) compt.install_directory(d) compt.install_access(mode='400', owner=j2_ctx.docker_registry.run_u) compt.install_abspath(crt, d.join('ca.crt')) # need in /etc/pki as well (now) # https://success.docker.com/article/i-get-x509-certificate-signed-by-unknown-authority-error-when-i-try-to-login-to-my-dtr-with-default-certificates compt.install_abspath( crt, _CA_TRUST_D.join(j2_ctx.docker_registry.host + '.crt')) compt.append_root_bash('update-ca-trust')
def host_init(j2_ctx, host): from rsconf import db jf = db.secret_path(j2_ctx, _PASSWD_SECRET_JSON_F, visibility=db.VISIBILITY_GLOBAL) if jf.check(): with jf.open() as f: y = pkjson.load_any(f) else: y = pkcollections.Dict() if not host in y: y[host] = _passwd_entry(j2_ctx, host) pkjson.dump_pretty(y, filename=jf) return """install -m 600 /dev/stdin /root/.netrc <<'EOF' machine {} login {} password {} EOF curl {} | install_server={} bash -s {} # On {}: ssh {} true""".format( _vhost(j2_ctx), host, y[host], j2_ctx.rsconf_db.http_host, j2_ctx.rsconf_db.http_host, host, j2_ctx.bkp.primary, host, )
def _find_tls_crt(j2_ctx, domain): from rsconf.pkcli import tls from rsconf import db d = db.secret_path(j2_ctx, TLS_SECRET_SUBDIR, visibility='global') for crt, domains in j2_ctx.component.tls_crt.items(): if domain in domains: return d.join(crt), domains for s in ( domain, domain.replace('.', '_'), '.'.join([_WILDCARD_TLS] + domain.split('.')[1:]), # sirepo.com is in wildcard cert star.sirepo.com _WILDCARD_TLS + '.' + domain, ): src = d.join(s) # due to dots in domain, we can't use ext= if (src + tls.KEY_EXT).check(): return src, domain assert j2_ctx.component.tls_crt_create, \ f'{domain}: tls crt for domain not found' src = d.join(domain) pkio.mkdir_parent_only(src) tls.gen_self_signed_crt(str(src), *domain) return src, domain
def secret_path_value(self, filename, gen_secret=None, visibility=None): from rsconf import db src = db.secret_path(self.hdb, filename, visibility=visibility) if src.check(): return pkio.read_text(src), src assert gen_secret, \ 'unable to generate secret: path={}'.format(src) res = gen_secret() res = pkcompat.from_bytes(self._write_binary(src, res)) return res, src
def host_init(hdb, host): jf = db.secret_path(hdb, _PASSWD_SECRET_JSON_F, visibility=_PASSWD_VISIBILITY) if jf.check(): with jf.open() as f: y = pkjson.load_any(f) else: y = PKDict() assert not host in y, \ '{}: host already exists'.format(host) y[host] = db.random_string() pkjson.dump_pretty(y, filename=jf) pf = db.secret_path(hdb, _PASSWD_SECRET_F, visibility=_PASSWD_VISIBILITY) with pf.open(mode='at') as f: f.write( '{}:{}\n'.format( host, pkcompat.from_bytes( bcrypt.hashpw( pkcompat.to_bytes(y[host]), bcrypt.gensalt(5), ), ), ), )
def setup_cluster(compt, hosts, tls_d, run_u, j2_ctx): from rsconf import db compt.install_access(mode='700', owner=run_u) compt.install_directory(tls_d) b = db.secret_path(j2_ctx, compt.name + '_' + _TLS_BASENAME, visibility='host') pkio.mkdir_parent_only(b) for h in hosts: c, ca = _self_signed_crt(j2_ctx, h) c = _signed_crt(j2_ctx, ca, b.join(h)) d = tls_d.join(h) compt.install_access(mode='700') compt.install_directory(d) compt.install_access(mode='400') # POSIT: sirepo.runner.docker uses {cacert,cert,key}.pem compt.install_abspath(ca.crt, d.join('cacert.pem')) compt.install_abspath(c.crt, d.join('cert.pem')) compt.install_abspath(c.key, d.join('key.pem'))
def _sasl_password_path(j2_ctx): from rsconf import db return db.secret_path(j2_ctx, _SASL_PASSWORD_JSON_F, visibility=db.VISIBILITY_GLOBAL)
def passwd_secret_f(j2_ctx): from rsconf import db return db.secret_path(j2_ctx, PASSWD_SECRET_F, visibility=db.VISIBILITY_GLOBAL)