Skip to content

Commit

Permalink
1.4.1 (#12)
Browse files Browse the repository at this point in the history
* Bumped version to 1.4.1

* Prevent deleting of credentials which are in use

* SSL certificate Support
  • Loading branch information
salilponde authored Dec 22, 2023
1 parent 96b353d commit 3df95dc
Show file tree
Hide file tree
Showing 12 changed files with 151 additions and 8 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ on:
branches: ["main"]

env:
VERSION: "1.4"
VERSION: "1.4.1"

jobs:
docker:
Expand Down
1 change: 1 addition & 0 deletions cmd/server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ func main() {
os.Getenv("DB_CONNECTION_STRING"),
os.Getenv("DATA_PATH"),
os.Getenv("LOG_LEVEL"),
os.Getenv("SSL_ENABLED"),
)
s.Run(os.Getenv("BIND_ADDRESS"))
}
2 changes: 1 addition & 1 deletion pkg/common/common.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
package common

const Version = "1.4"
const Version = "1.4.1"
53 changes: 53 additions & 0 deletions pkg/crypto/ssl/ssl.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package ssl

import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"math/big"
"time"
)

func GenerateSelfSignedCert() (cert string, key string, err error) {
privateKey, err := rsa.GenerateKey(rand.Reader, 4096)
if err != nil {
return "", "", err
}

notBefore := time.Now()
notAfter := notBefore.Add(365 * 24 * 10 * time.Hour)
template := x509.Certificate{
SerialNumber: big.NewInt(0),
Subject: pkix.Name{},
SignatureAlgorithm: x509.SHA256WithRSA,
NotBefore: notBefore,
NotAfter: notAfter,
BasicConstraintsValid: true,
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyAgreement | x509.KeyUsageKeyEncipherment | x509.KeyUsageDataEncipherment,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
}
derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &privateKey.PublicKey, privateKey)
if err != nil {
return "", "", err

}

cert = string(pem.EncodeToMemory(
&pem.Block{
Type: "CERTIFICATE",
Bytes: derBytes,
},
))

privateKeyBytes := x509.MarshalPKCS1PrivateKey(privateKey)
key = string(pem.EncodeToMemory(
&pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: privateKeyBytes,
},
))

return cert, key, nil
}
10 changes: 10 additions & 0 deletions pkg/server/handler/credential.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package handler

import (
"errors"
"strconv"

"github.com/productiveops/dokemon/pkg/server/model"
Expand Down Expand Up @@ -109,6 +110,15 @@ func (h *Handler) DeleteCredentialById(c echo.Context) error {
return resourceNotFound(c, "Credential")
}

inUse, err := h.credentialStore.IsInUse(uint(id))
if err != nil {
panic(err)
}

if inUse {
return unprocessableEntity(c, errors.New("Credentials are in use and cannot be deleted"))
}

if err := h.credentialStore.DeleteById(uint(id)); err != nil {
panic(err)
}
Expand Down
57 changes: 55 additions & 2 deletions pkg/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ import (
"errors"
"net/http"
"os"
"path"
"strings"
"time"

"github.com/productiveops/dokemon/pkg/common"
"github.com/productiveops/dokemon/pkg/crypto/ske"
"github.com/productiveops/dokemon/pkg/crypto/ssl"
"github.com/productiveops/dokemon/pkg/server/handler"
"github.com/productiveops/dokemon/pkg/server/model"
"github.com/productiveops/dokemon/pkg/server/requestutil"
Expand All @@ -28,19 +30,24 @@ import (
type Server struct {
Echo *echo.Echo
handler *handler.Handler
dataPath string
sslEnabled bool
}

func (s *Server) Init(dbConnectionString string, dataPath string, logLevel string) {
func (s *Server) Init(dbConnectionString string, dataPath string, logLevel string, sslEnabled string) {
setLogLevel(logLevel)
log.Info().Msg("Starting Dokemon v" + common.Version)

if dataPath == "" {
dataPath = "/data"
}
s.dataPath = dataPath

if dbConnectionString == "" {
dbConnectionString = dataPath + "/db"
}

s.sslEnabled = sslEnabled == "1"

// Init compose projects directory
composeProjectsPath := dataPath + "/compose"
Expand Down Expand Up @@ -126,7 +133,18 @@ func (s *Server) Run(addr string) {
addr = ":9090"
}

err := s.Echo.Start(addr)
var err error
if s.sslEnabled {
certsDirPath := path.Join(s.dataPath, "certs")
certPath := path.Join(certsDirPath, "server.crt")
keyPath := path.Join(certsDirPath, "server.key")
s.generateSelfSignedCerts(certsDirPath, certPath, keyPath)

err = s.Echo.StartTLS(addr, certPath, keyPath)
} else {
err = s.Echo.Start(addr)
}

if err != nil {
panic(err)
}
Expand Down Expand Up @@ -154,6 +172,41 @@ func (s *Server) authMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
}
}

func (s *Server) generateSelfSignedCerts(certDirPath string, certPath string, keyPath string) {
if _, err := os.Stat(certDirPath); errors.Is(err, os.ErrNotExist) {
err := os.MkdirAll(certDirPath, os.ModePerm)
if err != nil {
panic(err)
}
}
if _, err := os.Stat(certPath); errors.Is(err, os.ErrNotExist) {
log.Debug().Msg("SSL certificate file does not exist. Generating self-signed certificate...")

cert, key, err := ssl.GenerateSelfSignedCert()
if err != nil {
panic(err)
}

certFile, err := os.Create(certPath)
if err != nil {
panic(err)
}
_, err = certFile.WriteString(cert)
if err != nil {
panic(err)
}

keyFile, err := os.Create(keyPath)
if err != nil {
panic(err)
}
_, err = keyFile.WriteString(key)
if err != nil {
panic(err)
}
}
}

func setLogLevel(logLevel string) {
log.Info().Str("level", logLevel).Msg("Setting log level")
switch logLevel {
Expand Down
23 changes: 23 additions & 0 deletions pkg/server/store/credential.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,30 @@ func (s *SqlCredentialStore) Exists(id uint) (bool, error) {
return count > 0, nil
}

func (s *SqlCredentialStore) IsInUse(id uint) (bool, error) {
var ncp_ref_count, cli_ref_count int64

if err := s.db.Model(&model.NodeComposeProject{}).Where("credential_id = ?", id).Count(&ncp_ref_count).Error; err != nil {
return false, err
}

if err := s.db.Model(&model.ComposeLibraryItem{}).Where("credential_id = ?", id).Count(&cli_ref_count).Error; err != nil {
return false, err
}

return (ncp_ref_count + cli_ref_count) > 0, nil
}

func (s *SqlCredentialStore) DeleteById(id uint) error {
inUse, err := s.IsInUse(id)
if err != nil {
return err
}

if inUse {
return errors.New("Credentials are in use and cannot be deleted")
}

if err := s.db.Delete(&model.Credential{}, id).Error; err != nil {
return err
}
Expand Down
1 change: 0 additions & 1 deletion pkg/server/store/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ func (s *SqlEnvironmentStore) IsInUse(id uint) (bool, error) {
return node_ref_count > 0, nil
}


func (s *SqlEnvironmentStore) DeleteById(id uint) error {
inUse, err := s.IsInUse(id)
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions pkg/server/store/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ type CredentialStore interface {
Update(m *model.Credential) error
GetById(id uint) (*model.Credential, error)
GetList(pageNo, pageSize uint) ([]model.Credential, int64, error)
IsInUse(id uint) (bool, error)
DeleteById(id uint) error
Exists(id uint) (bool, error)

Expand Down
1 change: 1 addition & 0 deletions runserver.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ go build .\cmd\server\
$env:DB_CONNECTION_STRING="c:\temp\dokemondata\db"
$env:DATA_PATH="c:\temp\dokemondata"
$env:LOG_LEVEL="DEBUG"
$env:SSL_ENABLED="1"
.\server.exe
2 changes: 1 addition & 1 deletion web/src/lib/version.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export const VERSION = "1.4"
export const VERSION = "1.4.1"
6 changes: 4 additions & 2 deletions web/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ export default defineConfig(({ command, mode }) => {
if (mode === "development") {
proxy = {
"/api": {
target: "http://localhost:9090",
target: "https://localhost:9090",
secure: false, // Allow self-signed certificates
},
"/ws": {
target: "http://localhost:9090",
target: "https://localhost:9090",
ws: true,
secure: false, // Allow self-signed certificates
},
}
}
Expand Down

0 comments on commit 3df95dc

Please sign in to comment.