-
Notifications
You must be signed in to change notification settings - Fork 3
proxmox test #715
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
proxmox test #715
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR adds Proxmox Virtual Environment support to onctl, enabling users to manage VMs on Proxmox infrastructure using the same interface as other cloud providers.
- Implements complete Proxmox provider with VM lifecycle management (create, list, destroy, SSH)
- Adds configuration template and comprehensive documentation for Proxmox setup
- Integrates Proxmox as a supported cloud provider in the main application
Reviewed Changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| internal/providerpxmx/common.go | Proxmox client initialization with API authentication |
| internal/cloud/proxmox.go | Main provider implementation with CloudProviderInterface methods |
| internal/files/init/proxmox.yaml | Default configuration template for Proxmox VMs |
| docs/PROXMOX.md | User documentation with setup instructions and examples |
| cmd/root.go | Integration of Proxmox provider into main application |
| PROXMOX_IMPLEMENTATION.md | Technical implementation summary and documentation |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| tlsConfig := &tls.Config{ | ||
| InsecureSkipVerify: true, // For self-signed certificates | ||
| } |
Copilot
AI
Oct 7, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The TLS configuration unconditionally disables certificate verification. Consider making this configurable via an environment variable like PROXMOX_INSECURE_TLS to allow secure connections in production environments.
| return "", err | ||
| } | ||
|
|
||
| SSHKeyMD5 := fmt.Sprintf("%x", md5.Sum(publicKey)) |
Copilot
AI
Oct 7, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MD5 is cryptographically insecure. Consider using SHA-256 for key hashing instead of MD5.
| // Wait for VM to start | ||
| time.Sleep(5 * time.Second) |
Copilot
AI
Oct 7, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hard-coded sleep duration should be configurable or use proper polling with timeout. Consider implementing a wait mechanism that checks VM status periodically with a maximum timeout.
| // Wait for VM to start | |
| time.Sleep(5 * time.Second) | |
| // Wait for VM to start by polling status with timeout | |
| const maxWait = 60 * time.Second | |
| const pollInterval = 2 * time.Second | |
| startTime := time.Now() | |
| for { | |
| status, err := p.Client.GetVmState(ctx, newVmRef) | |
| if err != nil { | |
| return Vm{}, fmt.Errorf("failed to get VM state: %v", err) | |
| } | |
| if status.Status == "running" { | |
| break | |
| } | |
| if time.Since(startTime) > maxWait { | |
| return Vm{}, fmt.Errorf("timeout waiting for VM to start") | |
| } | |
| time.Sleep(pollInterval) | |
| } |
| } | ||
|
|
||
| // Wait for VM to stop | ||
| time.Sleep(3 * time.Second) |
Copilot
AI
Oct 7, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another hard-coded sleep duration. Consider using a configurable timeout or polling mechanism to check if the VM has actually stopped before proceeding with deletion.
| return fmt.Errorf("invalid VM ID: %v", err) | ||
| } | ||
|
|
||
| vmRef := pxapi.NewVmRef(pxapi.GuestID(vmID)) |
Check failure
Code scanning / CodeQL
Incorrect conversion between integer types High
strconv.Atoi
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 4 months ago
To fix this issue, ensure that server.ID is a valid non-negative integer within the bounds of uint32 before converting it. Specifically, after parsing the string to an integer, you should explicitly check that the vmID value is between 0 and math.MaxUint32 (inclusive). If the bounds check fails, return an appropriate error instead of performing the conversion. This change should be implemented just after parsing the ID and before passing it to pxapi.GuestID. You will need to import the math package to access math.MaxUint32 if it is not already imported in the snippet.
-
Copy modified line R12 -
Copy modified lines R147-R149 -
Copy modified line R151
| @@ -9,6 +9,7 @@ | ||
| "os" | ||
| "strconv" | ||
| "time" | ||
| "math" | ||
|
|
||
| pxapi "github.com/Telmate/proxmox-api-go/proxmox" | ||
| "github.com/cdalar/onctl/internal/tools" | ||
| @@ -143,8 +144,11 @@ | ||
| if err != nil { | ||
| return fmt.Errorf("invalid VM ID: %v", err) | ||
| } | ||
| if vmID < 0 || vmID > int(math.MaxUint32) { | ||
| return fmt.Errorf("VM ID out of uint32 bounds: %d", vmID) | ||
| } | ||
|
|
||
| vmRef := pxapi.NewVmRef(pxapi.GuestID(vmID)) | ||
| vmRef := pxapi.NewVmRef(pxapi.GuestID(uint32(vmID))) | ||
| vmRef.SetNode(viper.GetString("proxmox.node")) | ||
|
|
||
| ctx := context.Background() |
| } | ||
|
|
||
| tlsConfig := &tls.Config{ | ||
| InsecureSkipVerify: true, // For self-signed certificates |
Check failure
Code scanning / CodeQL
Disabled TLS certificate check High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 4 months ago
The correct way to fix this issue is to securely verify server certificates rather than disabling verification. If self-signed certificates are used, the recommended approach is to add the CA certificate to the trusted pool, so InsecureSkipVerify can remain false. You can do this with x509.NewCertPool and loading the CA from a PEM file or environment variable, then assign this pool to the RootCAs of the tls.Config.
To fix, change line 22 to avoid setting InsecureSkipVerify: true. Instead, set InsecureSkipVerify: false (or omit it for the default). In addition, offer to load CA certificates from a PEM file path given by an environment variable like PROXMOX_CA_CERT, if available. This can be done inside GetClient().
Add imports for crypto/x509 and io/ioutil if not already present, and update the TLS config to use a custom Root CA pool if a PEM CA file is configured.
The fix involves:
- Changing
InsecureSkipVerifytofalse. - (Optionally and preferably) Adding logic: If an environment variable (e.g.,
PROXMOX_CA_CERT) is set, read the CA cert(s) from that file, parse into a cert pool, and assign totls.Config.RootCAs. - Add error handling for loading and parsing CA certs.
- Add necessary imports at the top:
crypto/x509andio/ioutil.
This preserves secure TLS validation while still allowing self-signed certificates, when they are properly trusted.
-
Copy modified lines R5-R6 -
Copy modified lines R23-R36 -
Copy modified lines R38-R40
| @@ -2,6 +2,8 @@ | ||
|
|
||
| import ( | ||
| "crypto/tls" | ||
| "crypto/x509" | ||
| "io/ioutil" | ||
| "log" | ||
| "os" | ||
|
|
||
| @@ -18,8 +20,24 @@ | ||
| os.Exit(1) | ||
| } | ||
|
|
||
| // Load CA certificate if PROXMOX_CA_CERT is set, to allow verification for self-signed certs. | ||
| var rootCAs *x509.CertPool | ||
| caCertPath := os.Getenv("PROXMOX_CA_CERT") | ||
| if caCertPath != "" { | ||
| caCert, err := ioutil.ReadFile(caCertPath) | ||
| if err != nil { | ||
| log.Fatalf("Failed to read CA certificate from %s: %v", caCertPath, err) | ||
| } | ||
| rootCAs = x509.NewCertPool() | ||
| if !rootCAs.AppendCertsFromPEM(caCert) { | ||
| log.Fatalf("Failed to parse CA certificate from %s", caCertPath) | ||
| } | ||
| } | ||
|
|
||
| tlsConfig := &tls.Config{ | ||
| InsecureSkipVerify: true, // For self-signed certificates | ||
| // Do not skip verification! | ||
| InsecureSkipVerify: false, | ||
| RootCAs: rootCAs, | ||
| } | ||
|
|
||
| client, err := pxapi.NewClient(apiURL, nil, "", tlsConfig, "", 300) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codex Review
Here are some automated review suggestions for this pull request.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting
| // Clone the VM | ||
| log.Println("[DEBUG] Cloning template", template, "to new VM", server.Name) | ||
| _, err = p.Client.CloneQemuVm(ctx, sourceVmr, cloneParams) | ||
| if err != nil { | ||
| return Vm{}, fmt.Errorf("failed to clone VM: %v", err) | ||
| } | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wait for Proxmox clone task before configuring VM
After invoking CloneQemuVm, the code immediately calls SetVmConfig and StartVm on the new VM with no wait. Proxmox cloning is asynchronous and keeps the target VM locked until the task finishes, so these subsequent calls typically fail with errors like “VM is locked” or “VM ID does not exist”. This causes most onctl create calls to error out even though the clone eventually completes. The task returned by CloneQemuVm should be waited on (WaitForCompletion/polling) before configuring or starting the VM.
Useful? React with 👍 / 👎.
internal/providerpxmx/common.go
Outdated
| ctx := context.Background() | ||
| err = client.Login(ctx, tokenID, secret, "") | ||
| if err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using password login for API token credentials blocks client initialization
GetClient reads PROXMOX_TOKEN_ID and PROXMOX_SECRET (documented as token-based auth) and then calls client.Login(ctx, tokenID, secret, ""). The Proxmox API expects username/password on Login; tokens must instead be set with SetAPIToken or similar and do not use the login endpoint. As written, authentication will fail with 401 when a token is supplied, so the provider exits before any command runs. Switch to the token-based authentication method or accept username/password explicitly.
Useful? React with 👍 / 👎.
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 7 out of 8 changed files in this pull request and generated 3 comments.
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| tlsConfig := &tls.Config{ | ||
| InsecureSkipVerify: true, // For self-signed certificates |
Copilot
AI
Oct 7, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Skipping TLS verification poses a security risk by allowing man-in-the-middle attacks. Consider making this configurable via environment variable or adding a warning message about the security implications.
| tlsConfig := &tls.Config{ | |
| InsecureSkipVerify: true, // For self-signed certificates | |
| insecureSkipVerify := false | |
| if os.Getenv("PROXMOX_INSECURE_SKIP_VERIFY") == "true" { | |
| insecureSkipVerify = true | |
| log.Println("WARNING: Skipping TLS verification. This poses a security risk and allows man-in-the-middle attacks.") | |
| } | |
| tlsConfig := &tls.Config{ | |
| InsecureSkipVerify: insecureSkipVerify, |
| } | ||
|
|
||
| // Wait for VM to start | ||
| time.Sleep(5 * time.Second) |
Copilot
AI
Oct 7, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hard-coded sleep duration makes the code less maintainable. Consider using a configurable timeout or implementing a proper wait mechanism that polls VM status until it's ready.
| return "", err | ||
| } | ||
|
|
||
| SSHKeyMD5 := fmt.Sprintf("%x", md5.Sum(publicKey)) |
Copilot
AI
Oct 7, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MD5 is cryptographically broken and should not be used for security purposes. Consider using SHA-256 or another secure hash function for key fingerprinting.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #715 +/- ##
========================================
- Coverage 8.33% 7.66% -0.68%
========================================
Files 31 33 +2
Lines 3036 3302 +266
========================================
Hits 253 253
- Misses 2762 3028 +266
Partials 21 21 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
No description provided.