Kaynağa Gözat

add basic auth stuff

reid 2 yıl önce
ebeveyn
işleme
19736e50e6
2 değiştirilmiş dosya ile 156 ekleme ve 2 silme
  1. 153 0
      auth/auth.go
  2. 3 2
      rectify/rectify.go

+ 153 - 0
auth/auth.go

@@ -0,0 +1,153 @@
+package main
+
+import (
+	"crypto/rand"
+	"crypto/sha256"
+	"encoding/base64"
+	"encoding/hex"
+	"encoding/json"
+	"goseg/config"
+	"fmt"
+	"time"
+
+	"golang.org/x/crypto/nacl/secretbox"
+)
+
+// CheckToken checks the validity of the token.
+func CheckToken(token string, websocket interface{}, setup bool) (bool, string, error) {
+	if token == "" {
+		authStatus := false
+		if setup {
+			authStatus = true
+		}
+		newToken, err := CreateToken(websocket, setup)
+		if err != nil {
+			return false, "", err
+		}
+		return authStatus, newToken["token"], nil
+	}
+
+	// Token verification logic here...
+	// ...
+
+	return false, "", nil
+}
+
+// CreateToken creates a new session token.
+func CreateToken(websocket interface{}, setup bool) (map[string]string, error) {
+	// placeholder logic for IP and UserAgent
+	ip := "localhost"
+	userAgent := "lick"
+	// if more properties are needed from websocket, you can extract them here
+	conf := config.Conf()
+	key := conf.KeyFile
+	// generate random strings for id, secret, and padding
+	id := NewSecretString(32)
+	secret := NewSecretString(128)
+	padding := NewSecretString(32)
+	contents := map[string]string{
+		"id":         id,
+		"ip":         ip,
+		"user_agent": userAgent,
+		"secret":     secret,
+		"padding":    padding,
+		"authorized": fmt.Sprintf("%v", setup),
+		"created":    time.Now().Format("2006-01-02_15:04:05"),
+	}
+	// encrypt the contents
+	encryptedText, err := KeyfileEncrypt(contents, key)
+	if err != nil {
+		return nil, fmt.Errorf("failed to encrypt token: %v", err)
+	}
+	// and hash
+	hashed := sha256.Sum256([]byte(encryptedText))
+	// Update sessions in the system's configuration
+	now := time.Now().Format("2006-01-02_15:04:05")
+	if setup {
+		updates := map[string]interface{}{
+			"Sessions": map[string]interface{}{
+				"Authorized": map[string]string{
+					"Hash":    hex.EncodeToString(hashed[:]),
+					"Created": now,
+				},
+			},
+		}
+		config.UpdateConf(updates)
+	} else {
+		updates := map[string]interface{}{
+			"Sessions": map[string]interface{}{
+				"Unauthorized": map[string]string{
+					"Hash":    hex.EncodeToString(hashed[:]),
+					"Created": now,
+				},
+			},
+		}
+		config.UpdateConf(updates)
+	}
+	return map[string]string{
+		"id":    id,
+		"token": encryptedText,
+	}, nil
+}
+
+// encrypt the contents using stored keyfile val
+func KeyfileEncrypt(contents map[string]string, key string) (string, error) {
+	contentBytes, err := json.Marshal(contents)
+	if err != nil {
+		return "", err
+	}
+	// convert key to bytes
+	keyBytes := []byte(key)
+	if len(keyBytes) != 32 {
+		return "", fmt.Errorf("key must be 32 bytes in length")
+	}
+	var keyArray [32]byte
+	copy(keyArray[:], keyBytes)
+	// generate nonce
+	var nonce [24]byte
+	if _, err := rand.Read(nonce[:]); err != nil {
+		return "", err
+	}
+	// encrypt contents
+	encrypted := secretbox.Seal(nonce[:], contentBytes, &nonce, &keyArray)
+	return base64.URLEncoding.EncodeToString(encrypted), nil
+}
+
+// decrypt routine
+func KeyfileDecrypt(encryptedText string, key string) (map[string]string, error) {
+	// get bytes
+    keyBytes := []byte(key)
+    var keyArray [32]byte
+    copy(keyArray[:], keyBytes)
+    encryptedBytes, err := base64.URLEncoding.DecodeString(encryptedText)
+    if err != nil {
+        return nil, err
+    }
+	// get nonce
+    var nonce [24]byte
+    copy(nonce[:], encryptedBytes[:24])
+	// attempt decrypt
+    decrypted, ok := secretbox.Open(nil, encryptedBytes[24:], &nonce, &keyArray)
+    if !ok {
+        return nil, fmt.Errorf("Decryption failed")
+    }
+    var contents map[string]string
+    if err := json.Unmarshal(decrypted, &contents); err != nil {
+        return nil, err
+    } 
+    return contents, nil
+}
+
+// NewSecretString generates a random secret string of the given length.
+func NewSecretString(length int) string {
+	randBytes := make([]byte, length)
+	_, err := rand.Read(randBytes)
+	if err != nil {
+		return ""
+	}
+	return base64.URLEncoding.EncodeToString(randBytes)
+}
+
+func main() {
+	fmt.Println("Compiled")
+}

+ 3 - 2
rectify/rectify.go

@@ -41,6 +41,7 @@ func DockerSubscriptionHandler() {
 				if containerState.DesiredStatus != "stopped" {
 					docker.StartContainer(contName, containerState.Type)
 				}
+				broadcast.BroadcastToClients()
 			}
 
 		case "start":
@@ -49,6 +50,7 @@ func DockerSubscriptionHandler() {
 			if containerState, exists := config.GetContainerState()[contName]; exists {
 				containerState.ActualStatus = "running"
 				config.UpdateContainerState(contName, containerState)
+				broadcast.BroadcastToClients()
 			}
 
 		case "die":
@@ -58,14 +60,13 @@ func DockerSubscriptionHandler() {
 				// we don't want infinite restart loop
 				containerState.DesiredStatus = "died"
 				config.UpdateContainerState(contName, containerState)
+				broadcast.BroadcastToClients()
 			}
 
 		default:
 			if config.DebugMode == true {
 				logger.Info(fmt.Sprintf("%s event: %s", contName, dockerEvent.Action))
 			}
-			return
 		}
-		broadcast.BroadcastToClients()
 	}
 }