Skip to content

Commit

Permalink
Merge pull request #1 from SatoshiPortal/releases/v0.2.0
Browse files Browse the repository at this point in the history
Releases/v0.2.0
  • Loading branch information
Kexkey authored May 8, 2019
2 parents 42409a2 + b36b3e1 commit b5b1020
Show file tree
Hide file tree
Showing 14 changed files with 531 additions and 63 deletions.
32 changes: 32 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
FROM golang:1.11.6-alpine3.8 as builder

RUN apk add git

RUN mkdir -p /go/src/cyphernode_welcome

ADD cnAuth /go/src/cyphernode_welcome/cnAuth
COPY main.go /go/src/cyphernode_welcome

WORKDIR /go/src/cyphernode_welcome

RUN go get

RUN go build main.go
RUN chmod +x /go/src/cyphernode_welcome/main

FROM alpine:3.8

RUN apk add ca-certificates

RUN mkdir -p /app
RUN mkdir -p /data

COPY --from=builder /go/src/cyphernode_welcome/main /app/cyphernode_welcome
ADD static /app/static
ADD templates /app/templates

ENV PATH=$PATH:/app/

WORKDIR /app/

CMD ["cyphernode_welcome"]
13 changes: 6 additions & 7 deletions cnAuth/cnAuth.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,14 +110,13 @@ echo ""

func ( cnAuth *CnAuth ) BearerFromKey( keyLabel string ) (string, error) {
if keyHex, ok := cnAuth.keys[keyLabel]; ok {
h64 := base64.StdEncoding.EncodeToString( []byte("{\"alg\":\"HS256\",\"typ\":\"JWT\"}") )
p64 := base64.StdEncoding.EncodeToString( []byte(fmt.Sprintf("{\"id\":\"%s\",\"exp\":%d}", keyLabel, time.Now().Unix()+10 ) ) )
header := "{\"alg\":\"HS256\",\"typ\":\"JWT\"}"
payload := fmt.Sprintf("{\"id\":\"%s\",\"exp\":%d}", keyLabel, time.Now().Unix()+10 )

h64 := base64.StdEncoding.EncodeToString( []byte(header) )
p64 := base64.StdEncoding.EncodeToString( []byte(payload) )
toSign := h64+"."+p64
key, err := hex.DecodeString(keyHex)
if err != nil {
return "", err
}
h := hmac.New( sha256.New, key )
h := hmac.New( sha256.New, []byte(keyHex) )
h.Write([]byte(toSign))
sha := hex.EncodeToString(h.Sum(nil))
return "Bearer "+toSign+"."+sha, nil
Expand Down
16 changes: 9 additions & 7 deletions data/config.toml
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
[server]
listen = "0.0.0.0:8080"
index_template = "templates/index.html"
path_prefix = "/welcome"

[gatekeeper]
status_url = "http://localhost:3333/status"
key_label = "001"
key_file = "data/keys.properties"
cert_file = "data/cert.pem"



status_url = "https://gatekeeper/v0/getblockchaininfo"
installation_info_url = "https://gatekeeper/s/stats/installation.json"
config_archive_url = "https://gatekeeper/s/stats/config.7z"
certs_url = "https://gatekeeper/s/stats/client.7z"

key_label = "000"
key_file = "/data/keys.properties"
cert_file = "/data/cert.pem"
7 changes: 4 additions & 3 deletions data/keys.properties
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
kapi_id="001";kapi_key="a27f9e73fdde6a5005879c273c9aea5e8d917eec77bbdfd73272c0af9b4c6b7a";kapi_groups="watcher";eval ugroups_${kapi_id}=${kapi_groups};eval ukey_${kapi_id}=${kapi_key}
kapi_id="002";kapi_key="fe58ddbb66d7302a7087af3242a98b6326c51a257f5eab1c06bb8cc02e25890d";kapi_groups="watcher,spender";eval ugroups_${kapi_id}=${kapi_groups};eval ukey_${kapi_id}=${kapi_key}
kapi_id="003";kapi_key="f0b8bb52f4c7007938757bcdfc73b452d6ce08cc0c660ce57c5464ae95f35417";kapi_groups="watcher,spender,admin";eval ugroups_${kapi_id}=${kapi_groups};eval ukey_${kapi_id}=${kapi_key}
kapi_id="000";kapi_key="6ddd3bbeb6daf9c643113def55e86893d94916668a5cadd892ee524ba4a519a1";kapi_groups="stats";eval ugroups_${kapi_id}=${kapi_groups};eval ukey_${kapi_id}=${kapi_key}
kapi_id="001";kapi_key="256b2061bf06b4c046b8e279596df598a35a42689e21e997e9ac6ac20e3e1522";kapi_groups="stats,watcher";eval ugroups_${kapi_id}=${kapi_groups};eval ukey_${kapi_id}=${kapi_key}
kapi_id="002";kapi_key="9822479eb361c573bc96c0936fb5fa30d0f14e6d44ed6d9219856d123e7b47ce";kapi_groups="stats,watcher,spender";eval ugroups_${kapi_id}=${kapi_groups};eval ukey_${kapi_id}=${kapi_key}
kapi_id="003";kapi_key="9538760ae5cdc195f4f32f867475c4e3b13894cd859b0c2d6e3c8d729b3217c8";kapi_groups="stats,watcher,spender,admin";eval ugroups_${kapi_id}=${kapi_groups};eval ukey_${kapi_id}=${kapi_key}
216 changes: 191 additions & 25 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,109 +26,275 @@ package main

import (
"bytes"
"cyphernode_status/cnAuth"
"crypto/tls"
"crypto/x509"
"cyphernode_welcome/cnAuth"
"encoding/json"
"fmt"
"github.com/gorilla/mux"
"github.com/op/go-logging"
"github.com/pkg/errors"
"github.com/spf13/viper"
"html/template"
"io/ioutil"
"net/http"
"os"
)

type Status struct {
Foo string `json:"foo"`
type BlockChainInfo struct {
Verificationprogress float32 `json:"verificationprogress"`
}

type InstallationInfoFeature struct {
Name string `json:"name"`
CoreFeature bool `json:"coreFeature"`
Working bool `json:"working"`
}

type InstallationInfoContainer struct {
Name string `json:"name"`
Active bool `json:"active"`
}

type TemplateData struct {
Features []InstallationInfoFeature `json:"features"`
Containers []InstallationInfoContainer `json:"containers"`
ForwardedPrefix string
FeatureByName map[string]bool
}

var auth *cnAuth.CnAuth
var statsKeyLabel string
var indexTemplate string
var rootTemplate *template.Template
var statusUrl string
var installationInfoUrl string
var configArchiveUrl string
var certsUrl string
var passwordHashes map[string][]byte

var httpClient *http.Client
var log = logging.MustGetLogger("main")

func RootHandler(w http.ResponseWriter, _ *http.Request) {
t,_ := template.ParseFiles(indexTemplate)
t.Execute(w, nil)

func RootHandler(w http.ResponseWriter, req *http.Request) {
installationInfo, err := getInstallatioInfo()
if err != nil {
log.Errorf("Error retrieving installation info %s", err )
}
installationInfo.ForwardedPrefix = req.Header.Get("X-Forwarded-Prefix")
rootTemplate.Execute(w, installationInfo)
}

func generateAuthHeaders() map[string]string {
result := make( map[string]string, 0 )
return result
func getBodyUsingAuth( url string ) ([]byte,error) {

req, err := http.NewRequest("GET", url, nil)
if err != nil {
return nil, err
}

bearer, err := auth.BearerFromKey(statsKeyLabel)
if err != nil {
return nil, err
}

req.Header.Set("Authorization", bearer )
res,err := httpClient.Do(req)
if err != nil {
return nil, err
}

defer res.Body.Close()

if res.StatusCode == 0 {
return nil, err
}

if res.StatusCode != 200 {
return nil, errors.New("Unexpected http status code")
}

body, err := ioutil.ReadAll(res.Body)

if res.StatusCode == 0 {
return nil, err
}

return body, nil
}

func StatusHandler(w http.ResponseWriter, r *http.Request) {
func getInstallatioInfo() (*TemplateData,error) {
log.Info("getInstallatioInfo")
body,err := getBodyUsingAuth( installationInfoUrl )

if err != nil {
log.Errorf("getInstallatioInfo: %s", err)
return nil,err
}

log.Infof("getInstallatioInfo: %", string(body))


installationInfo := new(TemplateData)

err = json.Unmarshal( body, &installationInfo )

req, err := http.NewRequest("GET", statusUrl, nil)
if err != nil {
log.Errorf("getInstallatioInfo: %s", err)
return nil,err
}

// map features to FeatureByName
installationInfo.FeatureByName = make( map[string]bool, 0 )
for f := 0 ; f< len(installationInfo.Features); f++ {
installationInfo.FeatureByName[installationInfo.Features[f].Name] = installationInfo.Features[f].Working
}

log.Info("getInstallatioInfo: json done")

return installationInfo,nil
}

func VerificationProgressHandler(w http.ResponseWriter, r *http.Request) {

body,err := getBodyUsingAuth( statusUrl )

if err != nil {
log.Errorf("VerificationProgressHandler: %s", err)
w.WriteHeader(503 )
return
}

res, err := http.DefaultClient.Do(req)
blockChainInfo := new( BlockChainInfo )

err = json.Unmarshal( body, &blockChainInfo )

if err != nil {
log.Errorf("VerificationProgressHandler: %s", err)
w.WriteHeader(503 )
return
}

defer res.Body.Close()
w.Header().Set("Content-Type", "application/json")
result, err := json.Marshal(&blockChainInfo)
fmt.Fprint(w, bytes.NewBuffer(result))
}

body, _ := ioutil.ReadAll(res.Body)

//status := new (Status)
//jsonData, _ := json.Marshal(status)
w.Header().Set("Content-Type", "application/json")
bearer, err := auth.BearerFromKey(statsKeyLabel)
func ConfigHandler(w http.ResponseWriter, r *http.Request) {

body,err := getBodyUsingAuth( configArchiveUrl )

if err != nil {
log.Errorf("ConfigHandler: %s", err)
w.WriteHeader(503 )
return
}
w.Header().Set("Authorization", bearer )

w.Header().Set("Content-Type", "application/x-7z-compressed")
fmt.Fprint(w, bytes.NewBuffer(body))
return
}

func CertsHandler(w http.ResponseWriter, r *http.Request) {

body,err := getBodyUsingAuth( certsUrl )

if err != nil {
log.Errorf("CertsHandler: %s", err)
w.WriteHeader(503 )
return
}

w.Header().Set("Content-Type", "application/x-7z-compressed")
fmt.Fprint(w, bytes.NewBuffer(body))
}

func Secret(user, realm string) string {
if user == "john" {
// password is "hello"
return "$1$dlPL2MqE$oQmn16q49SqdmhenQuNgs1"
}
return ""
}

func main() {

viper.SetConfigName("config")
viper.AddConfigPath("/data")
viper.AddConfigPath("data")

err := viper.ReadInConfig()

if err != nil {
log.Error(err)
log.Errorf("Error loading config.toml: %s", err)
return
}

keysFilePath := viper.GetString("gatekeeper.key_file")
statsKeyLabel = viper.GetString("gatekeeper.key_label")
statusUrl = viper.GetString("gatekeeper.status_url")
installationInfoUrl = viper.GetString("gatekeeper.installation_info_url")
configArchiveUrl = viper.GetString("gatekeeper.config_archive_url")
certsUrl = viper.GetString("gatekeeper.certs_url")
certFile := viper.GetString("gatekeeper.cert_file")
listenTo := viper.GetString("server.listen")
indexTemplate = viper.GetString("server.index_template")
indexTemplate := viper.GetString("server.index_template")

rootTemplate, err = template.ParseFiles(indexTemplate)

if err != nil {
log.Errorf("Error loading root template: %s", err)
log.Error(err)
return
}

caCert, err := ioutil.ReadFile(certFile)
if err != nil {
log.Errorf("Error loading cert: %s", err)
log.Error(err)
return
}

caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert)

httpClient = &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
RootCAs: caCertPool,
},
},
}

file, err := os.Open(keysFilePath)

if err != nil {
log.Errorf("Error loading keys file: %s", err)
log.Error(err)
return
}

auth, err = cnAuth.NewCnAuthFromFile( file )
file.Close()

if err != nil {
log.Errorf("Error creating auther: %s", err)
log.Error(err)
return
}

log.Infof("Started cyphernode status page backend. URL Port [%v] ",listenTo)

router := mux.NewRouter()

router.HandleFunc("/", RootHandler)
router.HandleFunc("/status", StatusHandler)
router.HandleFunc("/verificationprogress", VerificationProgressHandler)
router.HandleFunc("/config.7z", ConfigHandler)
router.HandleFunc("/certs.7z", CertsHandler)

router.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir("./static"))))

http.Handle("/", router)
route := router.PathPrefix("/static")

log.Fatal(http.ListenAndServe(listenTo, nil))
log.Fatal(route, http.ListenAndServe(listenTo, nil))
}
7 changes: 7 additions & 0 deletions static/css/bootstrap-grid.min.css

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions static/css/bootstrap-reboot.min.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit b5b1020

Please sign in to comment.