feat: Updated brand to be vantage
This commit is contained in:
@@ -32,20 +32,20 @@ jobs:
|
||||
mkdir -p dist
|
||||
GOOS=linux GOARCH=amd64 go build \
|
||||
-ldflags="-s -w -X main.Version=${VERSION}" \
|
||||
-o dist/keymanager-agent-linux-amd64 ./cmd
|
||||
-o dist/vantage-agent-linux-amd64 ./cmd
|
||||
GOOS=linux GOARCH=arm64 go build \
|
||||
-ldflags="-s -w -X main.Version=${VERSION}" \
|
||||
-o dist/keymanager-agent-linux-arm64 ./cmd
|
||||
-o dist/vantage-agent-linux-arm64 ./cmd
|
||||
|
||||
- name: Checksums
|
||||
working-directory: agent/dist
|
||||
run: sha256sum keymanager-agent-linux-amd64 keymanager-agent-linux-arm64 > checksums.txt
|
||||
run: sha256sum vantage-agent-linux-amd64 vantage-agent-linux-arm64 > checksums.txt
|
||||
|
||||
- name: Create release
|
||||
uses: https://gitea.com/actions/gitea-release-action@v1
|
||||
with:
|
||||
token: ${{ secrets.RELEASE_TOKEN }}
|
||||
files: |
|
||||
agent/dist/keymanager-agent-linux-amd64
|
||||
agent/dist/keymanager-agent-linux-arm64
|
||||
agent/dist/vantage-agent-linux-amd64
|
||||
agent/dist/vantage-agent-linux-arm64
|
||||
agent/dist/checksums.txt
|
||||
|
||||
@@ -23,13 +23,13 @@ jobs:
|
||||
|
||||
- name: Build and push server image
|
||||
run: |
|
||||
IMAGE="${{ vars.DOCKER_HOST }}/${{ github.repository_owner }}/keymanager/server:latest"
|
||||
IMAGE="${{ vars.DOCKER_HOST }}/${{ github.repository_owner }}/vantage/server:latest"
|
||||
docker build -t "$IMAGE" -f server/Dockerfile server/
|
||||
docker push "$IMAGE"
|
||||
|
||||
- name: Build and push web image
|
||||
run: |
|
||||
IMAGE="${{ vars.DOCKER_HOST }}/${{ github.repository_owner }}/keymanager/web:latest"
|
||||
IMAGE="${{ vars.DOCKER_HOST }}/${{ github.repository_owner }}/vantage/web:latest"
|
||||
docker build \
|
||||
--build-arg NEXT_PUBLIC_API_URL="${{ vars.API_URL }}" \
|
||||
-t "$IMAGE" \
|
||||
|
||||
+3
-3
@@ -7,8 +7,8 @@ import (
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/mrhid6/keymanager/agent/internal/config"
|
||||
agentsync "github.com/mrhid6/keymanager/agent/internal/sync"
|
||||
"github.com/mrhid6/vantage/agent/internal/config"
|
||||
agentsync "github.com/mrhid6/vantage/agent/internal/sync"
|
||||
)
|
||||
|
||||
var Version = "dev"
|
||||
@@ -32,7 +32,7 @@ func main() {
|
||||
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
|
||||
defer stop()
|
||||
|
||||
log.Printf("keymanager-agent %s starting (server=%s, poll=%s)", Version, cfg.ServerURL, cfg.PollInterval)
|
||||
log.Printf("vantage-agent %s starting (server=%s, poll=%s)", Version, cfg.ServerURL, cfg.PollInterval)
|
||||
if err := agentsync.Run(ctx, cfg, Version); err != nil {
|
||||
log.Fatalf("agent error: %v", err)
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
module github.com/mrhid6/keymanager/agent
|
||||
module github.com/mrhid6/vantage/agent
|
||||
|
||||
go 1.26
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
const ConfigPath = "/etc/keymanager/config.yaml"
|
||||
const ConfigPath = "/etc/vantage/config.yaml"
|
||||
|
||||
type Config struct {
|
||||
ServerURL string `yaml:"server_url"`
|
||||
@@ -38,7 +38,7 @@ func Save(cfg *Config) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.MkdirAll("/etc/keymanager", 0700); err != nil {
|
||||
if err := os.MkdirAll("/etc/vantage", 0700); err != nil {
|
||||
return err
|
||||
}
|
||||
return os.WriteFile(ConfigPath, data, 0600)
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/mrhid6/keymanager/agent/internal/grpc/pb"
|
||||
"github.com/mrhid6/vantage/agent/internal/grpc/pb"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
@@ -19,7 +19,7 @@ func init() {
|
||||
|
||||
type Client struct {
|
||||
conn *grpc.ClientConn
|
||||
client pb.KeyManagerClient
|
||||
client pb.VantageClient
|
||||
}
|
||||
|
||||
func New(serverURL string, useTLS bool) (*Client, error) {
|
||||
@@ -48,7 +48,7 @@ func New(serverURL string, useTLS bool) (*Client, error) {
|
||||
|
||||
return &Client{
|
||||
conn: conn,
|
||||
client: pb.NewKeyManagerClient(conn),
|
||||
client: pb.NewVantageClient(conn),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -107,6 +107,6 @@ func (c *Client) UploadGeneratedKey(serverID, agentToken, publicKey, privateKey,
|
||||
|
||||
// CommandStream opens a long-lived bidirectional stream for server-pushed commands.
|
||||
// The caller controls the stream lifetime via ctx.
|
||||
func (c *Client) CommandStream(ctx context.Context) (pb.KeyManager_CommandStreamClient, error) {
|
||||
func (c *Client) CommandStream(ctx context.Context) (pb.Vantage_CommandStreamClient, error) {
|
||||
return c.client.CommandStream(ctx)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Hand-written gRPC bindings for keymanager.proto (agent side, JSON codec).
|
||||
// Hand-written gRPC bindings for vantage.proto (agent side, JSON codec).
|
||||
|
||||
package pb
|
||||
|
||||
@@ -87,21 +87,21 @@ type CommandResult struct {
|
||||
|
||||
// CommandStream client-side interface
|
||||
|
||||
type KeyManager_CommandStreamClient interface {
|
||||
type Vantage_CommandStreamClient interface {
|
||||
Send(*AgentMessage) error
|
||||
Recv() (*ServerCommand, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type keyManagerCommandStreamClient struct {
|
||||
type vantageCommandStreamClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (c *keyManagerCommandStreamClient) Send(m *AgentMessage) error {
|
||||
func (c *vantageCommandStreamClient) Send(m *AgentMessage) error {
|
||||
return c.ClientStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (c *keyManagerCommandStreamClient) Recv() (*ServerCommand, error) {
|
||||
func (c *vantageCommandStreamClient) Recv() (*ServerCommand, error) {
|
||||
m := new(ServerCommand)
|
||||
if err := c.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
@@ -111,7 +111,7 @@ func (c *keyManagerCommandStreamClient) Recv() (*ServerCommand, error) {
|
||||
|
||||
// CommandStream server-side interface (included for completeness)
|
||||
|
||||
type KeyManager_CommandStreamServer interface {
|
||||
type Vantage_CommandStreamServer interface {
|
||||
Send(*ServerCommand) error
|
||||
Recv() (*AgentMessage, error)
|
||||
grpc.ServerStream
|
||||
@@ -133,22 +133,22 @@ func (s *keyManagerCommandStreamServer) Recv() (*AgentMessage, error) {
|
||||
return m, nil
|
||||
}
|
||||
|
||||
type KeyManagerClient interface {
|
||||
type VantageClient interface {
|
||||
Register(ctx context.Context, in *RegisterRequest, opts ...grpc.CallOption) (*RegisterResponse, error)
|
||||
SyncKeys(ctx context.Context, in *SyncRequest, opts ...grpc.CallOption) (*SyncResponse, error)
|
||||
UploadGeneratedKey(ctx context.Context, in *UploadKeyRequest, opts ...grpc.CallOption) (*UploadKeyResponse, error)
|
||||
CommandStream(ctx context.Context, opts ...grpc.CallOption) (KeyManager_CommandStreamClient, error)
|
||||
CommandStream(ctx context.Context, opts ...grpc.CallOption) (Vantage_CommandStreamClient, error)
|
||||
}
|
||||
|
||||
type UnimplementedKeyManagerServer struct{}
|
||||
type UnimplementedVantageServer struct{}
|
||||
|
||||
func (UnimplementedKeyManagerServer) Register(context.Context, *RegisterRequest) (*RegisterResponse, error) {
|
||||
func (UnimplementedVantageServer) Register(context.Context, *RegisterRequest) (*RegisterResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "not implemented")
|
||||
}
|
||||
func (UnimplementedKeyManagerServer) SyncKeys(context.Context, *SyncRequest) (*SyncResponse, error) {
|
||||
func (UnimplementedVantageServer) SyncKeys(context.Context, *SyncRequest) (*SyncResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "not implemented")
|
||||
}
|
||||
func (UnimplementedKeyManagerServer) UploadGeneratedKey(context.Context, *UploadKeyRequest) (*UploadKeyResponse, error) {
|
||||
func (UnimplementedVantageServer) UploadGeneratedKey(context.Context, *UploadKeyRequest) (*UploadKeyResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "not implemented")
|
||||
}
|
||||
|
||||
@@ -156,13 +156,13 @@ type keyManagerClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewKeyManagerClient(cc grpc.ClientConnInterface) KeyManagerClient {
|
||||
func NewVantageClient(cc grpc.ClientConnInterface) VantageClient {
|
||||
return &keyManagerClient{cc}
|
||||
}
|
||||
|
||||
func (c *keyManagerClient) Register(ctx context.Context, in *RegisterRequest, opts ...grpc.CallOption) (*RegisterResponse, error) {
|
||||
out := new(RegisterResponse)
|
||||
if err := c.cc.Invoke(ctx, "/keymanager.v1.KeyManager/Register", in, out, opts...); err != nil {
|
||||
if err := c.cc.Invoke(ctx, "/vantage.v1.Vantage/Register", in, out, opts...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
@@ -170,7 +170,7 @@ func (c *keyManagerClient) Register(ctx context.Context, in *RegisterRequest, op
|
||||
|
||||
func (c *keyManagerClient) SyncKeys(ctx context.Context, in *SyncRequest, opts ...grpc.CallOption) (*SyncResponse, error) {
|
||||
out := new(SyncResponse)
|
||||
if err := c.cc.Invoke(ctx, "/keymanager.v1.KeyManager/SyncKeys", in, out, opts...); err != nil {
|
||||
if err := c.cc.Invoke(ctx, "/vantage.v1.Vantage/SyncKeys", in, out, opts...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
@@ -178,17 +178,17 @@ func (c *keyManagerClient) SyncKeys(ctx context.Context, in *SyncRequest, opts .
|
||||
|
||||
func (c *keyManagerClient) UploadGeneratedKey(ctx context.Context, in *UploadKeyRequest, opts ...grpc.CallOption) (*UploadKeyResponse, error) {
|
||||
out := new(UploadKeyResponse)
|
||||
if err := c.cc.Invoke(ctx, "/keymanager.v1.KeyManager/UploadGeneratedKey", in, out, opts...); err != nil {
|
||||
if err := c.cc.Invoke(ctx, "/vantage.v1.Vantage/UploadGeneratedKey", in, out, opts...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *keyManagerClient) CommandStream(ctx context.Context, opts ...grpc.CallOption) (KeyManager_CommandStreamClient, error) {
|
||||
func (c *keyManagerClient) CommandStream(ctx context.Context, opts ...grpc.CallOption) (Vantage_CommandStreamClient, error) {
|
||||
desc := &grpc.StreamDesc{StreamName: "CommandStream", ServerStreams: true, ClientStreams: true}
|
||||
stream, err := c.cc.NewStream(ctx, desc, "/keymanager.v1.KeyManager/CommandStream", opts...)
|
||||
stream, err := c.cc.NewStream(ctx, desc, "/vantage.v1.Vantage/CommandStream", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &keyManagerCommandStreamClient{stream}, nil
|
||||
return &vantageCommandStreamClient{stream}, nil
|
||||
}
|
||||
@@ -12,8 +12,8 @@ import (
|
||||
|
||||
const authorizedKeysPath = "/root/.ssh/authorized_keys"
|
||||
const sshConfigPath = "/root/.ssh/config"
|
||||
const managedConfigPath = "/root/.ssh/keymanager.conf"
|
||||
const includeDirective = "Include /root/.ssh/keymanager.conf"
|
||||
const managedConfigPath = "/root/.ssh/vantage.conf"
|
||||
const includeDirective = "Include /root/.ssh/vantage.conf"
|
||||
|
||||
func ReadAuthorizedKeys() ([]string, error) {
|
||||
data, err := os.ReadFile(authorizedKeysPath)
|
||||
@@ -140,7 +140,7 @@ func GenerateKeyPair(keyPath string, opts KeyGenOptions) (string, error) {
|
||||
}
|
||||
|
||||
// AddSSHIdentity writes an IdentityFile entry for keyPath into the managed
|
||||
// keymanager.conf include file, and ensures ~/.ssh/config includes it.
|
||||
// vantage.conf include file, and ensures ~/.ssh/config includes it.
|
||||
func AddSSHIdentity(keyPath string) error {
|
||||
if err := os.MkdirAll(filepath.Dir(sshConfigPath), 0700); err != nil {
|
||||
return fmt.Errorf("mkdir .ssh: %w", err)
|
||||
@@ -204,7 +204,7 @@ func RemoveSSHIdentity(keyPath string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ensureIncludeDirective adds "Include /root/.ssh/keymanager.conf" to the top
|
||||
// ensureIncludeDirective adds "Include /root/.ssh/vantage.conf" to the top
|
||||
// of ~/.ssh/config if it is not already present. The Include must appear before
|
||||
// any Host stanzas to be effective for all connections.
|
||||
func ensureIncludeDirective() error {
|
||||
|
||||
+13
-13
@@ -15,10 +15,10 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/mrhid6/keymanager/agent/internal/config"
|
||||
grpcclient "github.com/mrhid6/keymanager/agent/internal/grpc"
|
||||
"github.com/mrhid6/keymanager/agent/internal/grpc/pb"
|
||||
"github.com/mrhid6/keymanager/agent/internal/keys"
|
||||
"github.com/mrhid6/vantage/agent/internal/config"
|
||||
grpcclient "github.com/mrhid6/vantage/agent/internal/grpc"
|
||||
"github.com/mrhid6/vantage/agent/internal/grpc/pb"
|
||||
"github.com/mrhid6/vantage/agent/internal/keys"
|
||||
)
|
||||
|
||||
func Run(ctx context.Context, cfg *config.Config, version string) error {
|
||||
@@ -178,7 +178,7 @@ func connectAndHandleStream(ctx context.Context, cfg *config.Config) error {
|
||||
|
||||
func handleDeleteKey(cmd *pb.ServerCommand) {
|
||||
label := cmd.DeleteKey.Label
|
||||
keyPath := fmt.Sprintf("/root/.ssh/keymanager_%s", strings.ReplaceAll(label, " ", "_"))
|
||||
keyPath := fmt.Sprintf("/root/.ssh/vantage_%s", strings.ReplaceAll(label, " ", "_"))
|
||||
|
||||
if err := keys.RemoveSSHIdentity(keyPath); err != nil {
|
||||
log.Printf("remove ssh identity failed (cmd=%s): %v", cmd.CommandId, err)
|
||||
@@ -196,13 +196,13 @@ func handleUpdateAgent(cmd *pb.ServerCommand) {
|
||||
u := cmd.UpdateAgent
|
||||
arch := runtime.GOARCH // "amd64" or "arm64"
|
||||
tag := "agent%2Fv" + u.Version
|
||||
binaryURL := fmt.Sprintf("%s/mrhid6/keymanager/releases/download/%s/keymanager-agent-linux-%s", u.GiteaBaseURL, tag, arch)
|
||||
checksumURL := fmt.Sprintf("%s/mrhid6/keymanager/releases/download/%s/checksums.txt", u.GiteaBaseURL, tag)
|
||||
binaryURL := fmt.Sprintf("%s/mrhid6/vantage/releases/download/%s/vantage-agent-linux-%s", u.GiteaBaseURL, tag, arch)
|
||||
checksumURL := fmt.Sprintf("%s/mrhid6/vantage/releases/download/%s/checksums.txt", u.GiteaBaseURL, tag)
|
||||
|
||||
log.Printf("updating agent to v%s from %s (cmd=%s)", u.Version, u.GiteaBaseURL, cmd.CommandId)
|
||||
|
||||
// Download binary
|
||||
tmpBin := "/tmp/keymanager-agent-update"
|
||||
tmpBin := "/tmp/vantage-agent-update"
|
||||
if err := downloadFile(binaryURL, tmpBin); err != nil {
|
||||
log.Printf("update download failed (cmd=%s): %v", cmd.CommandId, err)
|
||||
return
|
||||
@@ -214,7 +214,7 @@ func handleUpdateAgent(cmd *pb.ServerCommand) {
|
||||
log.Printf("update checksum fetch failed (cmd=%s): %v", cmd.CommandId, err)
|
||||
return
|
||||
}
|
||||
if err := verifyChecksum(tmpBin, fmt.Sprintf("keymanager-agent-linux-%s", arch), checksumData); err != nil {
|
||||
if err := verifyChecksum(tmpBin, fmt.Sprintf("vantage-agent-linux-%s", arch), checksumData); err != nil {
|
||||
log.Printf("update checksum mismatch (cmd=%s): %v", cmd.CommandId, err)
|
||||
os.Remove(tmpBin)
|
||||
return
|
||||
@@ -224,13 +224,13 @@ func handleUpdateAgent(cmd *pb.ServerCommand) {
|
||||
log.Printf("update chmod failed (cmd=%s): %v", cmd.CommandId, err)
|
||||
return
|
||||
}
|
||||
if err := os.Rename(tmpBin, "/usr/local/bin/keymanager-agent"); err != nil {
|
||||
if err := os.Rename(tmpBin, "/usr/local/bin/vantage-agent"); err != nil {
|
||||
log.Printf("update replace binary failed (cmd=%s): %v", cmd.CommandId, err)
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("agent binary replaced, restarting service (cmd=%s)", cmd.CommandId)
|
||||
exec.Command("systemctl", "restart", "keymanager-agent").Run()
|
||||
exec.Command("systemctl", "restart", "vantage-agent").Run()
|
||||
}
|
||||
|
||||
func downloadFile(url, dest string) error {
|
||||
@@ -290,7 +290,7 @@ func verifyChecksum(filePath, filename string, checksumData []byte) error {
|
||||
func handleGenerateKey(cfg *config.Config, cmd *pb.ServerCommand) {
|
||||
g := cmd.GenerateKey
|
||||
label := g.Label
|
||||
keyPath := fmt.Sprintf("/root/.ssh/keymanager_%s", strings.ReplaceAll(label, " ", "_"))
|
||||
keyPath := fmt.Sprintf("/root/.ssh/vantage_%s", strings.ReplaceAll(label, " ", "_"))
|
||||
|
||||
opts := keys.KeyGenOptions{
|
||||
KeyType: g.KeyType,
|
||||
@@ -352,7 +352,7 @@ func GenerateAndUpload(cfg *config.Config, label string) error {
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
keyPath := fmt.Sprintf("/root/.ssh/keymanager_%s", strings.ReplaceAll(label, " ", "_"))
|
||||
keyPath := fmt.Sprintf("/root/.ssh/vantage_%s", strings.ReplaceAll(label, " ", "_"))
|
||||
pubKey, err := keys.GenerateKeyPair(keyPath, keys.KeyGenOptions{Comment: label})
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# KeyManager
|
||||
# Vantage
|
||||
|
||||
A self-hosted SSH key management system. A central server (Go + Next.js + MongoDB) manages public key assignments across servers. A lightweight Go agent runs on each managed server, polls the central server via gRPC, and atomically rewrites `/root/.ssh/authorized_keys` to match the desired state.
|
||||
|
||||
@@ -34,7 +34,7 @@ A self-hosted SSH key management system. A central server (Go + Next.js + MongoD
|
||||
## Repository Structure
|
||||
|
||||
```
|
||||
keymanager/
|
||||
vantage/
|
||||
├── agent/
|
||||
│ ├── cmd/main.go
|
||||
│ └── internal/
|
||||
@@ -56,7 +56,7 @@ keymanager/
|
||||
│ ├── app/
|
||||
│ └── components/
|
||||
├── proto/
|
||||
│ └── keymanager/v1/keymanager.proto
|
||||
│ └── vantage/v1/vantage.proto
|
||||
├── deploy/
|
||||
│ ├── docker-compose.yml
|
||||
│ └── agent.service
|
||||
@@ -72,9 +72,9 @@ keymanager/
|
||||
|
||||
```protobuf
|
||||
syntax = "proto3";
|
||||
package keymanager.v1;
|
||||
package vantage.v1;
|
||||
|
||||
service KeyManager {
|
||||
service Vantage {
|
||||
rpc Register(RegisterRequest) returns (RegisterResponse);
|
||||
rpc SyncKeys(SyncRequest) returns (SyncResponse);
|
||||
rpc UploadGeneratedKey(UploadKeyRequest) returns (UploadKeyResponse);
|
||||
@@ -172,10 +172,10 @@ No streaming — polling only. Poll interval: **30 seconds**.
|
||||
|
||||
## Agent Lifecycle
|
||||
|
||||
### Config file — `/etc/keymanager/config.yaml`
|
||||
### Config file — `/etc/vantage/config.yaml`
|
||||
|
||||
```yaml
|
||||
server_url: "keymanager.yourdomain.com:9090"
|
||||
server_url: "vantage.yourdomain.com:9090"
|
||||
server_id: "<uuid>"
|
||||
pre_reg_token: "<token>" # removed after first successful Register()
|
||||
agent_token: "" # written by agent after Register()
|
||||
@@ -216,15 +216,15 @@ Config file permissions: `0600`. Config directory: `0700`.
|
||||
- Uploads public key via `UploadGeneratedKey()`
|
||||
- Private key stays local on the machine
|
||||
|
||||
### Systemd unit — `/etc/systemd/system/keymanager-agent.service`
|
||||
### Systemd unit — `/etc/systemd/system/vantage-agent.service`
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=KeyManager Agent
|
||||
Description=Vantage Agent
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/local/bin/keymanager-agent
|
||||
ExecStart=/usr/local/bin/vantage-agent
|
||||
Restart=always
|
||||
RestartSec=10
|
||||
User=root
|
||||
@@ -241,14 +241,14 @@ WantedBy=multi-user.target
|
||||
2. Backend generates a short-lived pre-registration token (TTL: 1 hour) and a `server_id`
|
||||
3. UI displays a one-liner install command with copy button:
|
||||
```bash
|
||||
curl -fsSL https://keymanager.yourdomain.com/install | \
|
||||
curl -fsSL https://vantage.yourdomain.com/install | \
|
||||
bash -s -- --server-id=<id> --token=<token>
|
||||
```
|
||||
4. Install script:
|
||||
- Detects arch (`amd64` / `arm64`)
|
||||
- Downloads agent binary from Gitea release
|
||||
- Verifies SHA-256 checksum
|
||||
- Writes `/etc/keymanager/config.yaml`
|
||||
- Writes `/etc/vantage/config.yaml`
|
||||
- Installs and starts systemd unit
|
||||
5. On first `SyncKeys` call, server marks status as `active`
|
||||
|
||||
@@ -259,7 +259,7 @@ The backend serves `/install` dynamically, injecting the latest agent version by
|
||||
## Security
|
||||
|
||||
- gRPC over TLS (Let's Encrypt or self-signed with cert pinning on the agent)
|
||||
- Agent authenticates with a per-server token stored at `/etc/keymanager/config.yaml` (`0600`)
|
||||
- Agent authenticates with a per-server token stored at `/etc/vantage/config.yaml` (`0600`)
|
||||
- Server stores `SHA-256(agent_token)` — never the plaintext token
|
||||
- Private keys generated by agents are encrypted at rest in MongoDB (AES-256)
|
||||
- `authorized_keys` written as `0600`, owned by root
|
||||
@@ -298,13 +298,13 @@ Build command:
|
||||
```bash
|
||||
GOOS=linux GOARCH=amd64 go build \
|
||||
-ldflags="-s -w -X main.Version=${VERSION}" \
|
||||
-o dist/keymanager-agent-linux-amd64 ./cmd
|
||||
-o dist/vantage-agent-linux-amd64 ./cmd
|
||||
```
|
||||
|
||||
Release assets:
|
||||
|
||||
- `keymanager-agent-linux-amd64`
|
||||
- `keymanager-agent-linux-arm64`
|
||||
- `vantage-agent-linux-amd64`
|
||||
- `vantage-agent-linux-arm64`
|
||||
- `checksums.txt`
|
||||
|
||||
### Server deploy — `.gitea/workflows/server-deploy.yml`
|
||||
@@ -312,7 +312,7 @@ Release assets:
|
||||
Triggered on pushes to `main` touching `server/**`, `web/**`, or `proto/**`. Builds and pushes Docker images to the Gitea container registry, then deploys via SSH:
|
||||
|
||||
```bash
|
||||
cd /opt/keymanager && docker compose pull && docker compose up -d --remove-orphans
|
||||
cd /opt/vantage && docker compose pull && docker compose up -d --remove-orphans
|
||||
```
|
||||
|
||||
### Tagging convention
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
[Unit]
|
||||
Description=KeyManager Agent
|
||||
Documentation=https://github.com/your-org/keymanager
|
||||
Description=Vantage Agent
|
||||
Documentation=https://github.com/your-org/vantage
|
||||
After=network.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/local/bin/keymanager-agent
|
||||
ExecStart=/usr/local/bin/vantage-agent
|
||||
Restart=always
|
||||
RestartSec=10
|
||||
User=root
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
SyslogIdentifier=keymanager-agent
|
||||
SyslogIdentifier=vantage-agent
|
||||
|
||||
# Security hardening
|
||||
NoNewPrivileges=true
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
services:
|
||||
migrate:
|
||||
image: mongo:8
|
||||
depends_on:
|
||||
mongo:
|
||||
condition: service_healthy
|
||||
volumes:
|
||||
- ./migrate/server-migrate.sh:/migrate.sh:ro
|
||||
command: bash /migrate.sh
|
||||
environment:
|
||||
MONGO_HOST: mongo
|
||||
MONGO_PORT: "27017"
|
||||
SRC_DB: keymanager
|
||||
DST_DB: vantage
|
||||
# Set DROP_SRC=true to automatically drop the keymanager database after migration
|
||||
DROP_SRC: "false"
|
||||
restart: "no"
|
||||
@@ -31,7 +31,7 @@ services:
|
||||
- "8080:8080"
|
||||
- "9090:9090"
|
||||
environment:
|
||||
MONGO_URI: mongodb://mongo:27017/keymanager
|
||||
MONGO_URI: mongodb://mongo:27017/vantage
|
||||
REDIS_ADDR: redis:6379
|
||||
GITEA_HOST: ${GITEA_HOST}
|
||||
PUBLIC_HOST: ${PUBLIC_HOST}
|
||||
|
||||
@@ -0,0 +1,219 @@
|
||||
#!/usr/bin/env bash
|
||||
# Migrates an existing keymanager-agent installation to vantage-agent.
|
||||
# Run as root on each managed server.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
|
||||
info() { echo -e "${GREEN}[migrate]${NC} $*"; }
|
||||
warn() { echo -e "${YELLOW}[migrate]${NC} $*"; }
|
||||
die() { echo -e "${RED}[migrate]${NC} $*" >&2; exit 1; }
|
||||
|
||||
[ "$(id -u)" -eq 0 ] || die "Must be run as root"
|
||||
|
||||
GITEA_HOST="${GITEA_HOST:-}"
|
||||
GITEA_OWNER="${GITEA_OWNER:-}"
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 1. Detect old installation
|
||||
# ---------------------------------------------------------------------------
|
||||
OLD_BINARY="/usr/local/bin/keymanager-agent"
|
||||
OLD_CONFIG_DIR="/etc/keymanager"
|
||||
OLD_CONFIG="$OLD_CONFIG_DIR/config.yaml"
|
||||
OLD_SERVICE="keymanager-agent"
|
||||
OLD_SERVICE_FILE="/etc/systemd/system/${OLD_SERVICE}.service"
|
||||
OLD_SSH_CONF="/root/.ssh/keymanager.conf"
|
||||
OLD_SSH_CONFIG="/root/.ssh/config"
|
||||
|
||||
NEW_BINARY="/usr/local/bin/vantage-agent"
|
||||
NEW_CONFIG_DIR="/etc/vantage"
|
||||
NEW_CONFIG="$NEW_CONFIG_DIR/config.yaml"
|
||||
NEW_SERVICE="vantage-agent"
|
||||
NEW_SERVICE_FILE="/etc/systemd/system/${NEW_SERVICE}.service"
|
||||
NEW_SSH_CONF="/root/.ssh/vantage.conf"
|
||||
|
||||
if [ ! -f "$OLD_CONFIG" ] && [ ! -f "$OLD_BINARY" ]; then
|
||||
warn "No keymanager-agent installation found — nothing to migrate."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
info "Found keymanager-agent installation. Starting migration to vantage-agent..."
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 2. Stop and disable old service
|
||||
# ---------------------------------------------------------------------------
|
||||
if systemctl is-active --quiet "$OLD_SERVICE" 2>/dev/null; then
|
||||
info "Stopping $OLD_SERVICE..."
|
||||
systemctl stop "$OLD_SERVICE"
|
||||
fi
|
||||
if systemctl is-enabled --quiet "$OLD_SERVICE" 2>/dev/null; then
|
||||
systemctl disable "$OLD_SERVICE"
|
||||
fi
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 3. Migrate config directory
|
||||
# ---------------------------------------------------------------------------
|
||||
if [ -f "$OLD_CONFIG" ] && [ ! -f "$NEW_CONFIG" ]; then
|
||||
info "Migrating config: $OLD_CONFIG -> $NEW_CONFIG"
|
||||
mkdir -p "$NEW_CONFIG_DIR"
|
||||
chmod 0700 "$NEW_CONFIG_DIR"
|
||||
cp "$OLD_CONFIG" "$NEW_CONFIG"
|
||||
chmod 0600 "$NEW_CONFIG"
|
||||
elif [ -f "$NEW_CONFIG" ]; then
|
||||
warn "$NEW_CONFIG already exists — skipping config copy."
|
||||
fi
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 4. Migrate SSH managed conf file
|
||||
# ---------------------------------------------------------------------------
|
||||
if [ -f "$OLD_SSH_CONF" ]; then
|
||||
info "Migrating SSH conf: $OLD_SSH_CONF -> $NEW_SSH_CONF"
|
||||
|
||||
# Rewrite IdentityFile paths: /root/.ssh/keymanager_* -> /root/.ssh/vantage_*
|
||||
sed 's|/root/\.ssh/keymanager_|/root/.ssh/vantage_|g' "$OLD_SSH_CONF" > "$NEW_SSH_CONF"
|
||||
chmod 0600 "$NEW_SSH_CONF"
|
||||
fi
|
||||
|
||||
# Update Include directive in /root/.ssh/config
|
||||
if [ -f "$OLD_SSH_CONFIG" ]; then
|
||||
if grep -q "Include /root/.ssh/keymanager.conf" "$OLD_SSH_CONFIG"; then
|
||||
info "Updating Include directive in $OLD_SSH_CONFIG"
|
||||
sed -i 's|Include /root/\.ssh/keymanager\.conf|Include /root/.ssh/vantage.conf|g' "$OLD_SSH_CONFIG"
|
||||
fi
|
||||
fi
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 5. Rename generated key files
|
||||
# ---------------------------------------------------------------------------
|
||||
shopt -s nullglob
|
||||
OLD_KEYS=(/root/.ssh/keymanager_*)
|
||||
if [ ${#OLD_KEYS[@]} -gt 0 ]; then
|
||||
info "Renaming ${#OLD_KEYS[@]} key file(s)..."
|
||||
for old_path in "${OLD_KEYS[@]}"; do
|
||||
filename=$(basename "$old_path")
|
||||
new_filename="${filename/keymanager_/vantage_}"
|
||||
new_path="/root/.ssh/$new_filename"
|
||||
if [ ! -e "$new_path" ]; then
|
||||
cp "$old_path" "$new_path"
|
||||
chmod "$(stat -c '%a' "$old_path")" "$new_path"
|
||||
info " $old_path -> $new_path"
|
||||
else
|
||||
warn " $new_path already exists — skipping"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
shopt -u nullglob
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 6. Download new vantage-agent binary
|
||||
# ---------------------------------------------------------------------------
|
||||
ARCH="$(uname -m)"
|
||||
case "$ARCH" in
|
||||
x86_64) ARCH="amd64" ;;
|
||||
aarch64) ARCH="arm64" ;;
|
||||
*) die "Unsupported architecture: $ARCH" ;;
|
||||
esac
|
||||
|
||||
if [ -n "$GITEA_HOST" ] && [ -n "$GITEA_OWNER" ]; then
|
||||
info "Fetching latest vantage-agent release from $GITEA_HOST..."
|
||||
|
||||
RELEASE_JSON=$(curl -fsSL "https://${GITEA_HOST}/api/v1/repos/${GITEA_OWNER}/vantage/releases?limit=1&type=tag" 2>/dev/null || echo "")
|
||||
|
||||
if [ -n "$RELEASE_JSON" ]; then
|
||||
DOWNLOAD_URL=$(echo "$RELEASE_JSON" | grep -o "\"browser_download_url\":\"[^\"]*vantage-agent-linux-${ARCH}\"" | head -1 | cut -d'"' -f4)
|
||||
CHECKSUM_URL=$(echo "$RELEASE_JSON" | grep -o "\"browser_download_url\":\"[^\"]*checksums\.txt\"" | head -1 | cut -d'"' -f4)
|
||||
|
||||
if [ -n "$DOWNLOAD_URL" ]; then
|
||||
info "Downloading $DOWNLOAD_URL..."
|
||||
TMP_BIN="/tmp/vantage-agent-new"
|
||||
curl -fsSL -o "$TMP_BIN" "$DOWNLOAD_URL"
|
||||
|
||||
if [ -n "$CHECKSUM_URL" ]; then
|
||||
TMP_SUMS="/tmp/vantage-checksums.txt"
|
||||
curl -fsSL -o "$TMP_SUMS" "$CHECKSUM_URL"
|
||||
EXPECTED=$(grep "vantage-agent-linux-${ARCH}" "$TMP_SUMS" | awk '{print $1}')
|
||||
ACTUAL=$(sha256sum "$TMP_BIN" | awk '{print $1}')
|
||||
[ "$EXPECTED" = "$ACTUAL" ] || die "Checksum mismatch! Expected $EXPECTED, got $ACTUAL"
|
||||
rm -f "$TMP_SUMS"
|
||||
info "Checksum verified."
|
||||
fi
|
||||
|
||||
chmod 0755 "$TMP_BIN"
|
||||
mv "$TMP_BIN" "$NEW_BINARY"
|
||||
info "Installed $NEW_BINARY"
|
||||
else
|
||||
warn "Could not find vantage-agent binary in release — skipping binary install."
|
||||
fi
|
||||
else
|
||||
warn "Could not reach Gitea API — skipping binary download."
|
||||
fi
|
||||
elif [ -f "$OLD_BINARY" ]; then
|
||||
warn "GITEA_HOST/GITEA_OWNER not set — skipping binary download."
|
||||
warn "You must manually install the vantage-agent binary to $NEW_BINARY before starting the service."
|
||||
fi
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 7. Install new systemd service
|
||||
# ---------------------------------------------------------------------------
|
||||
info "Installing $NEW_SERVICE_FILE..."
|
||||
cat > "$NEW_SERVICE_FILE" <<'EOF'
|
||||
[Unit]
|
||||
Description=Vantage Agent
|
||||
Documentation=https://github.com/your-org/vantage
|
||||
After=network.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/local/bin/vantage-agent
|
||||
Restart=always
|
||||
RestartSec=10
|
||||
User=root
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
SyslogIdentifier=vantage-agent
|
||||
NoNewPrivileges=true
|
||||
ProtectSystem=false
|
||||
ProtectHome=false
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
systemctl daemon-reload
|
||||
systemctl enable "$NEW_SERVICE"
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 8. Start new service (only if binary exists)
|
||||
# ---------------------------------------------------------------------------
|
||||
if [ -f "$NEW_BINARY" ]; then
|
||||
info "Starting $NEW_SERVICE..."
|
||||
systemctl start "$NEW_SERVICE"
|
||||
sleep 2
|
||||
if systemctl is-active --quiet "$NEW_SERVICE"; then
|
||||
info "vantage-agent is running."
|
||||
else
|
||||
warn "vantage-agent failed to start. Check: journalctl -u vantage-agent"
|
||||
fi
|
||||
else
|
||||
warn "Binary not yet installed — service NOT started."
|
||||
warn "Install the binary then run: systemctl start vantage-agent"
|
||||
fi
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 9. Clean up old installation
|
||||
# ---------------------------------------------------------------------------
|
||||
info "Cleaning up old keymanager-agent files..."
|
||||
rm -f "$OLD_SERVICE_FILE"
|
||||
rm -f "$OLD_BINARY"
|
||||
rm -rf "$OLD_CONFIG_DIR"
|
||||
rm -f "$OLD_SSH_CONF"
|
||||
|
||||
shopt -s nullglob
|
||||
for old_key in /root/.ssh/keymanager_*; do
|
||||
rm -f "$old_key"
|
||||
done
|
||||
shopt -u nullglob
|
||||
|
||||
systemctl daemon-reload
|
||||
info "Migration complete."
|
||||
@@ -0,0 +1,124 @@
|
||||
#!/usr/bin/env bash
|
||||
# Runs inside the migration container.
|
||||
# Copies all collections + indexes from $SRC_DB to $DST_DB,
|
||||
# verifies document counts, then optionally drops the source.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
|
||||
info() { echo -e "${GREEN}[migrate]${NC} $*"; }
|
||||
warn() { echo -e "${YELLOW}[migrate]${NC} $*"; }
|
||||
die() { echo -e "${RED}[migrate]${NC} $*" >&2; exit 1; }
|
||||
|
||||
MONGO_HOST="${MONGO_HOST:-mongo}"
|
||||
MONGO_PORT="${MONGO_PORT:-27017}"
|
||||
SRC_DB="${SRC_DB:-keymanager}"
|
||||
DST_DB="${DST_DB:-vantage}"
|
||||
DROP_SRC="${DROP_SRC:-false}"
|
||||
|
||||
MONGO_URI="mongodb://${MONGO_HOST}:${MONGO_PORT}"
|
||||
|
||||
mongosh_eval() {
|
||||
local db="$1"; local script="$2"
|
||||
mongosh --quiet "${MONGO_URI}/${db}" --eval "$script"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 1. Wait for MongoDB to be reachable
|
||||
# ---------------------------------------------------------------------------
|
||||
info "Waiting for MongoDB at ${MONGO_HOST}:${MONGO_PORT}..."
|
||||
for i in $(seq 1 30); do
|
||||
mongosh --quiet "${MONGO_URI}/admin" --eval "db.adminCommand('ping')" >/dev/null 2>&1 && break
|
||||
[ "$i" -eq 30 ] && die "MongoDB not reachable after 30 attempts."
|
||||
sleep 2
|
||||
done
|
||||
info "MongoDB is ready."
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 2. Check source database
|
||||
# ---------------------------------------------------------------------------
|
||||
SRC_COLLECTIONS=$(mongosh_eval admin "
|
||||
const names = db.getSiblingDB('${SRC_DB}').getCollectionNames();
|
||||
print(names.join(','));
|
||||
")
|
||||
|
||||
if [ -z "$SRC_COLLECTIONS" ] || [ "$SRC_COLLECTIONS" = "," ]; then
|
||||
warn "Source database '${SRC_DB}' has no collections — nothing to migrate."
|
||||
warn "If this is a fresh deployment, '${DST_DB}' will be created automatically."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
info "Collections in '${SRC_DB}': ${SRC_COLLECTIONS}"
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 3. Copy all collections via \$out
|
||||
# ---------------------------------------------------------------------------
|
||||
info "Copying collections from '${SRC_DB}' to '${DST_DB}'..."
|
||||
|
||||
mongosh_eval admin "
|
||||
const src = db.getSiblingDB('${SRC_DB}');
|
||||
const cols = src.getCollectionNames();
|
||||
cols.forEach(function(name) {
|
||||
src[name].aggregate([{ \\\$out: { db: '${DST_DB}', coll: name } }]);
|
||||
print('Copied: ' + name);
|
||||
});
|
||||
"
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 4. Recreate indexes
|
||||
# ---------------------------------------------------------------------------
|
||||
info "Recreating indexes in '${DST_DB}'..."
|
||||
|
||||
mongosh_eval admin "
|
||||
const src = db.getSiblingDB('${SRC_DB}');
|
||||
const dst = db.getSiblingDB('${DST_DB}');
|
||||
src.getCollectionNames().forEach(function(col) {
|
||||
src[col].getIndexes().forEach(function(idx) {
|
||||
if (idx.name === '_id_') return;
|
||||
const opts = { name: idx.name };
|
||||
if (idx.unique) opts.unique = true;
|
||||
if (idx.sparse) opts.sparse = true;
|
||||
if (idx.expireAfterSeconds !== undefined) opts.expireAfterSeconds = idx.expireAfterSeconds;
|
||||
try {
|
||||
dst[col].createIndex(idx.key, opts);
|
||||
print('Index: ' + col + '.' + idx.name);
|
||||
} catch(e) {
|
||||
print('Skipped index ' + idx.name + ' on ' + col + ': ' + e.message);
|
||||
}
|
||||
});
|
||||
});
|
||||
"
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 5. Verify document counts
|
||||
# ---------------------------------------------------------------------------
|
||||
info "Verifying document counts..."
|
||||
|
||||
MISMATCH=0
|
||||
IFS=',' read -ra COLS <<< "$SRC_COLLECTIONS"
|
||||
for col in "${COLS[@]}"; do
|
||||
[ -z "$col" ] && continue
|
||||
SRC_N=$(mongosh_eval "$SRC_DB" "print(db['${col}'].countDocuments())")
|
||||
DST_N=$(mongosh_eval "$DST_DB" "print(db['${col}'].countDocuments())")
|
||||
if [ "$SRC_N" = "$DST_N" ]; then
|
||||
info " ${col}: ${SRC_N} docs OK"
|
||||
else
|
||||
warn " ${col}: src=${SRC_N} dst=${DST_N} MISMATCH"
|
||||
MISMATCH=1
|
||||
fi
|
||||
done
|
||||
|
||||
[ "$MISMATCH" -eq 1 ] && die "Count mismatch — source database NOT dropped. Investigate and re-run."
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 6. Optionally drop source database
|
||||
# ---------------------------------------------------------------------------
|
||||
if [ "$DROP_SRC" = "true" ]; then
|
||||
info "Dropping source database '${SRC_DB}'..."
|
||||
mongosh_eval admin "db.getSiblingDB('${SRC_DB}').dropDatabase(); print('Dropped.');"
|
||||
info "Dropped '${SRC_DB}'."
|
||||
else
|
||||
warn "Source database '${SRC_DB}' kept. Set DROP_SRC=true to drop it automatically."
|
||||
fi
|
||||
|
||||
info "Migration complete."
|
||||
@@ -1,10 +1,10 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package keymanager.v1;
|
||||
package vantage.v1;
|
||||
|
||||
option go_package = "github.com/mrhid6/keymanager/server/internal/grpc/pb";
|
||||
option go_package = "github.com/mrhid6/vantage/server/internal/grpc/pb";
|
||||
|
||||
service KeyManager {
|
||||
service Vantage {
|
||||
rpc Register(RegisterRequest) returns (RegisterResponse);
|
||||
rpc SyncKeys(SyncRequest) returns (SyncResponse);
|
||||
rpc UploadGeneratedKey(UploadKeyRequest) returns (UploadKeyResponse);
|
||||
+3
-3
@@ -11,14 +11,14 @@ RUN go mod download
|
||||
COPY . .
|
||||
|
||||
ARG VERSION=dev
|
||||
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w -X main.Version=${VERSION}" -o /keymanager-server ./cmd
|
||||
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w -X main.Version=${VERSION}" -o /vantage-server ./cmd
|
||||
|
||||
# Runtime stage
|
||||
FROM scratch
|
||||
|
||||
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
|
||||
COPY --from=builder /keymanager-server /keymanager-server
|
||||
COPY --from=builder /vantage-server /vantage-server
|
||||
|
||||
EXPOSE 8080 9090
|
||||
|
||||
ENTRYPOINT ["/keymanager-server"]
|
||||
ENTRYPOINT ["/vantage-server"]
|
||||
|
||||
+6
-6
@@ -7,16 +7,16 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/mrhid6/keymanager/server/internal/api"
|
||||
"github.com/mrhid6/keymanager/server/internal/auth"
|
||||
"github.com/mrhid6/keymanager/server/internal/db"
|
||||
grpcserver "github.com/mrhid6/keymanager/server/internal/grpc"
|
||||
"github.com/mrhid6/keymanager/server/internal/services"
|
||||
"github.com/mrhid6/vantage/server/internal/api"
|
||||
"github.com/mrhid6/vantage/server/internal/auth"
|
||||
"github.com/mrhid6/vantage/server/internal/db"
|
||||
grpcserver "github.com/mrhid6/vantage/server/internal/grpc"
|
||||
"github.com/mrhid6/vantage/server/internal/services"
|
||||
)
|
||||
|
||||
func main() {
|
||||
mongoURI := getEnv("MONGO_URI", "mongodb://localhost:27017")
|
||||
dbName := getEnv("MONGO_DB", "keymanager")
|
||||
dbName := getEnv("MONGO_DB", "vantage")
|
||||
|
||||
if err := db.Connect(mongoURI, dbName); err != nil {
|
||||
log.Fatalf("failed to connect to MongoDB: %v", err)
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
module github.com/mrhid6/keymanager/server
|
||||
module github.com/mrhid6/vantage/server
|
||||
|
||||
go 1.26
|
||||
|
||||
|
||||
@@ -6,9 +6,9 @@ import (
|
||||
"os"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/mrhid6/keymanager/server/internal/auth"
|
||||
"github.com/mrhid6/keymanager/server/internal/models"
|
||||
"github.com/mrhid6/keymanager/server/internal/services"
|
||||
"github.com/mrhid6/vantage/server/internal/auth"
|
||||
"github.com/mrhid6/vantage/server/internal/models"
|
||||
"github.com/mrhid6/vantage/server/internal/services"
|
||||
)
|
||||
|
||||
func RegisterRoutes(r *gin.Engine) {
|
||||
@@ -81,7 +81,7 @@ func newServer(c *gin.Context) {
|
||||
}
|
||||
host := os.Getenv("PUBLIC_HOST")
|
||||
if host == "" {
|
||||
host = "https://keymanager.example.com"
|
||||
host = "https://vantage.example.com"
|
||||
}
|
||||
|
||||
installCmd := fmt.Sprintf(
|
||||
@@ -309,7 +309,7 @@ case "$ARCH" in
|
||||
esac
|
||||
|
||||
# Get latest agent release tag
|
||||
LATEST=$(curl -fsSL "https://${GITEA_HOST}/api/v1/repos/mrhid6/keymanager/releases?limit=10" \
|
||||
LATEST=$(curl -fsSL "https://${GITEA_HOST}/api/v1/repos/mrhid6/vantage/releases?limit=10" \
|
||||
| grep -o '"tag_name":"agent/v[^"]*"' | head -1 | sed 's/"tag_name":"//;s/"//')
|
||||
|
||||
if [ -z "$LATEST" ]; then
|
||||
@@ -319,27 +319,27 @@ fi
|
||||
|
||||
VERSION="${LATEST#agent/}"
|
||||
LATEST_ENCODED="${LATEST/\//%%2F}"
|
||||
BINARY_URL="https://${GITEA_HOST}/mrhid6/keymanager/releases/download/${LATEST_ENCODED}/keymanager-agent-linux-${ARCH}"
|
||||
CHECKSUM_URL="https://${GITEA_HOST}/mrhid6/keymanager/releases/download/${LATEST_ENCODED}/checksums.txt"
|
||||
BINARY_URL="https://${GITEA_HOST}/mrhid6/vantage/releases/download/${LATEST_ENCODED}/vantage-agent-linux-${ARCH}"
|
||||
CHECKSUM_URL="https://${GITEA_HOST}/mrhid6/vantage/releases/download/${LATEST_ENCODED}/checksums.txt"
|
||||
|
||||
echo "Updating keymanager-agent to ${VERSION} (${ARCH})..."
|
||||
echo "Updating vantage-agent to ${VERSION} (${ARCH})..."
|
||||
|
||||
curl -fsSL -o /tmp/keymanager-agent "${BINARY_URL}"
|
||||
curl -fsSL -o /tmp/vantage-agent "${BINARY_URL}"
|
||||
curl -fsSL -o /tmp/checksums.txt "${CHECKSUM_URL}"
|
||||
|
||||
cd /tmp
|
||||
EXPECTED=$(grep "keymanager-agent-linux-${ARCH}" checksums.txt | awk '{print $1}')
|
||||
ACTUAL=$(sha256sum keymanager-agent | awk '{print $1}')
|
||||
EXPECTED=$(grep "vantage-agent-linux-${ARCH}" checksums.txt | awk '{print $1}')
|
||||
ACTUAL=$(sha256sum vantage-agent | awk '{print $1}')
|
||||
if [ "$EXPECTED" != "$ACTUAL" ]; then
|
||||
echo "Checksum mismatch!" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
systemctl stop keymanager-agent || true
|
||||
install -m 0755 /tmp/keymanager-agent /usr/local/bin/keymanager-agent
|
||||
systemctl start keymanager-agent
|
||||
systemctl stop vantage-agent || true
|
||||
install -m 0755 /tmp/vantage-agent /usr/local/bin/vantage-agent
|
||||
systemctl start vantage-agent
|
||||
|
||||
echo "keymanager-agent updated to ${VERSION} and restarted."
|
||||
echo "vantage-agent updated to ${VERSION} and restarted."
|
||||
`, giteaHost)
|
||||
|
||||
c.Header("Content-Type", "text/x-shellscript")
|
||||
@@ -356,7 +356,7 @@ func handleInstallScript(c *gin.Context) {
|
||||
}
|
||||
publicHost := os.Getenv("PUBLIC_HOST")
|
||||
if publicHost == "" {
|
||||
publicHost = "keymanager.example.com"
|
||||
publicHost = "vantage.example.com"
|
||||
}
|
||||
grpcHost := os.Getenv("GRPC_HOST")
|
||||
if grpcHost == "" {
|
||||
@@ -384,7 +384,7 @@ case "$ARCH" in
|
||||
esac
|
||||
|
||||
# Get latest agent release tag
|
||||
LATEST=$(curl -fsSL "https://${GITEA_HOST}/api/v1/repos/mrhid6/keymanager/releases?limit=10" \
|
||||
LATEST=$(curl -fsSL "https://${GITEA_HOST}/api/v1/repos/mrhid6/vantage/releases?limit=10" \
|
||||
| grep -o '"tag_name":"agent/v[^"]*"' | head -1 | sed 's/"tag_name":"//;s/"//')
|
||||
|
||||
if [ -z "$LATEST" ]; then
|
||||
@@ -394,28 +394,28 @@ fi
|
||||
|
||||
VERSION="${LATEST#agent/}"
|
||||
LATEST_ENCODED="${LATEST/\//%%2F}"
|
||||
BINARY_URL="https://${GITEA_HOST}/mrhid6/keymanager/releases/download/${LATEST_ENCODED}/keymanager-agent-linux-${ARCH}"
|
||||
CHECKSUM_URL="https://${GITEA_HOST}/mrhid6/keymanager/releases/download/${LATEST_ENCODED}/checksums.txt"
|
||||
BINARY_URL="https://${GITEA_HOST}/mrhid6/vantage/releases/download/${LATEST_ENCODED}/vantage-agent-linux-${ARCH}"
|
||||
CHECKSUM_URL="https://${GITEA_HOST}/mrhid6/vantage/releases/download/${LATEST_ENCODED}/checksums.txt"
|
||||
|
||||
echo "Installing keymanager-agent ${VERSION} (${ARCH})..."
|
||||
echo "Installing vantage-agent ${VERSION} (${ARCH})..."
|
||||
|
||||
curl -fsSL -o /tmp/keymanager-agent "${BINARY_URL}"
|
||||
curl -fsSL -o /tmp/vantage-agent "${BINARY_URL}"
|
||||
curl -fsSL -o /tmp/checksums.txt "${CHECKSUM_URL}"
|
||||
|
||||
cd /tmp
|
||||
EXPECTED=$(grep "keymanager-agent-linux-${ARCH}" checksums.txt | awk '{print $1}')
|
||||
ACTUAL=$(sha256sum keymanager-agent | awk '{print $1}')
|
||||
EXPECTED=$(grep "vantage-agent-linux-${ARCH}" checksums.txt | awk '{print $1}')
|
||||
ACTUAL=$(sha256sum vantage-agent | awk '{print $1}')
|
||||
if [ "$EXPECTED" != "$ACTUAL" ]; then
|
||||
echo "Checksum mismatch!" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
install -m 0755 /tmp/keymanager-agent /usr/local/bin/keymanager-agent
|
||||
install -m 0755 /tmp/vantage-agent /usr/local/bin/vantage-agent
|
||||
|
||||
mkdir -p /etc/keymanager
|
||||
chmod 0700 /etc/keymanager
|
||||
mkdir -p /etc/vantage
|
||||
chmod 0700 /etc/vantage
|
||||
|
||||
cat > /etc/keymanager/config.yaml <<EOF
|
||||
cat > /etc/vantage/config.yaml <<EOF
|
||||
server_url: "${GRPC_HOST}"
|
||||
server_id: "${SERVER_ID}"
|
||||
pre_reg_token: "${TOKEN}"
|
||||
@@ -423,15 +423,15 @@ agent_token: ""
|
||||
poll_interval: 30s
|
||||
tls: true
|
||||
EOF
|
||||
chmod 0600 /etc/keymanager/config.yaml
|
||||
chmod 0600 /etc/vantage/config.yaml
|
||||
|
||||
cat > /etc/systemd/system/keymanager-agent.service <<EOF
|
||||
cat > /etc/systemd/system/vantage-agent.service <<EOF
|
||||
[Unit]
|
||||
Description=KeyManager Agent
|
||||
Description=Vantage Agent
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/local/bin/keymanager-agent
|
||||
ExecStart=/usr/local/bin/vantage-agent
|
||||
Restart=always
|
||||
RestartSec=10
|
||||
User=root
|
||||
@@ -441,9 +441,9 @@ WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
systemctl daemon-reload
|
||||
systemctl enable --now keymanager-agent
|
||||
systemctl enable --now vantage-agent
|
||||
|
||||
echo "keymanager-agent installed and started."
|
||||
echo "vantage-agent installed and started."
|
||||
`, serverID, token, giteaHost, publicHost, grpcHost)
|
||||
|
||||
c.Header("Content-Type", "text/x-shellscript")
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Hand-written gRPC bindings for keymanager.proto using JSON codec.
|
||||
// Hand-written gRPC bindings for vantage.proto using JSON codec.
|
||||
// To use: register the JSON codec before creating gRPC servers/clients.
|
||||
|
||||
package pb
|
||||
@@ -90,7 +90,7 @@ type CommandResult struct {
|
||||
|
||||
// CommandStream server-side interface
|
||||
|
||||
type KeyManager_CommandStreamServer interface {
|
||||
type Vantage_CommandStreamServer interface {
|
||||
Send(*ServerCommand) error
|
||||
Recv() (*AgentMessage, error)
|
||||
grpc.ServerStream
|
||||
@@ -114,21 +114,21 @@ func (s *keyManagerCommandStreamServer) Recv() (*AgentMessage, error) {
|
||||
|
||||
// CommandStream client-side interface
|
||||
|
||||
type KeyManager_CommandStreamClient interface {
|
||||
type Vantage_CommandStreamClient interface {
|
||||
Send(*AgentMessage) error
|
||||
Recv() (*ServerCommand, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type keyManagerCommandStreamClient struct {
|
||||
type vantageCommandStreamClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (c *keyManagerCommandStreamClient) Send(m *AgentMessage) error {
|
||||
func (c *vantageCommandStreamClient) Send(m *AgentMessage) error {
|
||||
return c.ClientStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (c *keyManagerCommandStreamClient) Recv() (*ServerCommand, error) {
|
||||
func (c *vantageCommandStreamClient) Recv() (*ServerCommand, error) {
|
||||
m := new(ServerCommand)
|
||||
if err := c.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
@@ -138,51 +138,51 @@ func (c *keyManagerCommandStreamClient) Recv() (*ServerCommand, error) {
|
||||
|
||||
// Server interface
|
||||
|
||||
type KeyManagerServer interface {
|
||||
type VantageServer interface {
|
||||
Register(context.Context, *RegisterRequest) (*RegisterResponse, error)
|
||||
SyncKeys(context.Context, *SyncRequest) (*SyncResponse, error)
|
||||
UploadGeneratedKey(context.Context, *UploadKeyRequest) (*UploadKeyResponse, error)
|
||||
CommandStream(KeyManager_CommandStreamServer) error
|
||||
CommandStream(Vantage_CommandStreamServer) error
|
||||
}
|
||||
|
||||
type UnimplementedKeyManagerServer struct{}
|
||||
type UnimplementedVantageServer struct{}
|
||||
|
||||
func (UnimplementedKeyManagerServer) Register(context.Context, *RegisterRequest) (*RegisterResponse, error) {
|
||||
func (UnimplementedVantageServer) Register(context.Context, *RegisterRequest) (*RegisterResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Register not implemented")
|
||||
}
|
||||
|
||||
func (UnimplementedKeyManagerServer) SyncKeys(context.Context, *SyncRequest) (*SyncResponse, error) {
|
||||
func (UnimplementedVantageServer) SyncKeys(context.Context, *SyncRequest) (*SyncResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SyncKeys not implemented")
|
||||
}
|
||||
|
||||
func (UnimplementedKeyManagerServer) UploadGeneratedKey(context.Context, *UploadKeyRequest) (*UploadKeyResponse, error) {
|
||||
func (UnimplementedVantageServer) UploadGeneratedKey(context.Context, *UploadKeyRequest) (*UploadKeyResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UploadGeneratedKey not implemented")
|
||||
}
|
||||
|
||||
func (UnimplementedKeyManagerServer) CommandStream(KeyManager_CommandStreamServer) error {
|
||||
func (UnimplementedVantageServer) CommandStream(Vantage_CommandStreamServer) error {
|
||||
return status.Errorf(codes.Unimplemented, "method CommandStream not implemented")
|
||||
}
|
||||
|
||||
// Client interface
|
||||
|
||||
type KeyManagerClient interface {
|
||||
type VantageClient interface {
|
||||
Register(ctx context.Context, in *RegisterRequest, opts ...grpc.CallOption) (*RegisterResponse, error)
|
||||
SyncKeys(ctx context.Context, in *SyncRequest, opts ...grpc.CallOption) (*SyncResponse, error)
|
||||
UploadGeneratedKey(ctx context.Context, in *UploadKeyRequest, opts ...grpc.CallOption) (*UploadKeyResponse, error)
|
||||
CommandStream(ctx context.Context, opts ...grpc.CallOption) (KeyManager_CommandStreamClient, error)
|
||||
CommandStream(ctx context.Context, opts ...grpc.CallOption) (Vantage_CommandStreamClient, error)
|
||||
}
|
||||
|
||||
type keyManagerClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewKeyManagerClient(cc grpc.ClientConnInterface) KeyManagerClient {
|
||||
func NewVantageClient(cc grpc.ClientConnInterface) VantageClient {
|
||||
return &keyManagerClient{cc}
|
||||
}
|
||||
|
||||
func (c *keyManagerClient) Register(ctx context.Context, in *RegisterRequest, opts ...grpc.CallOption) (*RegisterResponse, error) {
|
||||
out := new(RegisterResponse)
|
||||
if err := c.cc.Invoke(ctx, "/keymanager.v1.KeyManager/Register", in, out, opts...); err != nil {
|
||||
if err := c.cc.Invoke(ctx, "/vantage.v1.Vantage/Register", in, out, opts...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
@@ -190,7 +190,7 @@ func (c *keyManagerClient) Register(ctx context.Context, in *RegisterRequest, op
|
||||
|
||||
func (c *keyManagerClient) SyncKeys(ctx context.Context, in *SyncRequest, opts ...grpc.CallOption) (*SyncResponse, error) {
|
||||
out := new(SyncResponse)
|
||||
if err := c.cc.Invoke(ctx, "/keymanager.v1.KeyManager/SyncKeys", in, out, opts...); err != nil {
|
||||
if err := c.cc.Invoke(ctx, "/vantage.v1.Vantage/SyncKeys", in, out, opts...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
@@ -198,90 +198,90 @@ func (c *keyManagerClient) SyncKeys(ctx context.Context, in *SyncRequest, opts .
|
||||
|
||||
func (c *keyManagerClient) UploadGeneratedKey(ctx context.Context, in *UploadKeyRequest, opts ...grpc.CallOption) (*UploadKeyResponse, error) {
|
||||
out := new(UploadKeyResponse)
|
||||
if err := c.cc.Invoke(ctx, "/keymanager.v1.KeyManager/UploadGeneratedKey", in, out, opts...); err != nil {
|
||||
if err := c.cc.Invoke(ctx, "/vantage.v1.Vantage/UploadGeneratedKey", in, out, opts...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *keyManagerClient) CommandStream(ctx context.Context, opts ...grpc.CallOption) (KeyManager_CommandStreamClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &KeyManager_ServiceDesc.Streams[0], "/keymanager.v1.KeyManager/CommandStream", opts...)
|
||||
func (c *keyManagerClient) CommandStream(ctx context.Context, opts ...grpc.CallOption) (Vantage_CommandStreamClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &Vantage_ServiceDesc.Streams[0], "/vantage.v1.Vantage/CommandStream", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &keyManagerCommandStreamClient{stream}, nil
|
||||
return &vantageCommandStreamClient{stream}, nil
|
||||
}
|
||||
|
||||
// Server registration
|
||||
|
||||
func RegisterKeyManagerServer(s grpc.ServiceRegistrar, srv KeyManagerServer) {
|
||||
s.RegisterService(&KeyManager_ServiceDesc, srv)
|
||||
func RegisterVantageServer(s grpc.ServiceRegistrar, srv VantageServer) {
|
||||
s.RegisterService(&Vantage_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
var KeyManager_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "keymanager.v1.KeyManager",
|
||||
HandlerType: (*KeyManagerServer)(nil),
|
||||
var Vantage_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "vantage.v1.Vantage",
|
||||
HandlerType: (*VantageServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{MethodName: "Register", Handler: _KeyManager_Register_Handler},
|
||||
{MethodName: "SyncKeys", Handler: _KeyManager_SyncKeys_Handler},
|
||||
{MethodName: "UploadGeneratedKey", Handler: _KeyManager_UploadGeneratedKey_Handler},
|
||||
{MethodName: "Register", Handler: _Vantage_Register_Handler},
|
||||
{MethodName: "SyncKeys", Handler: _Vantage_SyncKeys_Handler},
|
||||
{MethodName: "UploadGeneratedKey", Handler: _Vantage_UploadGeneratedKey_Handler},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
StreamName: "CommandStream",
|
||||
Handler: _KeyManager_CommandStream_Handler,
|
||||
Handler: _Vantage_CommandStream_Handler,
|
||||
ServerStreams: true,
|
||||
ClientStreams: true,
|
||||
},
|
||||
},
|
||||
Metadata: "keymanager/v1/keymanager.proto",
|
||||
Metadata: "vantage/v1/vantage.proto",
|
||||
}
|
||||
|
||||
func _KeyManager_Register_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
func _Vantage_Register_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(RegisterRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(KeyManagerServer).Register(ctx, in)
|
||||
return srv.(VantageServer).Register(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{Server: srv, FullMethod: "/keymanager.v1.KeyManager/Register"}
|
||||
info := &grpc.UnaryServerInfo{Server: srv, FullMethod: "/vantage.v1.Vantage/Register"}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(KeyManagerServer).Register(ctx, req.(*RegisterRequest))
|
||||
return srv.(VantageServer).Register(ctx, req.(*RegisterRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _KeyManager_SyncKeys_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
func _Vantage_SyncKeys_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(SyncRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(KeyManagerServer).SyncKeys(ctx, in)
|
||||
return srv.(VantageServer).SyncKeys(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{Server: srv, FullMethod: "/keymanager.v1.KeyManager/SyncKeys"}
|
||||
info := &grpc.UnaryServerInfo{Server: srv, FullMethod: "/vantage.v1.Vantage/SyncKeys"}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(KeyManagerServer).SyncKeys(ctx, req.(*SyncRequest))
|
||||
return srv.(VantageServer).SyncKeys(ctx, req.(*SyncRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _KeyManager_UploadGeneratedKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
func _Vantage_UploadGeneratedKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(UploadKeyRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(KeyManagerServer).UploadGeneratedKey(ctx, in)
|
||||
return srv.(VantageServer).UploadGeneratedKey(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{Server: srv, FullMethod: "/keymanager.v1.KeyManager/UploadGeneratedKey"}
|
||||
info := &grpc.UnaryServerInfo{Server: srv, FullMethod: "/vantage.v1.Vantage/UploadGeneratedKey"}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(KeyManagerServer).UploadGeneratedKey(ctx, req.(*UploadKeyRequest))
|
||||
return srv.(VantageServer).UploadGeneratedKey(ctx, req.(*UploadKeyRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _KeyManager_CommandStream_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
return srv.(KeyManagerServer).CommandStream(&keyManagerCommandStreamServer{stream})
|
||||
func _Vantage_CommandStream_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
return srv.(VantageServer).CommandStream(&keyManagerCommandStreamServer{stream})
|
||||
}
|
||||
@@ -6,8 +6,8 @@ import (
|
||||
"log"
|
||||
"net"
|
||||
|
||||
"github.com/mrhid6/keymanager/server/internal/grpc/pb"
|
||||
"github.com/mrhid6/keymanager/server/internal/services"
|
||||
"github.com/mrhid6/vantage/server/internal/grpc/pb"
|
||||
"github.com/mrhid6/vantage/server/internal/services"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/encoding"
|
||||
@@ -18,11 +18,11 @@ func init() {
|
||||
encoding.RegisterCodec(JSONCodec{})
|
||||
}
|
||||
|
||||
type keyManagerServer struct {
|
||||
pb.UnimplementedKeyManagerServer
|
||||
type vantageServer struct {
|
||||
pb.UnimplementedVantageServer
|
||||
}
|
||||
|
||||
func (s *keyManagerServer) Register(ctx context.Context, req *pb.RegisterRequest) (*pb.RegisterResponse, error) {
|
||||
func (s *vantageServer) Register(ctx context.Context, req *pb.RegisterRequest) (*pb.RegisterResponse, error) {
|
||||
agentToken, err := services.RegisterServer(req.ServerId, req.PreRegToken, req.Hostname, req.IpAddress, req.OsInfo)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "registration failed: %v", err)
|
||||
@@ -30,7 +30,7 @@ func (s *keyManagerServer) Register(ctx context.Context, req *pb.RegisterRequest
|
||||
return &pb.RegisterResponse{AgentToken: agentToken}, nil
|
||||
}
|
||||
|
||||
func (s *keyManagerServer) SyncKeys(ctx context.Context, req *pb.SyncRequest) (*pb.SyncResponse, error) {
|
||||
func (s *vantageServer) SyncKeys(ctx context.Context, req *pb.SyncRequest) (*pb.SyncResponse, error) {
|
||||
srv, err := services.ValidateAgentToken(req.ServerId, req.AgentToken)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Unauthenticated, "invalid agent token")
|
||||
@@ -48,7 +48,7 @@ func (s *keyManagerServer) SyncKeys(ctx context.Context, req *pb.SyncRequest) (*
|
||||
return &pb.SyncResponse{PublicKeys: keys}, nil
|
||||
}
|
||||
|
||||
func (s *keyManagerServer) UploadGeneratedKey(ctx context.Context, req *pb.UploadKeyRequest) (*pb.UploadKeyResponse, error) {
|
||||
func (s *vantageServer) UploadGeneratedKey(ctx context.Context, req *pb.UploadKeyRequest) (*pb.UploadKeyResponse, error) {
|
||||
srv, err := services.ValidateAgentToken(req.ServerId, req.AgentToken)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Unauthenticated, "invalid agent token")
|
||||
@@ -67,7 +67,7 @@ func (s *keyManagerServer) UploadGeneratedKey(ctx context.Context, req *pb.Uploa
|
||||
return &pb.UploadKeyResponse{KeyId: key.KeyID}, nil
|
||||
}
|
||||
|
||||
func (s *keyManagerServer) CommandStream(stream pb.KeyManager_CommandStreamServer) error {
|
||||
func (s *vantageServer) CommandStream(stream pb.Vantage_CommandStreamServer) error {
|
||||
// First message authenticates the agent and signals readiness.
|
||||
msg, err := stream.Recv()
|
||||
if err != nil {
|
||||
@@ -127,7 +127,7 @@ func StartGRPC(port int) error {
|
||||
}
|
||||
|
||||
s := grpc.NewServer()
|
||||
pb.RegisterKeyManagerServer(s, &keyManagerServer{})
|
||||
pb.RegisterVantageServer(s, &vantageServer{})
|
||||
|
||||
log.Printf("gRPC server listening on :%d", port)
|
||||
return s.Serve(lis)
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/mrhid6/keymanager/server/internal/grpc/pb"
|
||||
"github.com/mrhid6/vantage/server/internal/grpc/pb"
|
||||
)
|
||||
|
||||
type commandDispatcher struct {
|
||||
@@ -78,7 +78,7 @@ func GetLatestAgentVersion() (string, error) {
|
||||
if giteaHost == "" {
|
||||
giteaHost = "gitea.example.com"
|
||||
}
|
||||
url := fmt.Sprintf("https://%s/api/v1/repos/mrhid6/keymanager/releases?limit=20", giteaHost)
|
||||
url := fmt.Sprintf("https://%s/api/v1/repos/mrhid6/vantage/releases?limit=20", giteaHost)
|
||||
resp, err := http.Get(url) //nolint:gosec
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("fetch releases: %w", err)
|
||||
|
||||
@@ -9,8 +9,8 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/mrhid6/keymanager/server/internal/db"
|
||||
"github.com/mrhid6/keymanager/server/internal/models"
|
||||
"github.com/mrhid6/vantage/server/internal/db"
|
||||
"github.com/mrhid6/vantage/server/internal/models"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
)
|
||||
|
||||
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/mrhid6/keymanager/server/internal/db"
|
||||
"github.com/mrhid6/keymanager/server/internal/models"
|
||||
"github.com/mrhid6/vantage/server/internal/db"
|
||||
"github.com/mrhid6/vantage/server/internal/models"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
"go.mongodb.org/mongo-driver/v2/mongo/options"
|
||||
)
|
||||
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/mrhid6/keymanager/server/internal/db"
|
||||
"github.com/mrhid6/keymanager/server/internal/models"
|
||||
"github.com/mrhid6/vantage/server/internal/db"
|
||||
"github.com/mrhid6/vantage/server/internal/models"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
)
|
||||
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ import { AuthProvider } from "@/components/AuthProvider";
|
||||
import { Sidebar } from "@/components/Sidebar";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "KeyManager",
|
||||
title: "Vantage",
|
||||
description: "Self-hosted SSH key management",
|
||||
};
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ function GenerateKeyModal({
|
||||
<form onSubmit={handleSubmit} className="space-y-4">
|
||||
<div>
|
||||
<label className="mb-1.5 block text-sm font-medium text-text-secondary">
|
||||
Label <span className="text-text-tertiary">(used as the key name in KeyManager)</span>
|
||||
Label <span className="text-text-tertiary">(used as the key name in Vantage)</span>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
|
||||
@@ -26,7 +26,7 @@ export default function NewServerPage() {
|
||||
<div className="mb-6">
|
||||
<h1 className="text-2xl font-bold text-text-primary">Add Server</h1>
|
||||
<p className="mt-1 text-sm text-text-secondary">
|
||||
Generate an install command to register a new server with the KeyManager agent.
|
||||
Generate an install command to register a new server with the Vantage agent.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -39,7 +39,7 @@ export default function NewServerPage() {
|
||||
<p className="mb-6 text-sm text-text-secondary leading-relaxed">
|
||||
Click the button below to generate a one-time install command. The command
|
||||
contains a short-lived token (valid for 1 hour) that registers your server
|
||||
and installs the KeyManager agent automatically.
|
||||
and installs the Vantage agent automatically.
|
||||
</p>
|
||||
|
||||
{error && (
|
||||
@@ -111,8 +111,8 @@ export default function NewServerPage() {
|
||||
{[
|
||||
"The install script detects your CPU architecture (amd64 / arm64)",
|
||||
"Downloads and verifies the latest agent binary from the Gitea release",
|
||||
"Writes /etc/keymanager/config.yaml with the server ID and token",
|
||||
"Installs and starts the keymanager-agent systemd service",
|
||||
"Writes /etc/vantage/config.yaml with the server ID and token",
|
||||
"Installs and starts the vantage-agent systemd service",
|
||||
"The agent calls Register() to obtain a persistent auth token",
|
||||
"The server status changes to active on the first successful sync",
|
||||
].map((step, i) => (
|
||||
|
||||
@@ -44,7 +44,7 @@ export function Sidebar() {
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M15.75 5.25a3 3 0 013 3m3 0a6 6 0 01-7.029 5.912c-.563-.097-1.159.026-1.563.43L10.5 17.25H8.25v2.25H6v2.25H2.25v-2.818c0-.597.237-1.17.659-1.591l6.499-6.499c.404-.404.527-1 .43-1.563A6 6 0 1121.75 8.25z" />
|
||||
</svg>
|
||||
</div>
|
||||
<span className="text-base font-semibold text-text-primary">KeyManager</span>
|
||||
<span className="text-base font-semibold text-text-primary">Vantage</span>
|
||||
</div>
|
||||
|
||||
<nav className="flex-1 overflow-y-auto px-3 py-4">
|
||||
@@ -80,7 +80,7 @@ export function Sidebar() {
|
||||
</div>
|
||||
)}
|
||||
<div className="flex items-center justify-between">
|
||||
<p className="text-xs text-text-secondary">KeyManager v1.0</p>
|
||||
<p className="text-xs text-text-secondary">Vantage v1.0</p>
|
||||
{authEnabled && user && (
|
||||
<a
|
||||
href="/auth/logout"
|
||||
|
||||
Generated
+2
-2
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "keymanager-web",
|
||||
"name": "vantage-web",
|
||||
"version": "0.1.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "keymanager-web",
|
||||
"name": "vantage-web",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"@tanstack/react-query": "^5.51.1",
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "keymanager-web",
|
||||
"name": "vantage-web",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
||||
Reference in New Issue
Block a user