summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Heimes <christian@python.org>2015-10-15 15:27:23 +0200
committerChristian Heimes <christian@python.org>2015-10-15 15:27:23 +0200
commit5be736d996f8c6cc85c4d6e859deeea7f7088698 (patch)
tree9a7ccbbfa609b9f150c69048dfb402aee672a448
downloadcustodia_pwmgr-5be736d996f8c6cc85c4d6e859deeea7f7088698.tar.gz
custodia_pwmgr-5be736d996f8c6cc85c4d6e859deeea7f7088698.tar.xz
custodia_pwmgr-5be736d996f8c6cc85c4d6e859deeea7f7088698.zip
Initial commit of Custodia client API example
-rw-r--r--.dockerignore5
-rw-r--r--.gitignore6
-rw-r--r--Dockerfile15
-rw-r--r--README.txt2
-rwxr-xr-xcustodia_pwmgr/custodia_pwmgr.py126
-rw-r--r--custodia_pwmgr/static/style.css19
-rw-r--r--custodia_pwmgr/templates/canvas.html11
-rw-r--r--custodia_pwmgr/templates/index.html28
-rw-r--r--kubernetes/custodia-pwmgr-rc.yaml35
-rw-r--r--kubernetes/custodia-pwmgr-service.yaml14
-rw-r--r--requirements.txt5
-rwxr-xr-xrun.sh7
12 files changed, 273 insertions, 0 deletions
diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..0bdbbbf
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,5 @@
+*.pyc
+.*swp
+__pycache__
+
+kubernetes
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e21be1b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+*.pyc
+.*swp
+__pycache__
+
+custodia
+
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..af9f467
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,15 @@
+FROM fedora
+MAINTAINER Christian Heimes
+
+RUN dnf -y update && dnf clean all
+RUN dnf -y install dnf-plugins-core python python-flask python-requests && \
+ dnf clean all
+RUN dnf -y copr enable simo/jwcrypto && \
+ dnf -y install python-jwcrypto python-cryptography && \
+ dnf clean all
+
+ADD . /custodia_pwmgr
+
+EXPOSE 5000
+
+CMD ["/custodia_pwmgr/run.sh"]
diff --git a/README.txt b/README.txt
new file mode 100644
index 0000000..05c4f2f
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,2 @@
+Custodia client API example
+
diff --git a/custodia_pwmgr/custodia_pwmgr.py b/custodia_pwmgr/custodia_pwmgr.py
new file mode 100755
index 0000000..02f8f9b
--- /dev/null
+++ b/custodia_pwmgr/custodia_pwmgr.py
@@ -0,0 +1,126 @@
+#!/usr/bin/env python2.7
+#
+# Authors:
+# Christian Heimes <cheimes@redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Copyright (C) 2015 Red Hat, Inc.
+# All rights reserved.
+"""Custodia client API example
+"""
+
+import os
+import stat
+import sys
+from urllib import quote
+
+from flask import Flask, flash, render_template, redirect, request, url_for
+from custodia.client import CustodiaClient
+from requests.exceptions import HTTPError
+
+# get Unix socket from env
+CUSTODIA_SOCKET = os.environ.get('CUSTODIA_SOCKET')
+if CUSTODIA_SOCKET is None:
+ sys.exit('Please set CUSTODIA_SOCKET env var')
+s = os.stat(CUSTODIA_SOCKET)
+if not stat.S_ISSOCK(s.st_mode):
+ sys.exit('%s is not a socket' % CUSTODIA_SOCKET)
+del s
+
+
+app = Flask(__name__)
+app.config.update(
+ CUSTODIA_URL='http+unix://%s/secrets' % quote(CUSTODIA_SOCKET, safe=''),
+ # custodia_timeout=2,
+ CUSTODIA_CONTAINER='pwmgr',
+ SECRET_KEY='neHoch4doichu9el',
+ DEBUG=True,
+)
+
+
+class FlaskCustodia(object):
+ def __init__(self, app=None):
+ if app is not None:
+ self.init_app(app)
+
+ def init_app(self, app):
+ url = app.config['CUSTODIA_URL']
+ # timeout = app.config.get('custodia_timeout')
+ self._container = app.config['CUSTODIA_CONTAINER']
+ self._client = CustodiaClient(url)
+ self._client.headers['REMOTE_USER'] = self._container
+ self.mkcontainer()
+
+ def _genpath(self, key):
+ if set(key) & set('/.'):
+ raise ValueError(key)
+ return '/'.join((self._container, key))
+
+ def mkcontainer(self):
+ try:
+ self._client.create_container(self._container)
+ except HTTPError as e:
+ if e.response.status_code != 409:
+ raise
+ return False
+ else:
+ return True
+
+ def items(self):
+ r = self._client.list_container(self._container)
+ return r.json()
+
+ def get_simple(self, name):
+ return self._client.get_simple_key(
+ self._genpath(name))
+
+ def set_simple(self, name, value):
+ if not isinstance(value, basestring):
+ raise TypeError(value)
+ return self._client.set_simple_key(
+ self._genpath(name), value)
+
+ def delete(self, name):
+ return self._client.del_key(self._genpath(name))
+
+
+flaskcustodia = FlaskCustodia(app)
+
+
+@app.route('/')
+def index():
+ # flaskcustodia.set_simple('key', 'password')
+ items = flaskcustodia.items()
+ return render_template('index.html', items=items)
+
+
+@app.route('/add', methods=['POST'])
+def add_password():
+ name = request.form['name']
+ password = request.form['password']
+ flaskcustodia.set_simple(name, password)
+ flash('New entry was successfully stored')
+ return redirect(url_for('index'))
+
+
+@app.route('/delete', methods=['POST'])
+def delete_password():
+ name = request.form['name']
+ flaskcustodia.delete(name)
+ flash('Entry was successfully deleted')
+ return redirect(url_for('index'))
+
+if __name__ == '__main__':
+ app.run()
diff --git a/custodia_pwmgr/static/style.css b/custodia_pwmgr/static/style.css
new file mode 100644
index 0000000..211e307
--- /dev/null
+++ b/custodia_pwmgr/static/style.css
@@ -0,0 +1,19 @@
+body { font-family: sans-serif; background: #eee; }
+a, h1, h2 { color: #377BA8; }
+h1, h2 { font-family: 'Georgia', serif; margin: 0; }
+h1 { border-bottom: 2px solid #eee; }
+h2 { font-size: 1.2em; }
+
+.page { margin: 2em auto; width: 35em; border: 5px solid #ccc;
+ padding: 0.8em; background: white; }
+.entries { list-style: disc; margin: 0; padding: 0; }
+.entries li { margin: 0.8em 1.2em; }
+.entries li h2 { margin-left: -1em; }
+.add-entry { font-size: 0.9em; border-bottom: 1px solid #ccc; }
+.add-entry dl { font-weight: bold; }
+.metanav { text-align: right; font-size: 0.8em; padding: 0.3em;
+ margin-bottom: 1em; background: #fafafa; }
+.flash { background: #CEE5F5; padding: 0.5em;
+ border: 1px solid #AACBE2; }
+.error { background: #F0D6D6; padding: 0.5em; }
+
diff --git a/custodia_pwmgr/templates/canvas.html b/custodia_pwmgr/templates/canvas.html
new file mode 100644
index 0000000..136606d
--- /dev/null
+++ b/custodia_pwmgr/templates/canvas.html
@@ -0,0 +1,11 @@
+<!doctype html>
+<title>Custodia Example App</title>
+<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='style.css') }}">
+<div class="page">
+ <h1>Custodia Example App</h1>
+ {% for message in get_flashed_messages() %}
+ <div class="flash">{{ message }}</div>
+ {% endfor %}
+ {% block body %}{% endblock %}
+</div>
+
diff --git a/custodia_pwmgr/templates/index.html b/custodia_pwmgr/templates/index.html
new file mode 100644
index 0000000..e37ed82
--- /dev/null
+++ b/custodia_pwmgr/templates/index.html
@@ -0,0 +1,28 @@
+{% extends "canvas.html" %}
+{% block body %}
+<h2>Password Manager Example</h2>
+<h3>Passwords</h3>
+<ul class="entries">
+{% for item in items %}
+ <li>{{ item }}
+ <form action="{{ url_for('delete_password') }}" method="post">
+ <input type="hidden" name="name" value="{{ item }}" />
+ <input type="submit" value="Delete">
+ </form>
+ </li>
+{% else %}
+ <li>No passwords</li>
+{% endfor %}
+</ul>
+
+<h3>Add Password</h3>
+<form action="{{ url_for('add_password') }}" method="post">
+<dl>
+ <dt>Name:
+ <dd><input type="text" name="name">
+ <dt>Password:
+ <dd><input type="text" name="password">
+ <dd><input type="submit" value="Submit">
+</dl>
+</form>
+{% endblock %}
diff --git a/kubernetes/custodia-pwmgr-rc.yaml b/kubernetes/custodia-pwmgr-rc.yaml
new file mode 100644
index 0000000..d6b66d2
--- /dev/null
+++ b/kubernetes/custodia-pwmgr-rc.yaml
@@ -0,0 +1,35 @@
+apiVersion: v1
+kind: ReplicationController
+metadata:
+ name: custodia-pwmgr
+ labels:
+ name: custodia-pwmgr
+spec:
+ replicas: 1
+ selector:
+ name: custodia-pwmgr
+ version: v1
+ template:
+ metadata:
+ labels:
+ name: custodia-pwmgr
+ version: v1
+ secrets_namespace: pwmgr
+ spec:
+ containers:
+ - name: custodia-pwmgr
+ image: custodia-pwmgr
+ ports:
+ - containerPort: 5000
+ name: custodia-pwmgr
+ env:
+ - name: CUSTODIA_SOCKET
+ value: /custodia/server_socket
+ volumeMounts:
+ - name: custodia
+ mountPath: /custodia
+ readOnly: true
+ volumes:
+ - name: custodia
+ hostPath:
+ path: /var/lib/custodia/client
diff --git a/kubernetes/custodia-pwmgr-service.yaml b/kubernetes/custodia-pwmgr-service.yaml
new file mode 100644
index 0000000..3cac5b2
--- /dev/null
+++ b/kubernetes/custodia-pwmgr-service.yaml
@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: Service
+metadata:
+ labels:
+ name: custodia-pwmgr
+ name: custodia-pwmgr
+spec:
+ ports:
+ - port: 5000
+ targetPort: 5000
+ nodePort: 30666
+ selector:
+ name: custodia-pwmgr
+ type: NodePort
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..31b9753
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,5 @@
+flask
+requests
+cryptography
+jwcrypto
+git+https://fedorapeople.org/cgit/simo/public_git/custodia.git
diff --git a/run.sh b/run.sh
new file mode 100755
index 0000000..631aff9
--- /dev/null
+++ b/run.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+
+export PYTHONPATH=$DIR/custodia
+cd $DIR/custodia_pwmgr
+python2.7 custodia_pwmgr.py
+exit $?