Browse Source

alpha version

Nikola Kotur 6 years ago
parent
commit
64c6f14ed0

+ 2 - 1
.platform/services.yaml

@@ -1 +1,2 @@
-# I ain't got no services
+redis:
+    type: redis:3.0

+ 9 - 1
README.md

@@ -1,3 +1,11 @@
 # cubbyshare
 
-Simple, Platform.sh powered, application to share secrets that can be viewed only once
+Simple, Platform.sh powered, application to share secrets that can be viewed only once
+
+## Setup
+
+Create Platform.sh project.
+
+Push code.
+
+On master, create variable `env:VAULT_URI` with the URI to the Vault app within the same project (drop the trailing `/`).

+ 12 - 13
frontend/.platform.app.yaml

@@ -1,28 +1,27 @@
-# This file describes an application. You can have multiple applications
-# in the same project.
-#
-# See https://docs.platform.sh/user_guide/reference/platform-app-yaml.html
-
-# The name of this app. Must be unique within a project.
 name: frontend
 
-# The runtime the application uses.
 type: "python:3.6"
 
-# The build-time dependencies of the app.
 dependencies:
     python:
-       flask: '*'
+        flask: '*'
+        flask-bootstrap: '*'
+        flask-nav: '*'
+        flask-wtf: '*'
+        flask-debug: '*'
+        requests: "*"
+        redis: '*'
+        hvac: '*'
 
-# The hooks executed at various points in the lifecycle of the application.
 hooks:
     build: |
       sleep 1
 
-# The size of the persistent disk of the application (in MB).
 disk: 256
 
-# The configuration of app when it is exposed to the web.
 web:
     commands:
-        start: python server.py
+        start: FLASK_APP=__init__.py flask run --with-threads -h 0.0.0.0 -p 8888
+
+relationships:
+    redis: 'redis:redis'

+ 40 - 0
frontend/__init__.py

@@ -0,0 +1,40 @@
+import base64
+import json
+import os
+import traceback
+import uuid
+import sys
+import base64
+
+import redis
+import flask
+import flask.json
+from flask_bootstrap import Bootstrap
+
+from .frontend import frontend
+from .nav import nav
+
+
+app = flask.Flask(__name__)
+Bootstrap(app)
+app.config['BOOTSTRAP_SERVE_LOCAL'] = True
+app.config['SECRET_KEY'] = 'secretkey'
+app.register_blueprint(frontend)
+nav.init_app(app)
+
+app.config['RELATIONSHIPS'] = json.loads(
+    base64.b64decode(os.environ["PLATFORM_RELATIONSHIPS"])
+)
+app.redis = redis.StrictRedis(
+    host=app.config['RELATIONSHIPS']['redis'][0]['host'], 
+    port=app.config['RELATIONSHIPS']['redis'][0]['port'], 
+    db=0
+)
+def get_token():
+    return app.redis.get('token')
+app.get_token = get_token
+
+
+if __name__ == "__main__":
+    # token = redis_conn.get('token')
+    app.run(host='0.0.0.0', port=8888)

+ 12 - 0
frontend/forms.py

@@ -0,0 +1,12 @@
+from flask_wtf import FlaskForm
+from wtforms.fields import TextAreaField, SubmitField
+from wtforms.validators import DataRequired, ValidationError
+
+
+class DataForm(FlaskForm):
+    secrets = TextAreaField(u'Your data', validators=[DataRequired()])
+    submit = SubmitField("Create")
+
+    def validate_secrets(self, field):
+        if field.data == '':
+            raise ValidationError("No secrets found")

+ 78 - 0
frontend/frontend.py

@@ -0,0 +1,78 @@
+import os
+import base64
+
+import hvac
+import requests
+from flask import Blueprint, render_template, flash, redirect, url_for, current_app
+from flask_bootstrap import __version__ as FLASK_BOOTSTRAP_VERSION
+from flask_nav.elements import Navbar, View, Subgroup, Link, Text, Separator
+from markupsafe import escape
+
+from .forms import DataForm
+from .nav import nav
+
+frontend = Blueprint('frontend', __name__)
+
+
+nav.register_element('frontend_top', Navbar(
+    View('Cubbyshare', '.index'),
+    View('Home', '.index'),
+    View('About', '.about'),
+))
+
+
+@frontend.route('/', defaults={'path': ''})
+@frontend.route('/<path:path>')
+def index(path):
+    token = path
+    if not token:
+        form = DataForm()
+        return render_template('index.html', form=form, data='')
+
+    vault_uri = os.environ.get('VAULT_URI', None)
+    if not vault_uri:
+        flash('Missing VAULT_URI')
+        return redirect(url_for('.index'))
+
+    try:
+        cubby = hvac.Client(url=vault_uri, token=token)
+        result = cubby.read('cubbyhole/%s' % token)
+    except hvac.exceptions.Forbidden:
+        flash('Something went wrong')
+        return redirect(url_for('.index'))
+    secret = base64.b64decode(result['data']['wrap']).decode()
+    return render_template('index.html', form='', data=secret)
+
+
+@frontend.route('/add', methods=['POST'])
+def add_entry():
+    form = DataForm()
+
+    if form.validate_on_submit():
+        secret_data = base64.b64encode(form.secrets.data.encode()).decode()
+        root_token = current_app.get_token()
+
+        vault_uri = os.environ.get('VAULT_URI', None)
+        if not vault_uri:
+            flash('Missing VAULT_URI')
+            return redirect(url_for('.index'))
+
+        vault = hvac.Client(url=vault_uri, token=root_token)
+        token = vault.create_token(lease='24h', num_uses=2, renewable=False, no_default_policy=True)
+        token_id = token['auth']['client_token']
+
+        cubby = hvac.Client(url=vault_uri, token=token_id)
+        cubby.write('cubbyhole/%s' % token_id, wrap=secret_data)
+        flash('Successfully saved')
+
+        return render_template('success.html', token=token_id)
+    else:
+        for error_field, error_message in form.errors.items():
+            flash("Field : {field}; error : {error}".format(field=error_field, error=error_message))
+
+    return redirect(url_for('.index'))
+
+
+@frontend.route('/about')
+def about():
+    return render_template('about.html')

+ 3 - 0
frontend/nav.py

@@ -0,0 +1,3 @@
+from flask_nav import Nav
+
+nav = Nav()

+ 0 - 23
frontend/server.py

@@ -1,23 +0,0 @@
-import base64
-import json
-import os
-import traceback
-import uuid
-import sys
-
-import flask
-import flask.json
-
-
-app = flask.Flask(__name__)
-relationships = json.loads(base64.b64decode(os.environ["PLATFORM_RELATIONSHIPS"]))
-
-
-@app.route('/')
-def root():
-    tests = {}
-    return flask.json.jsonify(tests)
-
-
-if __name__ == "__main__":
-    app.run(host='0.0.0.0', port=8888)

File diff suppressed because it is too large
+ 3 - 0
frontend/static/html5shiv.min.js


File diff suppressed because it is too large
+ 5 - 0
frontend/static/respond.min.js


+ 3 - 0
frontend/static/sample-app.css

@@ -0,0 +1,3 @@
+.jumbotron {
+  margin-top: 1em;  // add a little space
+}

+ 33 - 0
frontend/templates/about.html

@@ -0,0 +1,33 @@
+{# This simple template derives from ``base.html``. See ``base.html`` for
+   more information about template inheritance. #}
+{%- extends "base.html" %}
+
+{# Loads some of the macros included with Flask-Bootstrap. We are using the
+   utils module here to automatically render Flask's flashed messages in a
+   bootstrap friendly manner #}
+{% import "bootstrap/utils.html" as utils %}
+
+
+{# Inside the ``content`` is where you should place most of your own stuff.
+   This will keep scripts at the page end and a navbar you add on later
+   intact. #}
+{% block content %}
+  <div class="container">
+  {%- with messages = get_flashed_messages(with_categories=True) %}
+  {%- if messages %}
+    <div class="row">
+      <div class="col-md-12">
+        {{utils.flashed_messages(messages)}}
+      </div>
+    </div>
+  {%- endif %}
+  {%- endwith %}
+    <div class="jumbotron">
+      <h1>About</h1>
+      <p>
+        <a class="btn btn-lg btn-default" role="button"
+           href="http://pythonhosted.org/Flask-Bootstrap" >Show docs</a>
+      </p>
+    </div>
+   </div>
+{%- endblock %}

+ 44 - 0
frontend/templates/base.html

@@ -0,0 +1,44 @@
+{# ``base.html`` is the template all our other templates derive from. While
+   Flask-Bootstrap ships with its own base, it is good form to create a custom
+   one for our app, as it allows customizing some aspects.
+
+   Deriving from bootstap/base.html gives us a basic page scaffoling.
+
+   You can find additional information about template inheritance at
+
+   http://jinja.pocoo.org/docs/templates/#template-inheritance
+#}
+{%- extends "bootstrap/base.html" %}
+
+{# We also set a default title, usually because we might forget to set one.
+   In our sample app, we will most likely just opt not to change it #}
+{% block title %}Sample App for Flask-Bootstrap{% endblock %}
+
+{# While we are at it, we also enable fixes for legacy browsers. First we
+   import the necessary macros: #}
+{% import "bootstrap/fixes.html" as fixes %}
+
+{# Then, inside the head block, we apply these. To not replace the header,
+   ``super()`` is used: #}
+{% block head %}
+{{super()}}
+
+{#- Docs: http://pythonhosted.org/Flask-Bootstrap/macros.html#fixes
+   The sample application already contains the required static files. #}
+{{fixes.ie8()}}
+{%- endblock %}
+
+{# Adding our own CSS files is also done here. Check the documentation at
+   http://pythonhosted.org/Flask-Bootstrap/basic-usage.html#available-blocks
+   for an overview. #}
+{% block styles -%}
+    {{super()}}  {# do not forget to call super or Bootstrap's own stylesheets
+                    will disappear! #}
+    <link rel="stylesheet" type="text/css"
+          href="{{url_for('static', filename='sample-app.css')}}">
+{% endblock %}
+
+{# Finally, round things out with navigation #}
+{% block navbar %}
+{{nav.frontend_top.render()}}
+{% endblock %}

+ 43 - 0
frontend/templates/index.html

@@ -0,0 +1,43 @@
+{% import "bootstrap/wtf.html" as wtf %}
+{% import "bootstrap/utils.html" as utils %}
+
+{%- extends "base.html" %}
+
+
+{% block content %}
+   <div class="container">
+      <div class="jumbotron">
+        <h1>Signup for our awesome service</h1>
+        <p>Note: Your data isn't going anywhere.</p>
+      </div>
+   <div class="col-md-12">
+    {% with messages = get_flashed_messages() %}
+      {% if messages %}
+        <ul class=flashes>
+        {% for message in messages %}
+          <li>{{ message }}</li>
+        {% endfor %}
+        </ul>
+      {% endif %}
+    {% endwith %}
+    
+    {% if data %}
+<pre>
+{{ data }}
+</pre>
+    {% endif %}
+
+    {% if form %}
+    <form method="POST" action="{{ url_for('frontend.add_entry') }}">
+        {{ form.csrf_token }}
+
+        {{ form.secrets.label }}
+        <br><br>
+        {{ form.secrets }}
+        <br><br>
+        {{ form.submit }}
+
+    </form>   
+    {% endif %}
+  </div>
+{%- endblock %}

+ 31 - 0
frontend/templates/success.html

@@ -0,0 +1,31 @@
+{# This simple template derives from ``base.html``. See ``base.html`` for
+   more information about template inheritance. #}
+{%- extends "base.html" %}
+
+{# Loads some of the macros included with Flask-Bootstrap. We are using the
+   utils module here to automatically render Flask's flashed messages in a
+   bootstrap friendly manner #}
+{% import "bootstrap/utils.html" as utils %}
+
+
+{# Inside the ``content`` is where you should place most of your own stuff.
+   This will keep scripts at the page end and a navbar you add on later
+   intact. #}
+{% block content %}
+  <div class="container">
+  {%- with messages = get_flashed_messages(with_categories=True) %}
+  {%- if messages %}
+    <div class="row">
+      <div class="col-md-12">
+        {{utils.flashed_messages(messages)}}
+      </div>
+    </div>
+  {%- endif %}
+  {%- endwith %}
+    <div class="row">
+      <div class="col-md-12">
+        Hi: {{ token }}
+      </div>
+    </div>
+   </div>
+{%- endblock %}

+ 22 - 8
vault/.platform.app.yaml

@@ -1,26 +1,40 @@
 name: vault
 
-type: golang:1.8
+type: golang:1.10
 
 hooks:
     build: |
-      make setup
-      # Remove the following line if committing your vendor directory.
-      make deps
-      make
+        go get -u github.com/hashicorp/vault
+
+dependencies:
+    python:
+       redis: '*'
 
 web:
     upstream:
         socket_family: tcp
         protocol: http
-
     commands:
         start: |
-          ./bin/example
-
+            # We start Vault
+            HOME=/app/data ./go/bin/vault server -dev -dev-listen-address 0.0.0.0:8888 &
+            # then wait for it to bootstrap
+            sleep 5
+            # and finally set root token in redis for frontend to use.
+            ./update-credentials.py
+            # Now just wait.
+            sleep infinity
     locations:
         /:
             allow: false
             passthru: true
 
 disk: 256
+
+mounts:
+    'data':
+        source: local
+        source_path: 'data'
+
+relationships:
+    redis: 'redis:redis'

+ 0 - 150
vault/Makefile

@@ -1,150 +0,0 @@
-# The import path is where your repository can be found.
-# To import subpackages, always prepend the full import path.
-# If you change this, run `make clean`. Read more: https://git.io/vM7zV
-IMPORT_PATH := github.com/platformsh/example
-
-# V := 1 # When V is set, print commands and build progress.
-
-# Space separated patterns of packages to skip in list, test, format.
-IGNORED_PACKAGES := /vendor/
-
-.PHONY: all
-all: build
-
-.PHONY: build
-build: .GOPATH/.ok
-	$Q go install $(if $V,-v) $(VERSION_FLAGS) $(IMPORT_PATH)
-
-.PHONY: deps
-deps:
-	bin/gvt fetch github.com/platformsh/gohelper
-	bin/gvt fetch github.com/go-sql-driver/mysql
-
-
-### Code not in the repository root? Another binary? Add to the path like this.
-# .PHONY: otherbin
-# otherbin: .GOPATH/.ok
-# 	$Q go install $(if $V,-v) $(VERSION_FLAGS) $(IMPORT_PATH)/cmd/otherbin
-
-##### ^^^^^^ EDIT ABOVE ^^^^^^ #####
-
-##### =====> Utility targets <===== #####
-
-.PHONY: clean test list cover format
-
-clean:
-	$Q rm -rf bin .GOPATH
-
-test: .GOPATH/.ok
-	$Q go test $(if $V,-v) -i -race $(allpackages) # install -race libs to speed up next run
-ifndef CI
-	$Q go vet $(allpackages)
-	$Q GODEBUG=cgocheck=2 go test -race $(allpackages)
-else
-	$Q ( go vet $(allpackages); echo $$? ) | \
-	    tee .GOPATH/test/vet.txt | sed '$$ d'; exit $$(tail -1 .GOPATH/test/vet.txt)
-	$Q ( GODEBUG=cgocheck=2 go test -v -race $(allpackages); echo $$? ) | \
-	    tee .GOPATH/test/output.txt | sed '$$ d'; exit $$(tail -1 .GOPATH/test/output.txt)
-endif
-
-list: .GOPATH/.ok
-	@echo $(allpackages)
-
-cover: bin/gocovmerge .GOPATH/.ok
-	@echo "NOTE: make cover does not exit 1 on failure, don't use it to check for tests success!"
-	$Q rm -f .GOPATH/cover/*.out .GOPATH/cover/all.merged
-	$(if $V,@echo "-- go test -coverpkg=./... -coverprofile=.GOPATH/cover/... ./...")
-	@for MOD in $(allpackages); do \
-		go test -coverpkg=`echo $(allpackages)|tr " " ","` \
-			-coverprofile=.GOPATH/cover/unit-`echo $$MOD|tr "/" "_"`.out \
-			$$MOD 2>&1 | grep -v "no packages being tested depend on"; \
-	done
-	$Q ./bin/gocovmerge .GOPATH/cover/*.out > .GOPATH/cover/all.merged
-ifndef CI
-	$Q go tool cover -html .GOPATH/cover/all.merged
-else
-	$Q go tool cover -html .GOPATH/cover/all.merged -o .GOPATH/cover/all.html
-endif
-	@echo ""
-	@echo "=====> Total test coverage: <====="
-	@echo ""
-	$Q go tool cover -func .GOPATH/cover/all.merged
-
-format: bin/goimports .GOPATH/.ok
-	$Q find .GOPATH/src/$(IMPORT_PATH)/ -iname \*.go | grep -v \
-	    -e "^$$" $(addprefix -e ,$(IGNORED_PACKAGES)) | xargs ./bin/goimports -w
-
-##### =====> Internals <===== #####
-
-.PHONY: setup
-setup: clean .GOPATH/.ok
-	@if ! grep "/.GOPATH" .gitignore > /dev/null 2>&1; then \
-	    echo "/.GOPATH" >> .gitignore; \
-	    echo "/bin" >> .gitignore; \
-	fi
-	go get -u github.com/FiloSottile/gvt
-	- ./bin/gvt fetch golang.org/x/tools/cmd/goimports
-	- ./bin/gvt fetch github.com/wadey/gocovmerge
-
-
-DATE             := $(shell date -u '+%Y-%m-%d-%H%M UTC')
-VERSION_FLAGS    := -ldflags='-X "main.BuildTime=$(DATE)"'
-
-
-#VERSION          := $(shell git describe --tags --always --dirty="-dev")
-#DATE             := $(shell date -u '+%Y-%m-%d-%H%M UTC')
-#VERSION_FLAGS    := -ldflags='-X "main.Version=$(VERSION)" -X "main.BuildTime=$(DATE)"'
-
-# cd into the GOPATH to workaround ./... not following symlinks
-_allpackages = $(shell ( cd $(CURDIR)/.GOPATH/src/$(IMPORT_PATH) && \
-    GOPATH=$(CURDIR)/.GOPATH go list ./... 2>&1 1>&3 | \
-    grep -v -e "^$$" $(addprefix -e ,$(IGNORED_PACKAGES)) 1>&2 ) 3>&1 | \
-    grep -v -e "^$$" $(addprefix -e ,$(IGNORED_PACKAGES)))
-
-# memoize allpackages, so that it's executed only once and only if used
-allpackages = $(if $(__allpackages),,$(eval __allpackages := $$(_allpackages)))$(__allpackages)
-
-export GOPATH := $(CURDIR)/.GOPATH
-unexport GOBIN
-
-Q := $(if $V,,@)
-
-.GOPATH/.ok:
-	$Q mkdir -p "$(dir .GOPATH/src/$(IMPORT_PATH))"
-	$Q ln -s ../../../.. ".GOPATH/src/$(IMPORT_PATH)"
-	$Q mkdir -p .GOPATH/test .GOPATH/cover
-	$Q mkdir -p bin
-	$Q ln -s ../bin .GOPATH/bin
-	$Q touch $@
-
-.PHONY: bin/gocovmerge bin/goimports
-bin/gocovmerge: .GOPATH/.ok
-	@test -d ./vendor/github.com/wadey/gocovmerge || \
-	    { echo "Vendored gocovmerge not found, try running 'make setup'..."; exit 1; }
-	$Q go install $(IMPORT_PATH)/vendor/github.com/wadey/gocovmerge
-bin/goimports: .GOPATH/.ok
-	@test -d ./vendor/golang.org/x/tools/cmd/goimports || \
-	    { echo "Vendored goimports not found, try running 'make setup'..."; exit 1; }
-	$Q go install $(IMPORT_PATH)/vendor/golang.org/x/tools/cmd/goimports
-
-# Based on https://github.com/cloudflare/hellogopher - v1.1 - MIT License
-#
-# Copyright (c) 2017 Cloudflare
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.

+ 1 - 0
vault/README.md

@@ -0,0 +1 @@
+This is Vault app.

+ 0 - 130
vault/server.go

@@ -1,130 +0,0 @@
-package main
-
-import (
-    "database/sql"
-    "fmt"
-    _ "github.com/go-sql-driver/mysql"
-    psh "github.com/platformsh/gohelper"
-    "html"
-    "log"
-    "net/http"
-)
-
-func main() {
-
-    // The psh library provides Platform.sh environment information mapped to Go structs.
-    p, err := psh.NewPlatformInfo()
-
-    if err != nil {
-        // This means we're not running on Platform.sh!
-        // In practice you would want to fall back to another way to define
-        // configuration information, say for your local development environment.
-        fmt.Println(err)
-        panic("Not in a Platform.sh Environment.")
-    }
-
-    fmt.Println("Yay, found Platform.sh info")
-
-    // Set up an extremely simple web server response.
-    http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {
-        // Run some background SQL, just to prove we can.
-        trySql(p, w)
-
-        // And say hello, per tradition.
-        fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
-    })
-
-    // The port to listen on is defined by Platform.sh.
-    log.Fatal(http.ListenAndServe(":"+p.Port, nil))
-}
-
-// trySql simply connects to a MySQL server defined by Platform.sh and
-// writes and reads from it.  This is not particularly useful code,
-// but demonstrates how you can leverage the Platform.sh library.
-func trySql(pi *psh.PlatformInfo, w http.ResponseWriter) {
-
-    dbString, err := pi.SqlDsn("mysql")
-    checkErr(err)
-
-    db, err := sql.Open("mysql", dbString)
-    checkErr(err)
-
-    // Force MySQL into modern mode.
-    db.Exec("SET NAMES=utf8")
-    db.Exec("SET sql_mode = 'ANSI,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,ONLY_FULL_GROUP_BY'")
-
-    _, err = db.Exec("DROP TABLE IF EXISTS userinfo")
-    checkErr(err)
-
-    _, err = db.Exec(`CREATE TABLE userinfo (
-            uid INT(10) NOT NULL AUTO_INCREMENT,
-            username VARCHAR(64) NULL DEFAULT NULL,
-            departname VARCHAR(128) NULL DEFAULT NULL,
-            created DATE NULL DEFAULT NULL,
-            PRIMARY KEY (uid)
-            ) DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;`)
-    checkErr(err)
-
-    // insert
-    stmt, err := db.Prepare("INSERT userinfo SET username=?,departname=?,created=?")
-    checkErr(err)
-
-    res, err := stmt.Exec("astaxie", "研发部门", "2012-12-09")
-    checkErr(err)
-
-    id, err := res.LastInsertId()
-    checkErr(err)
-
-    fmt.Println(id)
-    // update
-    stmt, err = db.Prepare("update userinfo set username=? where uid=?")
-    checkErr(err)
-
-    res, err = stmt.Exec("astaxieupdate", id)
-    checkErr(err)
-
-    affect, err := res.RowsAffected()
-    checkErr(err)
-
-    fmt.Println(affect)
-
-    // query
-    rows, err := db.Query("SELECT * FROM userinfo")
-    checkErr(err)
-
-    for rows.Next() {
-        var uid int
-        var username string
-        var department string
-        var created string
-        err = rows.Scan(&uid, &username, &department, &created)
-        checkErr(err)
-        fmt.Fprintln(w, uid)
-        fmt.Fprintln(w, username)
-        fmt.Printf(username)
-        fmt.Fprintln(w, department)
-        fmt.Fprintln(w, created)
-    }
-
-    // delete
-    stmt, err = db.Prepare("delete from userinfo where uid=?")
-    checkErr(err)
-
-    res, err = stmt.Exec(id)
-    checkErr(err)
-
-    affect, err = res.RowsAffected()
-    checkErr(err)
-
-    fmt.Fprintln(w, affect)
-
-    db.Close()
-}
-
-// checkErr is a simple wrapper for panicking on error.
-// It likely should not be used in a real application.
-func checkErr(err error) {
-    if err != nil {
-        panic(err)
-    }
-}

+ 30 - 0
vault/update-credentials.py

@@ -0,0 +1,30 @@
+#!/usr/bin/env python
+import json
+import base64
+import os
+
+import redis
+
+
+if __name__ == '__main__':
+    log_file = '/var/log/app.log'
+
+    print('Looking for root token in: %s' % log_file)
+
+    tokens = []
+    with open(log_file) as log:
+        for line in log:
+            if line.startswith('Root Token'):
+                tokens.append(line.strip())
+
+    token = tokens[-1].split(' ')[-1]
+
+    print('Found root token: %s' % token)
+    print('Saving token in redis')
+
+    relationships = json.loads(base64.b64decode(os.environ["PLATFORM_RELATIONSHIPS"]))
+    r = redis.StrictRedis(host=relationships['redis'][0]['host'], port=relationships['redis'][0]['port'], db=0)
+    if r.set('token', token):
+        print('Token saved in redis as `token`')
+    else:
+        print('Error saving in redis')

Some files were not shown because too many files changed in this diff