diff --git a/tatu/__init__.py b/tatu/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tatu/api/__init__.py b/tatu/api/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tatu/api/app.py b/tatu/api/app.py new file mode 100644 index 0000000..c921725 --- /dev/null +++ b/tatu/api/app.py @@ -0,0 +1,18 @@ +import falcon +import models +from db.persistence import SQLAlchemySessionManager + +def create_app(): + api = falcon.API(middleware=[SQLAlchemySessionManager()]) + api.add_route('/authorities', models.Authorities()) + api.add_route('/authorities/{uuid}', models.Authority()) + api.add_route('/users/{uuid}/certs', models.UserCerts()) + api.add_route('/users/{uuid}/certs/{fingerprint}', models.UserCert()) + api.add_route('/hosts/{uuid}/certs', models.HostCerts()) + api.add_route('/hosts/{uuid}/certs/{fingerprint}', models.HostCert()) + api.add_route('/host_cert_token', models.Tokens()) + return api + + +def get_app(): + return create_app() diff --git a/tatu/api/models.py b/tatu/api/models.py new file mode 100644 index 0000000..e4bfcdb --- /dev/null +++ b/tatu/api/models.py @@ -0,0 +1,39 @@ +import falcon + + +class Authorities(object): + + def on_post(self, req, resp): + resp.status = falcon.HTTP_400 + +class Authority(object): + + def on_get(self, req, resp): + resp.status = falcon.HTTP_400 + +class UserCerts(object): + + def on_get(self, req, resp): + resp.status = falcon.HTTP_400 + +class UserCert(object): + + def on_get(self, req, resp): + resp.status = falcon.HTTP_400 + + def on_post(self, req, resp): + resp.status = falcon.HTTP_400 + +class HostCerts(object): + + def on_get(self, req, resp): + resp.status = falcon.HTTP_400 + +class HostCert(object): + + def on_get(self, req, resp): + resp.status = falcon.HTTP_400 + + def on_post(self, req, resp): + resp.status = falcon.HTTP_400 + diff --git a/tatu/db/__init__.py b/tatu/db/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tatu/db/models.py b/tatu/db/models.py new file mode 100644 index 0000000..5b59a9d --- /dev/null +++ b/tatu/db/models.py @@ -0,0 +1,74 @@ +import sqlalchemy as sa +from sqlalchemy.ext.declarative import declarative_base +import sshpubkeys + +Base = declarative_base() + +def generate_uuid(): + return str(uuid.uuid4()) + +class Authority(Base): + __tablename__ = 'authorities' + + id = sa.Column(sa.String(36), primary_key=True) + user_pubkey = sa.Column(sa.Text) + user_privkey = sa.Column(sa.Text) + host_pubkey = sa.Column(sa.Text) + host_privkey = sa.Column(sa.Text) + +def createAuthority(session, id, user_pub, user_priv, host_pub, host_priv): + with session: + auth = Authority(id=id, + user_pubkey=user_pub, + user_privkey=user_priv, + host_pubkey=host_pub, + host_privkey=host_priv) + session.add(auth) + session.commit() + return auth + +class UserCert(Base): + __tablename__ = 'user_certs' + + user_id = sa.Column(sa.String(36), primary_key=True) + auth_id = sa.Column(sa.String(36), sa.ForeignKey('authorities.id')) + fingerprint = sa.Column(sa.String(36), primary_key=True) + privkey = sa.Column(sa.Text) + pubkey = sa.Column(sa.Text) + cert = sa.Column(sa.Text) + +def createUser(session, id, auth_id, pub, priv): + with session: + user = User(id=id, + auth_id=auth_id, + pubkey=pub, + privkey=priv) + # Generate the fingerprint from the public key + user.fingerprint = sshpubkeys.SSHKey(pub).hash() + # Retrieve the authority's private key and generate the certificate + + session.add(user) + session.commit() + return user + +class HostCert(Base): + __tablename__ = 'host_certs' + + host_id = sa.Column(sa.String(36), primary_key=True) + fingerprint = sa.Column(sa.String(36), primary_key=True) + privkey = sa.Column(sa.Text) + pubkey = sa.Column(sa.Text) + cert = sa.Column(sa.Text) + +class Tokens(Base): + __tablename__ = 'tokens' + + id = sa.Column(sa.String(36), primary_key=True, + default=generate_uuid) + hostname = sa.Column(sa.String(36)) + instance_id = sa.Column(sa.String(36)) + authority_id = sa.Column(sa.String(36), ForeignKey('authorities.id')) + +def createUserCert(session): + + diff --git a/tatu/db/persistence.py b/tatu/db/persistence.py new file mode 100644 index 0000000..ed52ca7 --- /dev/null +++ b/tatu/db/persistence.py @@ -0,0 +1,27 @@ +import os + +from sqlalchemy import create_engine +from sqlalchemy.orm import sessionmaker, scoped_session + + +def get_url(): + return os.getenv("DATABASE_URL", "sqlite:///development.db") + +class SQLAlchemySessionManager: + """ + Create a scoped session for every request and close it when the request + ends. + """ + + def __init__(self): + self.engine = create_engine(get_url()) + self.Session = scoped_session(sessionmaker(self._engine)) + + def process_resource(self, req, resp, resource, params): + resource.session = self.Session() + + def process_response(self, req, resp, resource, req_succeeded): + if hasattr(resource, 'session'): + if not req_succeeded: + resource.session.rollback() + self.Session.remove()