summaryrefslogtreecommitdiffstats
path: root/custodia_pwmgr/custodia_pwmgr.py
blob: d0ca754d11c40f7a9b22c838c9bfb1b3c0e78e04 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#!/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 RequestException

# 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='passwords',
    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 RequestException 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)


def flash_exception(msg, exc):
    return flash("%s: %s" % (msg, exc), 'error')


@app.route('/')
def index():
    # flaskcustodia.set_simple('key', 'password')
    try:
        items = flaskcustodia.items()
    except RequestException as e:
        flash_exception("Unable to retrieve secrets", e)
        items = []
    return render_template('index.html', items=items)


@app.route('/add', methods=['POST'])
def add_password():
    name = request.form['name']
    password = request.form['password']
    try:
        flaskcustodia.set_simple(name, password)
    except RequestException as e:
        flash_exception("Unable to add new entry", e)
    else:
        flash('New entry was successfully stored')
    return redirect(url_for('index'))


@app.route('/get/<name>')
def get_password(name):
    try:
        value = flaskcustodia.get_simple(name)
    except RequestException as e:
        flash_exception("Cannot retrieve entry '%s'" % name, e)
        return redirect(url_for('index'))
    else:
        return render_template('secret.html', name=name, value=value)


@app.route('/delete', methods=['POST'])
def delete_password():
    name = request.form['name']
    try:
        flaskcustodia.delete(name)
    except RequestException as e:
        flash_exception("Unable to delete entry", e)
    else:
        flash('Entry was successfully deleted')
    return redirect(url_for('index'))

if __name__ == '__main__':
    app.run(host='0.0.0.0')