first commit
This commit is contained in:
@@ -0,0 +1,209 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/md5"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/mrhid6/keymanager/server/internal/db"
|
||||
"github.com/mrhid6/keymanager/server/internal/models"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
)
|
||||
|
||||
func computeFingerprint(pubKey string) string {
|
||||
parts := strings.Fields(pubKey)
|
||||
if len(parts) < 2 {
|
||||
return ""
|
||||
}
|
||||
raw, err := base64.StdEncoding.DecodeString(parts[1])
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
sum := md5.Sum(raw)
|
||||
var pairs []string
|
||||
for _, b := range sum {
|
||||
pairs = append(pairs, fmt.Sprintf("%02x", b))
|
||||
}
|
||||
return "MD5:" + strings.Join(pairs, ":")
|
||||
}
|
||||
|
||||
func CreateKey(label, publicKey, source, generatedByServerID string) (*models.Key, error) {
|
||||
key := &models.Key{
|
||||
KeyID: uuid.NewString(),
|
||||
Label: label,
|
||||
PublicKey: publicKey,
|
||||
Fingerprint: computeFingerprint(publicKey),
|
||||
Source: source,
|
||||
GeneratedByServerID: generatedByServerID,
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
_, err := db.Col("keys").InsertOne(ctx, key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return key, nil
|
||||
}
|
||||
|
||||
func GetKey(keyID string) (*models.Key, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
var key models.Key
|
||||
err := db.Col("keys").FindOne(ctx, bson.M{"key_id": keyID}).Decode(&key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &key, nil
|
||||
}
|
||||
|
||||
func ListKeys() ([]models.Key, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
cursor, err := db.Col("keys").Find(ctx, bson.M{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer cursor.Close(ctx)
|
||||
|
||||
var keys []models.Key
|
||||
if err := cursor.All(ctx, &keys); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return keys, nil
|
||||
}
|
||||
|
||||
func DeleteKey(keyID string) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
_, err := db.Col("keys").DeleteOne(ctx, bson.M{"key_id": keyID})
|
||||
return err
|
||||
}
|
||||
|
||||
func AssignKey(keyID, serverID string) (*models.Assignment, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
// Check if already assigned and active
|
||||
var existing models.Assignment
|
||||
err := db.Col("assignments").FindOne(ctx, bson.M{
|
||||
"key_id": keyID,
|
||||
"server_id": serverID,
|
||||
"revoked_at": nil,
|
||||
}).Decode(&existing)
|
||||
if err == nil {
|
||||
return &existing, nil
|
||||
}
|
||||
|
||||
a := &models.Assignment{
|
||||
KeyID: keyID,
|
||||
ServerID: serverID,
|
||||
AssignedAt: time.Now(),
|
||||
}
|
||||
_, err = db.Col("assignments").InsertOne(ctx, a)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
func RevokeAssignment(keyID, serverID string) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
now := time.Now()
|
||||
_, err := db.Col("assignments").UpdateOne(ctx,
|
||||
bson.M{"key_id": keyID, "server_id": serverID, "revoked_at": nil},
|
||||
bson.M{"$set": bson.M{"revoked_at": now}},
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
func GetAssignmentsForKey(keyID string) ([]models.Assignment, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
cursor, err := db.Col("assignments").Find(ctx, bson.M{"key_id": keyID, "revoked_at": nil})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer cursor.Close(ctx)
|
||||
|
||||
var assignments []models.Assignment
|
||||
if err := cursor.All(ctx, &assignments); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return assignments, nil
|
||||
}
|
||||
|
||||
type AssignmentWithServer struct {
|
||||
models.Assignment `bson:",inline"`
|
||||
Server *models.Server `json:"server,omitempty"`
|
||||
}
|
||||
|
||||
func GetAssignmentsWithServers(keyID string) ([]AssignmentWithServer, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
cursor, err := db.Col("assignments").Find(ctx, bson.M{"key_id": keyID})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer cursor.Close(ctx)
|
||||
|
||||
var assignments []models.Assignment
|
||||
if err := cursor.All(ctx, &assignments); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := make([]AssignmentWithServer, 0, len(assignments))
|
||||
for _, a := range assignments {
|
||||
item := AssignmentWithServer{Assignment: a}
|
||||
var srv models.Server
|
||||
if err := db.Col("servers").FindOne(ctx, bson.M{"server_id": a.ServerID}).Decode(&srv); err == nil {
|
||||
item.Server = &srv
|
||||
}
|
||||
result = append(result, item)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
type AssignmentWithKey struct {
|
||||
models.Assignment `bson:",inline"`
|
||||
Key *models.Key `json:"key,omitempty"`
|
||||
}
|
||||
|
||||
func GetAssignmentsWithKeysForServer(serverID string) ([]AssignmentWithKey, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
cursor, err := db.Col("assignments").Find(ctx, bson.M{"server_id": serverID})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer cursor.Close(ctx)
|
||||
|
||||
var assignments []models.Assignment
|
||||
if err := cursor.All(ctx, &assignments); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := make([]AssignmentWithKey, 0, len(assignments))
|
||||
for _, a := range assignments {
|
||||
item := AssignmentWithKey{Assignment: a}
|
||||
var key models.Key
|
||||
if err := db.Col("keys").FindOne(ctx, bson.M{"key_id": a.KeyID}).Decode(&key); err == nil {
|
||||
item.Key = &key
|
||||
}
|
||||
result = append(result, item)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
Reference in New Issue
Block a user