Skip to content

Commit

Permalink
Merge pull request #12 from Flajt/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
Flajt committed Sep 28, 2023
2 parents 3d579ca + b854f90 commit dacc8a2
Show file tree
Hide file tree
Showing 92 changed files with 1,736 additions and 26 deletions.
37 changes: 37 additions & 0 deletions .github/workflows/deploy-on-push.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: Deploy on PR
on:
push:
branches:
- main
jobs:
build:
environment:
name: prod
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4

- name: Setup Go 1.20
uses: actions/setup-go@v4
with:
go-version: '1.20'

- name: Install all dependencies
run: cd ${{github.workspace}}/scw_secret_wrapper && go get . && cd ${{github.workspace}}/helper && go get . && cd ${{github.workspace}}/sign && go get . && cd ${{github.workspace}}/cronjob && go get . && cd ${{github.workspace}}/has_new_key && go get . && cd ${{github.workspace}}/get_new_key && go get . && cd ${{github.workspace}}/

- name: Run go mod vendor
run: cd ${{github.workspace}}/get_new_key && go mod vendor && cd ${{github.workspace}}/has_new_key && go mod vendor && cd ${{github.workspace}}/sign && go mod vendor cd ${{github.workspace}}/cronjob && go mod vendor

- name: Convert secrets to .env.prod file
uses: shine1594/secrets-to-env-action@master
with:
secrets: ${{ toJSON(secrets) }}
secrets_env: production
file_name_prod: .env.prod

- name: Install Scaleway Plugin and Deploy
uses: serverless/github-action@v3.2
with:
args: -c "serverless plugin install --name serverless-scaleway-functions && serverless deploy" #env vars need to be set in Github Secrets for now
entrypoint: /bin/sh
40 changes: 40 additions & 0 deletions .github/workflows/test-on-pr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: Test on push
on:
pull_request:
branches:
- main
- dev
jobs:
test:
environment:
name: dev
runs-on: ubuntu-latest
steps:
- name: Convert secrets to env vars
uses: Firenza/secrets-to-env@v1.2.0
with:
secrets: ${{ toJSON(secrets) }}

- name: Checkout Code
uses: actions/checkout@v4

- name: Setup Go 1.20
uses: actions/setup-go@v4
with:
go-version: '1.20'

- name: Install all dependencies
run: cd ${{github.workspace}}/scw_secret_wrapper && go get . && cd ${{github.workspace}}/helper && go get . && cd ${{github.workspace}}/sign && go get . && cd ${{github.workspace}}/cronjob && go get .

- name: Sign tests
run: cd ${{github.workspace}}/sign && go test -v

- name: Run scw_secret_wrapper tests
run: cd ${{github.workspace}}/scw_secret_wrapper && go test ./... -v

- name: Run helper tests
run: cd ${{github.workspace}}/helper && go test -v

- name: Run cronjob tests
run: cd ${{github.workspace}}/cronjob && go test ./... -v

23 changes: 21 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,25 @@
*.pem
*.hex
decentproof-66628-firebase-adminsdk-5po37-26b01e1c7e.json
*.env
*.env*
node_modules/
.DS_STORE
.DS_STORE
*.zip

# Go specific files taken from: https://github.com/github/gitignore/blob/main/Go.gitignore

# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib

# Test binary, built with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# ignore vendor folder
vendor/
88 changes: 88 additions & 0 deletions cronjob/cronjob.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package decentproof_cronjob

import (
"net/http"
"os"
"strconv"

scw_secret_manager "github.com/Flajt/decentproof-backend/scw_secret_wrapper"
)

func Handle(w http.ResponseWriter, r *http.Request) {
var setupData = scw_secret_manager.ScaleWaySetupData{ProjectID: os.Getenv("SCW_DEFAULT_PROJECT_ID"), AccessKey: os.Getenv("SCW_ACCESS_KEY"), SecretKey: os.Getenv("SCW_SECRET_KEY"), Region: os.Getenv("SCW_DEFAULT_REGION")}

//TODO; Find a way to make things less messy
wrapper := scw_secret_manager.NewScaleWayWrapper(setupData)

// Step one: Check for existing keys
secretHolder, err := wrapper.ListSecrets("apiKey")
if err != nil {
returnError(w, err)
panic(err)
}
if secretHolder.TotalCount == 0 {
apiKey := GenerateApiKey()
keyAsBytes := []byte(apiKey)
if _, err := wrapper.SetSecret("apiKey", keyAsBytes); err != nil {
panic(err)
}
w.Header().Set("Content-type", "text/plain")
w.WriteHeader(http.StatusOK)
w.Write([]byte("Done"))
} else {
if versionHolder, err := wrapper.ListSecretVersions(secretHolder.Secrets[0].ID); err != nil {
panic(err)
} else {
if versionHolder.TotalCount == 2 {
firstSecret := versionHolder.SecretVersions[0]
secondSecret := versionHolder.SecretVersions[1]
secretOneCreationTime := firstSecret.CreatedAt
secretTwoCreationTime := secondSecret.CreatedAt
firstSecretCreationDateLater := secretOneCreationTime.After(*secretTwoCreationTime)
if firstSecretCreationDateLater {
//Delete secret 2
if err := wrapper.DeleteSecretVersion(secondSecret.SecretID, strconv.FormatUint(uint64(secondSecret.Revision), 10)); err != nil {
returnError(w, err)
panic(err)
}
} else {
if err := wrapper.DeleteSecretVersion(firstSecret.SecretID, strconv.FormatUint(uint64(firstSecret.Revision), 10)); err != nil {
returnError(w, err)
panic(err)
}
apiKey := GenerateApiKey()
apiKeyBytes := []byte(apiKey)
//TODO: Can this duplication be removed?
if firstSecretCreationDateLater {
if err := wrapper.CreateNewSecretVersion(*secretHolder.Secrets[1], apiKeyBytes); err != nil {
returnError(w, err)
panic(err)
}
} else {
if err := wrapper.CreateNewSecretVersion(*secretHolder.Secrets[0], apiKeyBytes); err != nil {
returnError(w, err)
panic(err)
}
}
}
} else {
apiKey := GenerateApiKey()
apiKeyBytes := []byte(apiKey)
if err := wrapper.CreateNewSecretVersion(*secretHolder.Secrets[0], apiKeyBytes); err != nil {
returnError(w, err)
panic(err)
}
}
w.Header().Set("Content-type", "text/plain")
w.WriteHeader(http.StatusOK)
w.Write([]byte("Done"))
}

}
}

func returnError(w http.ResponseWriter, err error) {
w.Header().Set("Content-type", "text/plain")
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error()))
}
16 changes: 16 additions & 0 deletions cronjob/generate_api_key.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package decentproof_cronjob

import (
"crypto/rand"
"encoding/base64"
)

func GenerateApiKey() string {
bytes := make([]byte, 32) // 32 bytes = 256 bits = 2^256 possible keys
if _, err := rand.Read(bytes); err != nil {
panic(err)
} else {
return base64.StdEncoding.EncodeToString(bytes)
}

}
15 changes: 15 additions & 0 deletions cronjob/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module github.com/Flajt/decentproof-backend/decentproof-cron

go 1.20

replace github.com/Flajt/decentproof-backend/scw_secret_wrapper => ../scw_secret_wrapper

require (
github.com/Flajt/decentproof-backend/scw_secret_wrapper v0.0.0-00010101000000-000000000000
github.com/joho/godotenv v1.5.1
)

require (
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.21 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)
8 changes: 8 additions & 0 deletions cronjob/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.21 h1:yWfiTPwYxB0l5fGMhl/G+liULugVIHD9AU77iNLrURQ=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.21/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
19 changes: 19 additions & 0 deletions cronjob/tests/api_key_generator_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package decentproof_cronjob

import (
"testing"

decentproof_cronjob "github.com/Flajt/decentproof-backend/decentproof-cron"
)

func TestKeyGeneration(t *testing.T) {
if key := decentproof_cronjob.GenerateApiKey(); key == "" {
t.Error("Key is empty")
} else {
if len(key)%4 != 0 {
t.Error("Key is not a multiple of 4")
t.Log(len(key))
}
}

}
92 changes: 92 additions & 0 deletions cronjob/tests/cronjob_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package decentproof_cronjob

import (
"net/http"
"os"
"testing"

scw_wrapper "github.com/Flajt/decentproof-backend/scw_secret_wrapper"
"github.com/joho/godotenv"

decentproof_cronjob "github.com/Flajt/decentproof-backend/decentproof-cron"
)

// MockResponseWriter is a basic mock implementation of http.ResponseWriter.
type MockResponseWriter struct {
StatusCode int
HeaderMap http.Header
Body []byte
}

func (m *MockResponseWriter) WriteHeader(statusCode int) {
m.StatusCode = statusCode
}

func (m *MockResponseWriter) Header() http.Header {
if m.HeaderMap == nil {
m.HeaderMap = make(http.Header)
}
return m.HeaderMap
}

func (m *MockResponseWriter) Write(data []byte) (int, error) {
m.Body = append(m.Body, data...)
return len(data), nil
}

func TestCronjob(t *testing.T) {
godotenv.Load("../.env")
var setupData = scw_wrapper.ScaleWaySetupData{ProjectID: os.Getenv("SCW_DEFAULT_PROJECT_ID"), AccessKey: os.Getenv("SCW_ACCESS_KEY"), SecretKey: os.Getenv("SCW_SECRET_KEY"), Region: os.Getenv("SCW_DEFAULT_REGION")}
t.Run("with zero entries", func(t *testing.T) {
wrapper := scw_wrapper.NewScaleWayWrapper(setupData)
decentproof_cronjob.Handle(&MockResponseWriter{}, nil)
want := 1
secretHolder, err := wrapper.ListSecrets()
if err != nil {
t.Error(err)
}
if secretHolder.TotalCount != uint32(want) {
t.Errorf("Got %d secrets, wanted %d", secretHolder.TotalCount, want)
}
versionHolder, err := wrapper.ListSecretVersions(secretHolder.Secrets[0].ID)
if err != nil {
t.Error(err)
}
if versionHolder.TotalCount != uint32(want) {
t.Errorf("Got %d secrets, wanted %d", versionHolder.TotalCount, want)
}
scw_wrapper.CleanUp(t)
})

t.Run("with two entries", func(t *testing.T) {
wrapper := scw_wrapper.NewScaleWayWrapper(setupData)
testInputAsBytes := []byte("test")
secret, err := wrapper.SetSecret("apiKey", testInputAsBytes)
if err != nil {
t.Error(err)
}

if err := wrapper.CreateNewSecretVersion(*secret, []byte("test2")); err != nil {
t.Error(err)
}
decentproof_cronjob.Handle(&MockResponseWriter{}, nil)
secretWant := 1
versionWant := 2
secretHolder, err := wrapper.ListSecrets()
if err != nil {
t.Error(err)
}
if secretHolder.TotalCount != uint32(secretWant) {
t.Errorf("Got %d secrets, wanted %d", secretHolder.TotalCount, secretWant)
}
versionHolder, err := wrapper.ListSecretVersions(secretHolder.Secrets[0].ID)
if err != nil {
t.Error(err)
}
if versionHolder.TotalCount != uint32(versionWant) {
t.Errorf("Got %d secrets, wanted %d", versionHolder.TotalCount, versionWant)
}
})

t.Cleanup(func() { scw_wrapper.CleanUp(t) })
}
38 changes: 38 additions & 0 deletions get_new_key/appcheck.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package get_new_key

import (
"context"
"os"

firebase "firebase.google.com/go/v4"
"google.golang.org/api/option"
)

type AppcheckWrapper struct {
App firebase.App
}

func NewAppcheckWrapper() *AppcheckWrapper {
//Important GOOGLE_ADMIN_SDK_CREDS needs to be set for this to work
if json, success := os.LookupEnv("GOOGLE_ADMIN_SDK_CREDS"); !success {
panic("Admin Creds not found in enviroment")
} else {
opt := option.WithCredentialsJSON([]byte(json))
if app, err := firebase.NewApp(context.Background(), nil, opt); err != nil {
panic(err)
} else {
return &AppcheckWrapper{App: *app}
}
}
}

func (appcheckWrapper *AppcheckWrapper) CheckApp(token string) (bool, error) {
if client, err := appcheckWrapper.App.AppCheck(context.Background()); err != nil {
panic(err)
} else {
if _, err := client.VerifyToken(token); err != nil {
return false, err
}
return true, nil
}
}
Loading

0 comments on commit dacc8a2

Please sign in to comment.