From 3501967c9ee02ab867a98d05914d9c06ee30a298 Mon Sep 17 00:00:00 2001 From: Nathan Coad Date: Fri, 27 Sep 2024 17:02:02 +1000 Subject: [PATCH] add ability to store/create encrypted vcenter password --- internal/secrets/secrets.go | 80 ++++ internal/settings/settings.go | 11 - internal/tasks/processEvents.go | 13 +- internal/tasks/tasks.go | 16 + internal/vcenter/vcenter.go | 28 +- main.go | 26 +- server/handler/encryptData.go | 61 +++ server/handler/handler.go | 4 + server/handler/vmModifyEvent.go | 2 +- server/handler/vmMoveEvent.go | 13 +- server/router/router.go | 9 +- server/server.go | 8 + vm.json | 736 -------------------------------- 13 files changed, 235 insertions(+), 772 deletions(-) create mode 100644 internal/secrets/secrets.go create mode 100644 internal/tasks/tasks.go create mode 100644 server/handler/encryptData.go delete mode 100644 vm.json diff --git a/internal/secrets/secrets.go b/internal/secrets/secrets.go new file mode 100644 index 0000000..3577f8a --- /dev/null +++ b/internal/secrets/secrets.go @@ -0,0 +1,80 @@ +package secrets + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "encoding/base64" + "io" + "log/slog" +) + +type Secrets struct { + Logger *slog.Logger + EncryptionKey []byte +} + +func New(logger *slog.Logger, key []byte) *Secrets { + return &Secrets{ + Logger: logger, + EncryptionKey: key, + } +} + +// Encrypt function that encrypts data using AES256-GCM and returns base64 encoded ciphertext +func (s *Secrets) Encrypt(plainText []byte) (string, error) { + block, err := aes.NewCipher(s.EncryptionKey) + if err != nil { + return "", err + } + + // Create a new GCM cipher + gcm, err := cipher.NewGCM(block) + if err != nil { + return "", err + } + + // Create a nonce + nonce := make([]byte, gcm.NonceSize()) + if _, err := io.ReadFull(rand.Reader, nonce); err != nil { + return "", err + } + + // Encrypt the plaintext using AES256-GCM + cipherText := gcm.Seal(nonce, nonce, plainText, nil) + + // Return the base64 encoded ciphertext + return base64.StdEncoding.EncodeToString(cipherText), nil +} + +// Decrypt function that decrypts base64 encoded AES256-GCM ciphertext +func (s *Secrets) Decrypt(base64CipherText string) ([]byte, error) { + // Decode the base64 ciphertext + cipherText, err := base64.StdEncoding.DecodeString(base64CipherText) + if err != nil { + return nil, err + } + + block, err := aes.NewCipher(s.EncryptionKey) + if err != nil { + return nil, err + } + + // Create a new GCM cipher + gcm, err := cipher.NewGCM(block) + if err != nil { + return nil, err + } + + // Extract the nonce from the ciphertext + nonceSize := gcm.NonceSize() + nonce, cipherText := cipherText[:nonceSize], cipherText[nonceSize:] + + // Decrypt the ciphertext + plainText, err := gcm.Open(nil, nonce, cipherText, nil) + if err != nil { + return nil, err + } + + return plainText, nil +} diff --git a/internal/settings/settings.go b/internal/settings/settings.go index 414be37..655f3e9 100644 --- a/internal/settings/settings.go +++ b/internal/settings/settings.go @@ -11,17 +11,6 @@ import ( // SettingsYML struct holds various runtime data that is too cumbersome to specify via command line, eg replacement properties type SettingsYML struct { Settings struct { - /* - Replacements []struct { - Key string `yaml:"Key"` - Value string `yaml:"Value"` - } `yaml:"replacements"` - - Omapi struct { - KeyName string `yaml:"key_name"` - KeySecret string `yaml:"key_secret"` - } `yaml:"omapi"` - */ TenantsToFilter []string `yaml:"tenants_to_filter"` NodeChargeClusters []string `yaml:"node_charge_clusters"` SrmActiveActiveVms []string `yaml:"srm_activeactive_vms"` diff --git a/internal/tasks/processEvents.go b/internal/tasks/processEvents.go index 9b43096..fa3e592 100644 --- a/internal/tasks/processEvents.go +++ b/internal/tasks/processEvents.go @@ -5,21 +5,12 @@ import ( "database/sql" "log/slog" "time" - "vctp/db" "vctp/db/queries" - "vctp/internal/settings" "vctp/internal/vcenter" "github.com/vmware/govmomi/vim25/types" ) -// Handler handles requests. -type CronTask struct { - Logger *slog.Logger - Database db.Database - Settings settings.SettingsYML -} - // use gocron to check events in the Events table func (c *CronTask) RunVmCheck(ctx context.Context, logger *slog.Logger) error { var ( @@ -42,6 +33,8 @@ func (c *CronTask) RunVmCheck(ctx context.Context, logger *slog.Logger) error { if err != nil { logger.Error("Unable to query for unprocessed events", "error", err) return nil // TODO - what to do with this error? + } else { + logger.Debug("Successfully queried for unprocessed events", "count", len(events)) } for _, evt := range events { @@ -51,7 +44,7 @@ func (c *CronTask) RunVmCheck(ctx context.Context, logger *slog.Logger) error { // to avoid doing unnecessary login/logout of vcenter c.Logger.Debug("connecting to vcenter") - vc := vcenter.New(c.Logger) + vc := vcenter.New(c.Logger, c.VcCreds) vc.Login(evt.Source) //datacenter = evt.DatacenterName.String diff --git a/internal/tasks/tasks.go b/internal/tasks/tasks.go new file mode 100644 index 0000000..39ab30c --- /dev/null +++ b/internal/tasks/tasks.go @@ -0,0 +1,16 @@ +package tasks + +import ( + "log/slog" + "vctp/db" + "vctp/internal/settings" + "vctp/internal/vcenter" +) + +// CronTask stores runtime information to be used by tasks +type CronTask struct { + Logger *slog.Logger + Database db.Database + Settings settings.SettingsYML + VcCreds *vcenter.VcenterLogin +} diff --git a/internal/vcenter/vcenter.go b/internal/vcenter/vcenter.go index db07cf4..a5f1c00 100644 --- a/internal/vcenter/vcenter.go +++ b/internal/vcenter/vcenter.go @@ -19,9 +19,15 @@ import ( ) type Vcenter struct { - Logger *slog.Logger - ctx context.Context - client *govmomi.Client + Logger *slog.Logger + ctx context.Context + client *govmomi.Client + credentials *VcenterLogin +} + +type VcenterLogin struct { + Username string + Password string } type VmProperties struct { @@ -30,23 +36,25 @@ type VmProperties struct { } // New creates a new Vcenter with the given logger -func New(logger *slog.Logger) *Vcenter { +func New(logger *slog.Logger, creds *VcenterLogin) *Vcenter { //ctx, cancel := context.WithCancel(context.Background()) //defer cancel() return &Vcenter{ - Logger: logger, - ctx: context.Background(), + Logger: logger, + ctx: context.Background(), + credentials: creds, } } func (v *Vcenter) Login(vUrl string) error { var insecure bool + // TODO - fix this insecureString := os.Getenv("VCENTER_INSECURE") - username := os.Getenv("VCENTER_USERNAME") - password := os.Getenv("VCENTER_PASSWORD") + //username := os.Getenv("VCENTER_USERNAME") + //password := os.Getenv("VCENTER_PASSWORD") // Connect to vCenter u, err := soap.ParseURL(vUrl) @@ -54,7 +62,7 @@ func (v *Vcenter) Login(vUrl string) error { log.Fatalf("Error parsing vCenter URL: %s", err) } - u.User = url.UserPassword(username, password) + u.User = url.UserPassword(v.credentials.Username, v.credentials.Password) /* c, err := govmomi.NewClient(ctx, u, insecure) @@ -77,7 +85,7 @@ func (v *Vcenter) Login(vUrl string) error { v.client = c - v.Logger.Debug("successfully connected to vCenter", "url", vUrl, "username", username) + v.Logger.Debug("successfully connected to vCenter", "url", vUrl, "username", v.credentials.Username) return nil } diff --git a/main.go b/main.go index d5b7ed8..1c844dd 100644 --- a/main.go +++ b/main.go @@ -9,9 +9,11 @@ import ( "runtime" "time" "vctp/db" + "vctp/internal/secrets" "vctp/internal/settings" "vctp/internal/tasks" utils "vctp/internal/utils" + "vctp/internal/vcenter" "vctp/log" "vctp/server" "vctp/server/router" @@ -26,6 +28,7 @@ var ( buildTime string // when the executable was built cronFrequency time.Duration cronInvFrequency time.Duration + encryptionKey = []byte("5L1l3B5KvwOCzUHMAlCgsgUTRAYMfSpa") ) func main() { @@ -112,6 +115,25 @@ func main() { utils.GenerateCerts(tlsCertFilename, tlsKeyFilename) } + // Load vcenter credentials from .env + a := secrets.New(logger, encryptionKey) + vcEp := os.Getenv("VCENTER_PASSWORD") + if len(vcEp) == 0 { + logger.Error("No vcenter password configured") + os.Exit(1) + } + vcPass, err := a.Decrypt(vcEp) + if err != nil { + logger.Error("failed to decrypt vcenter credentials", "error", err) + //os.Exit(1) + } + + creds := vcenter.VcenterLogin{ + //insecureString := os.Getenv("VCENTER_INSECURE") + Username: os.Getenv("VCENTER_USERNAME"), + Password: string(vcPass), + } + // Prepare the task scheduler c, err := gocron.NewScheduler() if err != nil { @@ -124,6 +146,7 @@ func main() { Logger: logger, Database: database, Settings: s, + VcCreds: &creds, } cronFrequencyString := os.Getenv("VCENTER_EVENT_POLLING_SECONDS") @@ -184,12 +207,13 @@ func main() { c.Start() // Start server + r := router.New(logger, database, buildTime, sha1ver, runtime.Version(), &creds, a) svr := server.New( logger, c, cancel, bindAddress, - server.WithRouter(router.New(logger, database, buildTime, sha1ver, runtime.Version())), + server.WithRouter(r), server.SetTls(bindDisableTls), server.SetCertificate(tlsCertFilename), server.SetPrivateKey(tlsKeyFilename), diff --git a/server/handler/encryptData.go b/server/handler/encryptData.go new file mode 100644 index 0000000..e9ae544 --- /dev/null +++ b/server/handler/encryptData.go @@ -0,0 +1,61 @@ +package handler + +import ( + "encoding/json" + "fmt" + "io" + "net/http" +) + +func (h *Handler) EncryptData(w http.ResponseWriter, r *http.Request) { + //ctx := context.Background() + var cipherText string + + reqBody, err := io.ReadAll(r.Body) + if err != nil { + h.Logger.Error("Invalid data received", "error", err) + fmt.Fprintf(w, "Invalid data received") + w.WriteHeader(http.StatusInternalServerError) + return + } else { + h.Logger.Debug("received input data", "length", len(reqBody)) + } + + // get the json input + var input map[string]string + if err := json.Unmarshal(reqBody, &input); err != nil { + h.Logger.Error("unable to unmarshal json", "error", err) + prettyPrint(reqBody) + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusInternalServerError) + json.NewEncoder(w).Encode(map[string]string{ + "status": "ERROR", + "message": fmt.Sprintf("Unable to unmarshal JSON in request body: '%s'", err), + }) + return + } else { + h.Logger.Debug("successfully decoded JSON") + prettyPrint(input) + } + + //cipher, err := h.Secret.Encrypt() + for k := range input { + //h.Logger.Debug("foo", "key", k, "value", input[k]) + cipherText, err = h.Secret.Encrypt([]byte(input[k])) + if err != nil { + h.Logger.Error("Unable to encrypt", "error", err) + } else { + h.Logger.Debug("Encrypted plaintext", "length", len(input[k]), "ciphertext", cipherText) + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(map[string]string{ + "status": "OK", + "message": cipherText, + }) + return + } + + } + + // return the result + +} diff --git a/server/handler/handler.go b/server/handler/handler.go index 164775d..d75cf32 100644 --- a/server/handler/handler.go +++ b/server/handler/handler.go @@ -5,6 +5,8 @@ import ( "log/slog" "net/http" "vctp/db" + "vctp/internal/secrets" + "vctp/internal/vcenter" "github.com/a-h/templ" ) @@ -16,6 +18,8 @@ type Handler struct { BuildTime string SHA1Ver string GoVersion string + VcCreds *vcenter.VcenterLogin + Secret *secrets.Secrets } func (h *Handler) html(ctx context.Context, w http.ResponseWriter, status int, t templ.Component) { diff --git a/server/handler/vmModifyEvent.go b/server/handler/vmModifyEvent.go index c40eab3..694e07b 100644 --- a/server/handler/vmModifyEvent.go +++ b/server/handler/vmModifyEvent.go @@ -244,7 +244,7 @@ func (h *Handler) calculateNewDiskSize(event models.CloudEventReceived) float64 var diskSize float64 var totalDiskBytes int64 h.Logger.Debug("connecting to vcenter") - vc := vcenter.New(h.Logger) + vc := vcenter.New(h.Logger, h.VcCreds) vc.Login(event.CloudEvent.Source) vmObject, err := vc.FindVMByIDWithDatacenter(event.CloudEvent.Data.VM.VM.Value, event.CloudEvent.Data.Datacenter.Datacenter.Value) diff --git a/server/handler/vmMoveEvent.go b/server/handler/vmMoveEvent.go index 852e75c..c3ad50c 100644 --- a/server/handler/vmMoveEvent.go +++ b/server/handler/vmMoveEvent.go @@ -94,13 +94,22 @@ func (h *Handler) VmMoveEvent(w http.ResponseWriter, r *http.Request) { result, err := h.Database.Queries().CreateUpdate(ctx, params) if err != nil { h.Logger.Error("unable to perform database insert", "error", err) + w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusInternalServerError) - fmt.Fprintf(w, "Error : %v\n", err) + json.NewEncoder(w).Encode(map[string]string{ + "status": "ERROR", + "message": fmt.Sprintf("Unable to insert move event into database: '%s'", err), + }) return + } else { h.Logger.Debug("created database record", "insert_result", result) w.WriteHeader(http.StatusOK) - fmt.Fprintf(w, "Processed update event: %v\n", result) + //fmt.Fprintf(w, "Processed update event: %v\n", result) + json.NewEncoder(w).Encode(map[string]string{ + "status": "OK", + "message": fmt.Sprintf("Successfully processed move event"), + }) return } } diff --git a/server/router/router.go b/server/router/router.go index dd97362..c9f5667 100644 --- a/server/router/router.go +++ b/server/router/router.go @@ -5,17 +5,21 @@ import ( "net/http" "vctp/db" "vctp/dist" + "vctp/internal/secrets" + "vctp/internal/vcenter" "vctp/server/handler" "vctp/server/middleware" ) -func New(logger *slog.Logger, database db.Database, buildTime string, sha1ver string, goVersion string) http.Handler { +func New(logger *slog.Logger, database db.Database, buildTime string, sha1ver string, goVersion string, creds *vcenter.VcenterLogin, secret *secrets.Secrets) http.Handler { h := &handler.Handler{ Logger: logger, Database: database, BuildTime: buildTime, SHA1Ver: sha1ver, GoVersion: goVersion, + VcCreds: creds, + Secret: secret, } mux := http.NewServeMux() @@ -35,5 +39,8 @@ func New(logger *slog.Logger, database db.Database, buildTime string, sha1ver st mux.HandleFunc("/api/report/inventory", h.InventoryReportDownload) mux.HandleFunc("/api/report/updates", h.UpdateReportDownload) + // endpoint for encrypting vcenter credential + mux.HandleFunc("/api/encrypt", h.EncryptData) + return middleware.NewLoggingMiddleware(logger, mux) } diff --git a/server/server.go b/server/server.go index e3c797c..a504e7f 100644 --- a/server/server.go +++ b/server/server.go @@ -21,6 +21,7 @@ type Server struct { disableTls bool tlsCertFilename string tlsKeyFilename string + encryptionKey string } // New creates a new server with the given logger, address and options. @@ -88,6 +89,13 @@ func WithRouter(handler http.Handler) Option { } } +// SetKey sets the encryption key we use when generating secrets +func SetKey(key string) Option { + return func(s *Server) { + s.encryptionKey = key + } +} + // SetTls sets the disable tls value func SetTls(disableTls bool) Option { return func(s *Server) { diff --git a/vm.json b/vm.json deleted file mode 100644 index 6a4c97b..0000000 --- a/vm.json +++ /dev/null @@ -1,736 +0,0 @@ -{ - "self": { - "type": "VirtualMachine", - "value": "vm-13671" - }, - "value": null, - "availableField": null, - "parent": null, - "customValue": null, - "overallStatus": "", - "configStatus": "", - "configIssue": null, - "effectiveRole": null, - "permission": null, - "name": "minecraft", - "disabledMethod": null, - "recentTask": null, - "declaredAlarmState": null, - "triggeredAlarmState": null, - "alarmActionsEnabled": null, - "tag": null, - "capability": { - "snapshotOperationsSupported": false, - "multipleSnapshotsSupported": false, - "snapshotConfigSupported": false, - "poweredOffSnapshotsSupported": false, - "memorySnapshotsSupported": false, - "revertToSnapshotSupported": false, - "quiescedSnapshotsSupported": false, - "disableSnapshotsSupported": false, - "lockSnapshotsSupported": false, - "consolePreferencesSupported": false, - "cpuFeatureMaskSupported": false, - "s1AcpiManagementSupported": false, - "settingScreenResolutionSupported": false, - "toolsAutoUpdateSupported": false, - "vmNpivWwnSupported": false, - "npivWwnOnNonRdmVmSupported": false, - "swapPlacementSupported": false, - "toolsSyncTimeSupported": false, - "virtualMmuUsageSupported": false, - "diskSharesSupported": false, - "bootOptionsSupported": false, - "settingVideoRamSizeSupported": false - }, - "config": { - "changeVersion": "2024-05-24T06:41:25.868508Z", - "modified": "1970-01-01T00:00:00Z", - "name": "minecraft", - "guestFullName": "Ubuntu Linux (32-bit)", - "version": "vmx-08", - "uuid": "422598c8-5ab7-63e7-ba34-8111936fea59", - "createDate": "1970-01-01T00:00:00Z", - "instanceUuid": "50251955-6d1b-8954-ae28-50284dd4b44e", - "npivTemporaryDisabled": true, - "locationId": "564d4d65-27af-07d1-d627-70d056c7f233", - "template": false, - "guestId": "ubuntuGuest", - "alternateGuestName": "", - "files": { - "vmPathName": "[freenas] minecraft/minecraft.vmx", - "snapshotDirectory": "[freenas] minecraft/", - "suspendDirectory": "[freenas] minecraft/", - "logDirectory": "[freenas] minecraft/" - }, - "tools": { - "toolsVersion": 10362, - "afterPowerOn": true, - "afterResume": true, - "beforeGuestStandby": true, - "beforeGuestShutdown": true, - "toolsUpgradePolicy": "upgradeAtPowerCycle", - "syncTimeWithHostAllowed": true, - "syncTimeWithHost": true, - "lastInstallInfo": { - "counter": 6 - } - }, - "flags": { - "enableLogging": true, - "useToe": false, - "runWithDebugInfo": false, - "monitorType": "release", - "htSharing": "any", - "snapshotDisabled": false, - "snapshotLocked": false, - "diskUuidEnabled": false, - "snapshotPowerOffBehavior": "powerOff", - "recordReplayEnabled": false, - "faultToleranceType": "unset", - "vvtdEnabled": false, - "vbsEnabled": false - }, - "defaultPowerOps": { - "powerOffType": "soft", - "suspendType": "hard", - "resetType": "soft", - "defaultPowerOffType": "soft", - "defaultSuspendType": "hard", - "defaultResetType": "soft", - "standbyAction": "checkpoint" - }, - "hardware": { - "numCPU": 1, - "numCoresPerSocket": 1, - "autoCoresPerSocket": false, - "memoryMB": 3072, - "virtualICH7MPresent": false, - "virtualSMCPresent": false, - "device": [ - { - "key": 100, - "deviceInfo": { - "label": "PCI controller 0", - "summary": "PCI controller 0" - }, - "busNumber": 0, - "device": [ - 500, - 12000, - 1000, - 4000 - ] - }, - { - "key": 200, - "deviceInfo": { - "label": "IDE 0", - "summary": "IDE 0" - }, - "busNumber": 0 - }, - { - "key": 201, - "deviceInfo": { - "label": "IDE 1", - "summary": "IDE 1" - }, - "busNumber": 1, - "device": [ - 3002 - ] - }, - { - "key": 300, - "deviceInfo": { - "label": "PS2 controller 0", - "summary": "PS2 controller 0" - }, - "busNumber": 0, - "device": [ - 600, - 700 - ] - }, - { - "key": 400, - "deviceInfo": { - "label": "SIO controller 0", - "summary": "SIO controller 0" - }, - "busNumber": 0, - "device": [ - 8000 - ] - }, - { - "key": 500, - "deviceInfo": { - "label": "Video card ", - "summary": "Video card" - }, - "controllerKey": 100, - "unitNumber": 0, - "videoRamSizeInKB": 4096, - "numDisplays": 1, - "useAutoDetect": false, - "enable3DSupport": false, - "use3dRenderer": "automatic", - "graphicsMemorySizeInKB": 262144 - }, - { - "key": 600, - "deviceInfo": { - "label": "Keyboard ", - "summary": "Keyboard" - }, - "controllerKey": 300, - "unitNumber": 0 - }, - { - "key": 700, - "deviceInfo": { - "label": "Pointing device", - "summary": "Pointing device; Device" - }, - "backing": { - "deviceName": "", - "useAutoDetect": false, - "hostPointingDevice": "autodetect" - }, - "controllerKey": 300, - "unitNumber": 1 - }, - { - "key": 1000, - "deviceInfo": { - "label": "SCSI controller 0", - "summary": "LSI Logic" - }, - "slotInfo": { - "pciSlotNumber": 16 - }, - "controllerKey": 100, - "unitNumber": 3, - "busNumber": 0, - "device": [ - 2000 - ], - "hotAddRemove": true, - "sharedBus": "noSharing", - "scsiCtlrUnitNumber": 7 - }, - { - "key": 2000, - "deviceInfo": { - "label": "Hard disk 1", - "summary": "62,914,560 KB" - }, - "backing": { - "fileName": "[freenas] minecraft/minecraft-000002.vmdk", - "datastore": { - "type": "Datastore", - "value": "datastore-6035" - }, - "diskMode": "persistent", - "split": false, - "writeThrough": false, - "thinProvisioned": true, - "eagerlyScrub": false, - "uuid": "6000C294-55e8-39b9-1852-00dcfd299398", - "contentId": "b739ed36bfc510b2f1c70000e628ed40", - "parent": { - "fileName": "[freenas] minecraft/minecraft-000001.vmdk", - "datastore": { - "type": "Datastore", - "value": "datastore-6035" - }, - "diskMode": "persistent", - "thinProvisioned": true, - "eagerlyScrub": false, - "uuid": "6000C294-55e8-39b9-1852-00dcfd299398", - "contentId": "45ff3b3b3935d631facb7eadbb916797", - "parent": { - "fileName": "[freenas] minecraft/minecraft.vmdk", - "datastore": { - "type": "Datastore", - "value": "datastore-6035" - }, - "diskMode": "persistent", - "thinProvisioned": true, - "eagerlyScrub": false, - "uuid": "6000C294-55e8-39b9-1852-00dcfd299398", - "contentId": "8e6ae3c31967c906303f7b3fe1b379f8", - "digestEnabled": false - }, - "deltaDiskFormat": "redoLogFormat", - "digestEnabled": false, - "deltaDiskFormatVariant": "vmfsSparseVariant" - }, - "deltaDiskFormat": "redoLogFormat", - "digestEnabled": false, - "deltaDiskFormatVariant": "vmfsSparseVariant", - "sharing": "sharingNone" - }, - "controllerKey": 1000, - "unitNumber": 0, - "capacityInKB": 62914560, - "capacityInBytes": 64424509440, - "shares": { - "shares": 1000, - "level": "normal" - }, - "storageIOAllocation": { - "limit": -1, - "shares": { - "shares": 1000, - "level": "normal" - }, - "reservation": 0 - }, - "diskObjectId": "271-2000", - "vDiskVersion": 1, - "nativeUnmanagedLinkedClone": false, - "guestReadOnly": false - }, - { - "key": 3002, - "deviceInfo": { - "label": "CD/DVD drive 1", - "summary": "ISO [] /usr/lib/vmware/isoimages/linux.iso" - }, - "backing": { - "fileName": "[] /usr/lib/vmware/isoimages/linux.iso" - }, - "connectable": { - "startConnected": false, - "allowGuestControl": true, - "connected": false, - "status": "untried" - }, - "controllerKey": 201, - "unitNumber": 0 - }, - { - "key": 4000, - "deviceInfo": { - "label": "Network adapter 1", - "summary": "DVSwitch: 50 02 bc 27 fa 1b 2c d1-0d 43 fb 29 46 60 c4 0b" - }, - "backing": { - "port": { - "switchUuid": "50 02 bc 27 fa 1b 2c d1-0d 43 fb 29 46 60 c4 0b", - "portgroupKey": "dvportgroup-4031", - "portKey": "102", - "connectionCookie": 209430599 - } - }, - "connectable": { - "migrateConnect": "unset", - "startConnected": true, - "allowGuestControl": true, - "connected": false, - "status": "untried" - }, - "slotInfo": { - "pciSlotNumber": 32 - }, - "controllerKey": 100, - "unitNumber": 7, - "addressType": "assigned", - "macAddress": "00:50:56:a5:16:29", - "wakeOnLanEnabled": true, - "resourceAllocation": { - "reservation": 0, - "share": { - "shares": 50, - "level": "normal" - }, - "limit": -1 - }, - "uptCompatibilityEnabled": false - }, - { - "key": 8000, - "deviceInfo": { - "label": "Floppy drive 1", - "summary": "Remote" - }, - "backing": { - "deviceName": "", - "useAutoDetect": false - }, - "connectable": { - "startConnected": false, - "allowGuestControl": true, - "connected": false, - "status": "untried" - }, - "controllerKey": 400, - "unitNumber": 0 - }, - { - "key": 12000, - "deviceInfo": { - "label": "VMCI device", - "summary": "Device on the virtual machine PCI bus that provides support for the virtual machine communication interface" - }, - "slotInfo": { - "pciSlotNumber": 33 - }, - "controllerKey": 100, - "unitNumber": 17, - "id": -1821382055, - "allowUnrestrictedCommunication": false, - "filterEnable": true - } - ], - "motherboardLayout": "i440bxHostBridge", - "simultaneousThreads": 1 - }, - "cpuAllocation": { - "reservation": 0, - "expandableReservation": false, - "limit": -1, - "shares": { - "shares": 1000, - "level": "normal" - } - }, - "memoryAllocation": { - "reservation": 0, - "expandableReservation": false, - "limit": -1, - "shares": { - "shares": 30720, - "level": "normal" - } - }, - "latencySensitivity": { - "level": "normal" - }, - "memoryHotAddEnabled": false, - "cpuHotAddEnabled": false, - "cpuHotRemoveEnabled": false, - "extraConfig": [ - { - "key": "svga.present", - "value": "TRUE" - }, - { - "key": "vmci.filter.enable", - "value": "TRUE" - }, - { - "key": "tools.guest.desktop.autolock", - "value": "FALSE" - }, - { - "key": "pciBridge0.present", - "value": "true" - }, - { - "key": "pciBridge4.present", - "value": "true" - }, - { - "key": "pciBridge4.virtualDev", - "value": "pcieRootPort" - }, - { - "key": "pciBridge4.functions", - "value": "8" - }, - { - "key": "pciBridge5.present", - "value": "true" - }, - { - "key": "pciBridge5.virtualDev", - "value": "pcieRootPort" - }, - { - "key": "pciBridge5.functions", - "value": "8" - }, - { - "key": "pciBridge6.present", - "value": "true" - }, - { - "key": "pciBridge6.virtualDev", - "value": "pcieRootPort" - }, - { - "key": "pciBridge6.functions", - "value": "8" - }, - { - "key": "pciBridge7.present", - "value": "true" - }, - { - "key": "pciBridge7.virtualDev", - "value": "pcieRootPort" - }, - { - "key": "pciBridge7.functions", - "value": "8" - }, - { - "key": "hpet0.present", - "value": "TRUE" - }, - { - "key": "nvram", - "value": "minecraft.nvram" - }, - { - "key": "virtualHW.productCompatibility", - "value": "hosted" - }, - { - "key": "scsi0.pciSlotNumber", - "value": "16" - }, - { - "key": "ethernet0.pciSlotNumber", - "value": "32" - }, - { - "key": "vmci0.pciSlotNumber", - "value": "33" - }, - { - "key": "snapshot.action", - "value": "keep" - }, - { - "key": "sched.cpu.latencySensitivity", - "value": "normal" - }, - { - "key": "replay.supported", - "value": "false" - }, - { - "key": "pciBridge0.pciSlotNumber", - "value": "17" - }, - { - "key": "pciBridge4.pciSlotNumber", - "value": "21" - }, - { - "key": "pciBridge5.pciSlotNumber", - "value": "22" - }, - { - "key": "pciBridge6.pciSlotNumber", - "value": "23" - }, - { - "key": "pciBridge7.pciSlotNumber", - "value": "24" - }, - { - "key": "tools.remindInstall", - "value": "FALSE" - }, - { - "key": "hostCPUID.0", - "value": "00000016756e65476c65746e49656e69" - }, - { - "key": "hostCPUID.1", - "value": "000906ea001008007ffafbffbfebfbff" - }, - { - "key": "hostCPUID.80000001", - "value": "0000000000000000000001212c100800" - }, - { - "key": "guestCPUID.0", - "value": "0000000d756e65476c65746e49656e69" - }, - { - "key": "guestCPUID.1", - "value": "000406f00001080096d832030f8bfbff" - }, - { - "key": "guestCPUID.80000001", - "value": "00000000000000000000010128100800" - }, - { - "key": "userCPUID.0", - "value": "0000000d756e65476c65746e49656e69" - }, - { - "key": "userCPUID.1", - "value": "000406f00001080096d832030f8bfbff" - }, - { - "key": "userCPUID.80000001", - "value": "00000000000000000000010128100800" - }, - { - "key": "evcCompatibilityMode", - "value": "TRUE" - }, - { - "key": "vmotion.checkpointFBSize", - "value": "4194304" - }, - { - "key": "softPowerOff", - "value": "TRUE" - }, - { - "key": "toolsInstallManager.updateCounter", - "value": "6" - }, - { - "key": "toolsInstallManager.lastInstallError", - "value": "0" - }, - { - "key": "numa.autosize.vcpu.maxPerVirtualNode", - "value": "1" - }, - { - "key": "numa.autosize.cookie", - "value": "10001" - }, - { - "key": "sched.swap.derivedName", - "value": "/vmfs/volumes/a79e4951-d31e6955/minecraft/minecraft-4bfd4f1d.vswp" - }, - { - "key": "scsi0:0.redo", - "value": "" - }, - { - "key": "monitor.phys_bits_used", - "value": "40" - }, - { - "key": "viv.moid", - "value": "91a88fc3-5936-4bfb-a6f8-018e073fcefb:vm-13671:XMmrS0IZV2SrrGL4GiADh//vraEEXaRMaC4vxsNBPOI=" - }, - { - "key": "vmxstats.filename", - "value": "minecraft.scoreboard" - }, - { - "key": "tools.capability.verifiedSamlToken", - "value": "TRUE" - }, - { - "key": "vmware.tools.internalversion", - "value": "10362" - }, - { - "key": "vmware.tools.requiredversion", - "value": "12389" - }, - { - "key": "migrate.hostLogState", - "value": "none" - }, - { - "key": "migrate.migrationId", - "value": "0" - }, - { - "key": "migrate.hostLog", - "value": "minecraft-662da845.hlog" - } - ], - "datastoreUrl": [ - { - "name": "freenas", - "url": "/vmfs/volumes/a79e4951-d31e6955" - } - ], - "swapPlacement": "inherit", - "bootOptions": { - "enterBIOSSetup": false, - "efiSecureBootEnabled": false, - "bootRetryEnabled": false, - "bootRetryDelay": 10000, - "networkBootProtocol": "ipv4" - }, - "changeTrackingEnabled": false, - "firmware": "bios", - "maxMksConnections": 40, - "guestAutoLockEnabled": false, - "memoryReservationLockedToMax": false, - "nestedHVEnabled": false, - "vPMCEnabled": false, - "scheduledHardwareUpgradeInfo": { - "upgradePolicy": "never", - "scheduledHardwareUpgradeStatus": "none" - }, - "messageBusTunnelEnabled": false, - "guestIntegrityInfo": { - "enabled": false - }, - "migrateEncryption": "opportunistic", - "sgxInfo": { - "epcSize": 0, - "flcMode": "unlocked", - "requireAttestation": false - }, - "ftEncryptionMode": "ftEncryptionOpportunistic", - "guestMonitoringModeInfo": {}, - "sevEnabled": false, - "numaInfo": { - "coresPerNumaNode": 0, - "autoCoresPerNumaNode": true - }, - "vmOpNotificationToAppEnabled": false, - "vmOpNotificationTimeout": -1, - "deviceGroups": {}, - "fixedPassthruHotPlugEnabled": false - }, - "layout": null, - "layoutEx": null, - "storage": null, - "environmentBrowser": { - "type": "", - "value": "" - }, - "resourcePool": null, - "parentVApp": null, - "resourceConfig": null, - "runtime": { - "connectionState": "", - "powerState": "", - "toolsInstallerMounted": false, - "numMksConnections": 0 - }, - "guest": null, - "summary": { - "runtime": { - "connectionState": "", - "powerState": "", - "toolsInstallerMounted": false, - "numMksConnections": 0 - }, - "config": { - "name": "", - "template": false, - "vmPathName": "" - }, - "quickStats": { - "guestHeartbeatStatus": "" - }, - "overallStatus": "" - }, - "datastore": null, - "network": null, - "snapshot": null, - "rootSnapshot": null, - "guestHeartbeatStatus": "" -} \ No newline at end of file