def post(self): head = request.headers if head.get('Content-Type').startswith("application/json"): data = request.get_json()["certificate"] if data.get("is_acme"): certs = certificates.get() for x in certs: if x.domain == data["domain"] and x.is_acme: emsg = ("You can only have one ACME certificate at a " "time for this domain.") return jsonify(errors={"msg": emsg}), 422 id = as_job(self._request_acme, data) return job_response( id, data={"certificate": {"id": data["id"]}}) else: id = as_job(self._generate, data) return job_response( id, data={"certificate": {"id": data["id"]}}) elif head.get('Content-Type').startswith("multipart/form-data"): name = request.form.get("id") files = [ request.files.get("file[0]").read(), request.files.get("file[1]").read(), request.files.get("file[2]").read() if request.files.get("file[2]") else None] id = as_job(self._upload, name, files) return job_response(id) else: abort(400)
def put(self, id): data = request.get_json()["website"] site = websites.get(id) if not site: abort(404) if data.get("operation") == "enable": site.nginx_enable() elif data.get("operation") == "disable": site.nginx_disable() elif data.get("operation") == "enable_ssl": cert = certificates.get(data["cert"]) cert.assign("website", site.id) elif data.get("operation") == "disable_ssl": site.cert.unassign("website", site.id) elif data.get("operation") == "update": id = as_job(self._put, site) return job_response( id, data={"website": site.serialized.update({"is_ready": False})}) else: site.domain = data["domain"] site.port = data["port"] site.edit(data.get("new_name")) if data.get("new_name"): remove_record("website", id) push_record("website", site.serialized) return jsonify(website=site.serialized)
def delete(id): """Delete a certificate.""" try: cert = certificates.get(id) cert.remove() logger.success('ctl:cert:delete', 'Deleted {0}'.format(id)) except Exception as e: raise CLIException(str(e))
def put(self, id): data = request.get_json()["certificate"] cert = certificates.get(id) other_certs = [x for x in certificates.get() if x.id != id] if not id or not cert: abort(404) for x in other_certs: for y in data["assigns"]: if y in x.assigns: x.unassign(y) push_record("certificate", x.serialized) for x in cert.assigns: if x not in data["assigns"]: cert.unassign(x) for x in data["assigns"]: if x not in cert.assigns: cert.assign(x) return jsonify(certificate=cert.serialized)
def get(self, id): if request.args.get("rescan", None): certificates.scan() certs = certificates.get(id) if id and not certs: abort(404) if isinstance(certs, certificates.Certificate): return jsonify(certificate=certs.serialized) else: return jsonify(certificates=[x.serialized for x in certs])
def get(self, id): if request.args.get("rescan", None): certificates.scan() certs = certificates.get(id) if id and not certs: abort(404) if type(certs) == list: return jsonify(certs=[x.as_dict() for x in certs]) else: return jsonify(cert=certs.as_dict())
def put(self, id): data = json.loads(request.data)["cert"] cert = certificates.get(id) if not id or not cert: abort(404) for x in cert.assigns: if not x in data["assigns"]: cert.unassign(x) for x in data["assigns"]: if not x in cert.assigns: cert.assign(x) return jsonify(cert=cert.as_dict(), message="Certificate updated successfully")
def assign(id, type, appid, specialid): """Assign a certificate to an app or website.""" try: cert = certificates.get(id) cert.assign({ "type": type, "id": appid, "aid": appid, "sid": specialid }) logger.info('ctl:cert:assign', 'Assigned {0} to {0}'.format(id, appid)) except Exception as e: raise CLIException(str(e))
def list_certs(): """List all certificates.""" try: certs = certificates.get() if not certs: logger.info('ctl:cert:list', 'No certificates found') llen = len(sorted(certs, key=lambda x: len(x.id))[-1].id) for x in sorted(certs, key=lambda x: x.id): klkt = "{0}-bit {1}".format(x.keylength, x.keytype) click.echo( click.style('{name: <{fill}}'.format(name=x.id, fill=llen + 3), fg="white", bold=True) + click.style('{name: <15}'.format(name=klkt), fg="green") + click.style(x.domain, fg="yellow")) except Exception as e: raise CLIException(str(e))
def info(name): """Show information about a particular certificate.""" try: cert = certificates.get(name) if not cert: logger.info('ctl:cert:info', 'No certificates found') return click.echo(click.style(cert.id, fg="white", bold=True)) click.echo(click.style(" * Domain: ", fg="yellow") + cert.domain) click.echo( click.style(" * Type: ", fg="yellow") + "{0}-bit {1}".format(cert.keylength, cert.keytype)) click.echo(click.style(" * SHA1: ", fg="yellow") + cert.sha1) click.echo( click.style(" * Expires: ", fg="yellow") + cert.expiry.strftime("%c")) if cert.assigns: imsg = ", ".join([y["name"] for y in cert.assigns]) click.echo(click.style(" * Assigned to: ", fg="yellow") + imsg) except Exception as e: raise CLIException(str(e))
def put(self, id): data = json.loads(request.data)["website"] site = websites.get(id) if not site: abort(404) if data.get("operation") == "enable": site.nginx_enable() elif data.get("operation") == "disable": site.nginx_disable() elif data.get("operation") == "enable_ssl": cert = certificates.get(data["cert"]) cert.assign("website", site.id) elif data.get("operation") == "disable_ssl": site.cert.unassign("website", site.id) elif data.get("operation") == "update": site.update() else: site.addr = data["addr"] site.port = data["port"] site.edit(data.get("new_name")) push_record("website", site.as_dict()) remove_record("website", id) return jsonify(message="Site edited successfully")
def delete(self, id): cert = certificates.get(id) if not id or not cert: abort(404) cert.remove() return Response(status=204)
def app(): """Application commands.""" conns.connect() applications.get(cry=False) certificates.get()
def scan(): """Search website directories for sites, load them and store metadata.""" from arkos import certificates logger.debug("Webs", "Scanning for websites") for x in os.listdir("/etc/nginx/sites-available"): path = os.path.join("/srv/http/webapps", x) if not os.path.exists(path): continue # Read metadata meta = configparser.SafeConfigParser() if not meta.read(os.path.join(path, ".arkos")): continue # Create the proper type of website object app = None app_type = meta.get("website", "app") app = applications.get(app_type) if app and app.type == "website": # If it's a regular website, initialize its class, metadata, etc if not app or not app.loadable or not app.installed: logger.debug( "Webs", "Website found but could not be loaded: {0}".format( meta.get("website", "id"))) continue site = app._website(id=meta.get("website", "id")) site.app = app site.data_path = (meta.get("website", "data_path") or "") \ if meta.has_option("website", "data_path") else "" site.db = databases.get(site.id) \ if meta.has_option("website", "dbengine") else None elif app: # If it's a reverse proxy, follow a simplified procedure site = ReverseProxy(id=meta.get("website", "id")) site.app = app else: # Unknown website type. logger.debug( "Webs", "Unknown website found and ignoring, id {0}".format( meta.get("website", "id"))) continue certname = meta.get("website", "ssl", fallback="None") site.cert = certificates.get(certname) if certname != "None" else None if site.cert: site.cert.assigns.append({ "type": "website", "id": site.id, "name": site.id if site.app else site.name }) site.version = meta.get("website", "version", fallback=None) site.enabled = os.path.exists( os.path.join("/etc/nginx/sites-enabled", x)) site.installed = True # Load the proper nginx serverblock and get more data try: block = nginx.loadf(os.path.join("/etc/nginx/sites-available", x)) for y in block.servers: if "ssl" in y.filter("Key", "listen")[0].value: site.ssl = True server = y break else: server = block.server port_regex = re.compile("(\\d+)\s*(.*)") listen = server.filter("Key", "listen")[0].value.lstrip("[::]:") site.port = int(re.match(port_regex, listen).group(1)) site.domain = server.filter("Key", "server_name")[0].value site.path = server.filter("Key", "root")[0].value site.php = "php" in server.filter("Key", "index")[0].value except IndexError: pass storage.websites[site.id] = site signals.emit("websites", "site_loaded", site) return storage.websites
def scan(): from arkos import certificates sites = [] for x in os.listdir("/etc/nginx/sites-available"): path = os.path.join("/srv/http/webapps", x) if not os.path.exists(path): continue # Read metadata meta = ConfigParser.SafeConfigParser() if not meta.read(os.path.join(path, ".arkos")): continue # Create the proper type of website object site_type = meta.get("website", "type") if site_type != "ReverseProxy": # If it's a regular website, initialize its class, metadata, etc app = applications.get(site_type) if not app.loadable or not app.installed: continue site = app._website(id=meta.get("website", "id")) site.meta = app site.data_path = meta.get("website", "data_path", "") \ if meta.has_option("website", "data_path") else "" site.db = databases.get(site.id) \ if meta.has_option("website", "dbengine") else None else: # If it's a reverse proxy, follow a simplified procedure site = ReverseProxy(id=meta.get("website", "id")) site.name = meta.get("website", "name") site.type = meta.get("website", "extra") site.meta = None certname = meta.get("website", "ssl", "None") site.cert = certificates.get(certname) if certname != "None" else None if site.cert: site.cert.assigns.append({ "type": "website", "id": site.id, "name": site.id if site.meta else site.name }) site.version = meta.get("website", "version", None) site.enabled = os.path.exists(os.path.join("/etc/nginx/sites-enabled", x)) site.installed = True # Load the proper nginx serverblock and get more data try: ssl = None block = nginx.loadf(os.path.join("/etc/nginx/sites-available", x)) for y in block.servers: if "ssl" in y.filter("Key", "listen")[0].value: site.ssl = True server = y break else: server = block.servers[0] port_regex = re.compile("(\\d+)\s*(.*)") site.port = int(re.match(port_regex, server.filter("Key", "listen")[0].value).group(1)) site.addr = server.filter("Key", "server_name")[0].value site.path = server.filter("Key", "root")[0].value site.php = "php" in server.filter("Key", "index")[0].value except IndexError: pass sites.append(site) signals.emit("websites", "site_loaded", site) storage.sites.set("sites", sites) return sites