add postgres db
This commit is contained in:
parent
5a6ccbc588
commit
3835b8ba86
33
Makefile
33
Makefile
@ -1,12 +1,15 @@
|
||||
GO_FILES := $(shell find . -name '*.go' -not -path './build/*')
|
||||
GO_FILES := $(shell find . -name '*.go' -not -path './build/*' -not -path './tmp/**')
|
||||
GOOSE_DBSTRING := "user=zadmin_user password=s3cret! dbname=zadmin_dev sslmode=disable host=localhost"
|
||||
GOOSE_MIGRATION_PATH := "./db/migrations/"
|
||||
GOOSE_SEED_PATH := "./db/seed/"
|
||||
|
||||
build-server: $(GO_FILES)
|
||||
mkdir -p build
|
||||
go build -o build/zadmin-server ./cmd/server/main.go
|
||||
CGO_ENABLED=0 go build -o build/zadmin-server ./cmd/server/main.go
|
||||
|
||||
build-client: $(GO_FILES)
|
||||
mkdir -p build
|
||||
go build -o build/zadmin-client ./cmd/client/main.go
|
||||
CGO_ENABLED=0 go build -o build/zadmin-client ./cmd/client/main.go
|
||||
|
||||
docker-up:
|
||||
mkdir -p ./tmp
|
||||
@ -16,6 +19,7 @@ docker-down:
|
||||
docker compose -f ./deployments/compose-dev.yaml down
|
||||
|
||||
docker-clean: docker-down
|
||||
docker volume rm -f deployments_pg_data
|
||||
rm -rf ./tmp
|
||||
|
||||
server: build-server
|
||||
@ -27,4 +31,25 @@ client: build-client
|
||||
clean:
|
||||
rm -r build
|
||||
|
||||
.PHONY: clean run-server run-client docker-up
|
||||
install-goose:
|
||||
go install github.com/pressly/goose/v3/cmd/goose@latest
|
||||
|
||||
db-status:
|
||||
@GOOSE_DRIVER=postgres GOOSE_DBSTRING=$(GOOSE_DBSTRING) goose -dir=$(GOOSE_MIGRATION_PATH) status
|
||||
|
||||
db-up:
|
||||
@GOOSE_DRIVER=postgres GOOSE_DBSTRING=$(GOOSE_DBSTRING) goose -dir=$(GOOSE_MIGRATION_PATH) up
|
||||
|
||||
db-reset:
|
||||
@GOOSE_DRIVER=postgres GOOSE_DBSTRING=$(GOOSE_DBSTRING) goose -dir=$(GOOSE_MIGRATION_PATH) reset
|
||||
|
||||
goose-custom:
|
||||
@GOOSE_DRIVER=postgres GOOSE_DBSTRING=$(GOOSE_DBSTRING) goose -dir=$(GOOSE_MIGRATION_PATH) $(cmd)
|
||||
|
||||
goose-seed-custom:
|
||||
@GOOSE_DRIVER=postgres GOOSE_DBSTRING=$(GOOSE_DBSTRING) goose -dir=$(GOOSE_SEED_PATH) $(cmd)
|
||||
|
||||
db-seed:
|
||||
echo "TODO"
|
||||
|
||||
.PHONY: clean run-server run-client docker-up docker-down docker-clean server client install-goose
|
||||
|
@ -69,3 +69,7 @@ Ideas???
|
||||
- The admin runs a installer with this credential
|
||||
- The installer enrolls the device in zadmin and generates a unique package for this machine
|
||||
- The installer places this package on the machine
|
||||
|
||||
## Docs
|
||||
|
||||
[goose](https://github.com/pressly/goose) is used for migrations
|
||||
|
@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"runtime"
|
||||
|
||||
"git.mziesel.nl/mans/zadmin/internal/models"
|
||||
"github.com/nats-io/nats.go"
|
||||
@ -37,7 +38,9 @@ func main() {
|
||||
}
|
||||
})
|
||||
|
||||
shouldExit := false
|
||||
for !shouldExit {
|
||||
}
|
||||
// shouldExit := false
|
||||
// for !shouldExit {
|
||||
// }
|
||||
// keep running indefenitly
|
||||
runtime.Goexit()
|
||||
}
|
||||
|
22
database/machine.go
Normal file
22
database/machine.go
Normal file
@ -0,0 +1,22 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
|
||||
"git.mziesel.nl/mans/zadmin/internal/models"
|
||||
"github.com/oklog/ulid/v2"
|
||||
)
|
||||
|
||||
func CreateMachine(db *sql.DB, m *models.Machine) error {
|
||||
query := "INSERT INTO machine (machine_name, os_type, os_arch) VALUES ($1, $2, $3)"
|
||||
_, err := db.Exec(query, m.MachineName, m.OsType, m.GoArch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetMachine(db *sql.DB) *models.Machine {
|
||||
ulid.Now()
|
||||
return &models.Machine{}
|
||||
}
|
13
db/migrations/20241214113527_add_ulid_functions.sql
Normal file
13
db/migrations/20241214113527_add_ulid_functions.sql
Normal file
@ -0,0 +1,13 @@
|
||||
-- +goose Up
|
||||
-- +goose StatementBegin
|
||||
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
||||
CREATE OR REPLACE FUNCTION generate_ulid() RETURNS uuid
|
||||
AS $$
|
||||
SELECT (lpad(to_hex(floor(extract(epoch FROM clock_timestamp()) * 1000)::bigint), 12, '0') || encode(gen_random_bytes(10), 'hex'))::uuid;
|
||||
$$ LANGUAGE SQL;
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose Down
|
||||
-- +goose StatementBegin
|
||||
DROP FUNCTION generate_ulid();
|
||||
-- +goose StatementEnd
|
26
db/migrations/20241214113904_add_machine_table.sql
Normal file
26
db/migrations/20241214113904_add_machine_table.sql
Normal file
@ -0,0 +1,26 @@
|
||||
-- +goose Up
|
||||
-- +goose StatementBegin
|
||||
CREATE TABLE machine (
|
||||
id UUID NOT NULL DEFAULT generate_ulid(),
|
||||
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
machine_name VARCHAR(255) NOT NULL,
|
||||
description text,
|
||||
os_type VARCHAR(255) NOT NULL,
|
||||
os_arch VARCHAR(255) NOT NULL,
|
||||
hostname VARCHAR(255),
|
||||
public_ipv4_address INET,
|
||||
public_ipv6_address INET,
|
||||
agent_version VARCHAR(255),
|
||||
host_uptime VARCHAR(255),
|
||||
logged_on_users VARCHAR(255),
|
||||
os_version VARCHAR(255),
|
||||
|
||||
PRIMARY KEY(id)
|
||||
);
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose Down
|
||||
-- +goose StatementBegin
|
||||
DROP TABLE machine;
|
||||
-- +goose StatementEnd
|
17
db/migrations/20241214133322_add_agent_table.sql
Normal file
17
db/migrations/20241214133322_add_agent_table.sql
Normal file
@ -0,0 +1,17 @@
|
||||
-- +goose Up
|
||||
-- +goose StatementBegin
|
||||
CREATE TABLE agent (
|
||||
id UUID NOT NULL DEFAULT generate_ulid(),
|
||||
machine_id UUID NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
PRIMARY KEY(id),
|
||||
FOREIGN KEY (machine_id) REFERENCES machine(id)
|
||||
);
|
||||
CREATE INDEX idx_agent_machine_id ON agent(machine_id);
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose Down
|
||||
-- +goose StatementBegin
|
||||
DROP TABLE agent;
|
||||
-- +goose StatementEnd
|
42
db/seed/seed.go
Normal file
42
db/seed/seed.go
Normal file
@ -0,0 +1,42 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"git.mziesel.nl/mans/zadmin/database"
|
||||
"git.mziesel.nl/mans/zadmin/internal/models"
|
||||
_ "github.com/lib/pq"
|
||||
"github.com/oklog/ulid/v2"
|
||||
)
|
||||
|
||||
func main() {
|
||||
db, err := sql.Open("postgres", "user=zadmin_user password=s3cret! dbname=zadmin_dev sslmode=disable host=localhost")
|
||||
if err != nil {
|
||||
log.Fatalf("goose: failed to open DB: %v\n", err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err := db.Close(); err != nil {
|
||||
log.Fatalf("failed to close DB: %v\n", err)
|
||||
}
|
||||
}()
|
||||
|
||||
createTestMachines(db)
|
||||
}
|
||||
|
||||
func createTestMachines(db *sql.DB) {
|
||||
machine := models.Machine{
|
||||
ID: ulid.Make(),
|
||||
MachineName: "test-machine",
|
||||
OsType: "linux",
|
||||
GoArch: "amd64",
|
||||
}
|
||||
fmt.Println(models.PrettyFormatData(machine))
|
||||
|
||||
err := database.CreateMachine(db, &machine)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
@ -1,6 +1,33 @@
|
||||
services:
|
||||
nats-server:
|
||||
image: nats:latest
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- 4222:4222
|
||||
command: ["-DV"]
|
||||
postgres:
|
||||
image: postgres:16-alpine
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- 5432:5432
|
||||
volumes:
|
||||
- pg_data:/var/lib/postgresql/data
|
||||
environment:
|
||||
- POSTGRES_PASSWORD=s3cret!
|
||||
- POSTGRES_USER=zadmin_user
|
||||
- POSTGRES_DB=zadmin_dev
|
||||
pgadmin:
|
||||
image: dpage/pgadmin4
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "8888:80"
|
||||
environment:
|
||||
PGADMIN_DEFAULT_EMAIL: mans@mziesel.com
|
||||
PGADMIN_DEFAULT_PASSWORD: secret
|
||||
PGADMIN_LISTEN_PORT: 80
|
||||
volumes:
|
||||
- pgadmin_data:/var/lib/pgadmin
|
||||
|
||||
volumes:
|
||||
pg_data: {}
|
||||
pgadmin_data: {}
|
||||
|
9
go.mod
9
go.mod
@ -3,14 +3,17 @@ module git.mziesel.nl/mans/zadmin
|
||||
go 1.23.0
|
||||
|
||||
require (
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/lib/pq v1.10.9
|
||||
github.com/mackerelio/go-osstat v0.2.5
|
||||
github.com/nats-io/nats.go v1.37.0
|
||||
golang.org/x/sys v0.20.0
|
||||
github.com/oklog/ulid/v2 v2.1.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/klauspost/compress v1.17.2 // indirect
|
||||
github.com/klauspost/compress v1.17.7 // indirect
|
||||
github.com/nats-io/nkeys v0.4.7 // indirect
|
||||
github.com/nats-io/nuid v1.0.1 // indirect
|
||||
golang.org/x/crypto v0.18.0 // indirect
|
||||
golang.org/x/crypto v0.31.0 // indirect
|
||||
golang.org/x/sys v0.28.0 // indirect
|
||||
)
|
||||
|
19
go.sum
19
go.sum
@ -1,5 +1,9 @@
|
||||
github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4=
|
||||
github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg=
|
||||
github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/mackerelio/go-osstat v0.2.5 h1:+MqTbZUhoIt4m8qzkVoXUJg1EuifwlAJSk4Yl2GXh+o=
|
||||
github.com/mackerelio/go-osstat v0.2.5/go.mod h1:atxwWF+POUZcdtR1wnsUcQxTytoHG4uhl2AKKzrOajY=
|
||||
github.com/nats-io/nats.go v1.37.0 h1:07rauXbVnnJvv1gfIyghFEo6lUcYRY0WXc3x7x0vUxE=
|
||||
@ -8,7 +12,10 @@ github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI=
|
||||
github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc=
|
||||
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
|
||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
|
||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
github.com/oklog/ulid/v2 v2.1.0 h1:+9lhoxAP56we25tyYETBBY1YLA2SaoLvUFgrP2miPJU=
|
||||
github.com/oklog/ulid/v2 v2.1.0/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ=
|
||||
github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o=
|
||||
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
|
||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
|
@ -80,7 +80,7 @@ func GetMachineData(ac models.MachineAgentConfig) (models.MachineData, error) {
|
||||
data.PublicIPv6Address = ipResponseBody.Address
|
||||
|
||||
// get machine uptime
|
||||
uptime, err := uptime.GetUptime()
|
||||
uptime, err := uptime.Get()
|
||||
if err != nil {
|
||||
LogError("failed to get machine uptime", err)
|
||||
return data, nil
|
||||
|
@ -1,47 +1,42 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/oklog/ulid/v2"
|
||||
)
|
||||
|
||||
// Model for the user accounts
|
||||
type AccountModel struct {
|
||||
ID string `json:"id"`
|
||||
type Account struct {
|
||||
ID ulid.ULID `json:"id"`
|
||||
FirstName string `json:"first_name"`
|
||||
LastName string `json:"last_name"`
|
||||
PasswordHash string `json:"password_hash"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
type OrganizationModel struct {
|
||||
ID string `json:"id"`
|
||||
type Organization struct {
|
||||
ID ulid.ULID `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
// Model for the hosts managed by zadmin
|
||||
type MachineModel struct {
|
||||
ID string `json:"id"` // machine ID
|
||||
Organization OrganizationModel `json:"organization"` // Organization this machine belongs to
|
||||
CreatedAt time.Time `json:"created_at"` // Time created in zadmin
|
||||
Description string `json:"description"` // Description of machine
|
||||
AgentConfig MachineAgentConfig `json:"agent_config"` // Config used by this machine
|
||||
OsType string `json:"os_type"` // OS Type TODO: make constants
|
||||
GoArch string `json:"go_arch"` // Go arch
|
||||
}
|
||||
|
||||
// Data of the machine
|
||||
type MachineData struct {
|
||||
type Machine struct {
|
||||
ID ulid.ULID `json:"id"` // machine ID
|
||||
MachineName string `json:"machine_name"` // Name of machine
|
||||
Organization Organization `json:"organization"` // Organization this machine belongs to
|
||||
CreatedAt time.Time `json:"created_at"` // Time created in zadmin
|
||||
Description string `json:"description"` // Description of machine
|
||||
OsType string `json:"os_type"` // OS Type TODO: make constants
|
||||
GoArch string `json:"go_arch"` // Go arch
|
||||
FirstSeen time.Time `json:"first_seen"` // Time of first contact with zadmin
|
||||
LastSeen time.Time `json:"last_seen"` // Time of last contact with zadmin
|
||||
Hostname string `json:"hostname"` // Configured system hostname
|
||||
PublicIPv4Address string `json:"public_ipv4_address"` // Public IPv4 address
|
||||
PublicIPv6Address string `json:"public_ipv6_address"` // Public IPv6 address
|
||||
NetworkInterfaces []MachineInterfaceDetails `json:"machine_interfaces"` // Interface details
|
||||
AgentVersion string `json:"agent_version"` // installed zadmin agent version
|
||||
AntivirusInfo AntivirusInfo `json:"antivirus_info"` // Antivirus info
|
||||
UsageStatistics UsageStatistics `json:"usage_statistics"` // Usage statistics of machine
|
||||
SoftwareCatalog []Software `json:"software_catalog"` // Software installed on machine
|
||||
@ -50,23 +45,6 @@ type MachineData struct {
|
||||
OSVersion string `json:"os_version"` // OS version
|
||||
}
|
||||
|
||||
// String method for MachineData
|
||||
func (m MachineData) String() string {
|
||||
var sb strings.Builder
|
||||
sb.WriteString(fmt.Sprintf("MachineData:\n"))
|
||||
sb.WriteString(fmt.Sprintf(" FirstSeen: %s\n", m.FirstSeen))
|
||||
sb.WriteString(fmt.Sprintf(" LastSeen: %s\n", m.LastSeen))
|
||||
sb.WriteString(fmt.Sprintf(" Hostname: %s\n", m.Hostname))
|
||||
sb.WriteString(fmt.Sprintf(" PublicIPv4Address: %s\n", m.PublicIPv4Address))
|
||||
sb.WriteString(fmt.Sprintf(" PublicIPv6Address: %s\n", m.PublicIPv6Address))
|
||||
sb.WriteString(fmt.Sprintf(" AgentVersion: %s\n", m.AgentVersion))
|
||||
sb.WriteString(fmt.Sprintf(" UptimeSeconds: %d\n", m.UptimeSeconds))
|
||||
sb.WriteString(fmt.Sprintf(" OSVersion: %s\n", m.OSVersion))
|
||||
sb.WriteString(fmt.Sprintf(" LoggedOnUsers: %v\n", m.LoggedOnUsers))
|
||||
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
// Software installed on a Machine
|
||||
type Software struct {
|
||||
Name string
|
||||
@ -110,6 +88,12 @@ type MachineInterfaceDetails struct {
|
||||
Addressess []string `json:"addressess"` // Interface IP addressess
|
||||
}
|
||||
|
||||
type Agent struct {
|
||||
ID ulid.ULID `json:"id"`
|
||||
Machine Machine `json:"machine"`
|
||||
CreatedAt time.Time `json:"created_at"` // Time created in zadmin
|
||||
}
|
||||
|
||||
// Configuration to be used by the agent on a machine
|
||||
type MachineAgentConfig struct {
|
||||
RESTServerHostname string `json:"rest_server_hostname"` // Hostname used for REST requests
|
||||
|
Loading…
x
Reference in New Issue
Block a user