-
Notifications
You must be signed in to change notification settings - Fork 0
feat: parse PEM bundle in GenerateCertificate and add --private-key flag #10
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
Changes from all commits
b532a5c
b775da0
7110ef1
e6f8ac9
7cb93ff
7a9d625
1707953
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2,13 +2,21 @@ package cmd | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "context" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "crypto/ecdsa" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "crypto/x509" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "encoding/base64" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "encoding/pem" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "fmt" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "net/http" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "os" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "os/signal" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "runtime/debug" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "strings" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "sync" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "syscall" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "time" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "github.com/agentuity/go-common/gravity/provider" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| _logger "github.com/agentuity/go-common/logger" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cnet "github.com/agentuity/go-common/network" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| csys "github.com/agentuity/go-common/sys" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -56,20 +64,48 @@ var rootCmd = &cobra.Command{ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| localPort, _ := flags.GetInt("port") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| orgID, _ := flags.GetString("org-id") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| projectID, _ := flags.GetString("project-id") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| token, _ := flags.GetString("token") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| maybePrivateKey, _ := flags.GetString("private-key") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| endpointID, _ := flags.GetString("endpoint-id") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| gravityUrl, _ := flags.GetString("url") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| healthCheck, _ := flags.GetBool("health-check") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| token, _ := flags.GetString("token") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if token != "" { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| logger.Fatal("The --token flag is no longer supported. Please update your Agentuity CLI to the latest version.") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ipv4addr, err := utils.GetPrivateIPv4() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| logger.Fatal("failed to get private IPv4: %v", err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| privateKeyPEM, err := loadPrivateKeyPEM(maybePrivateKey) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| logger.Fatal("failed to load private key: %v", err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| block, _ := pem.Decode(privateKeyPEM) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if block == nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| logger.Fatal("no PEM block found in --private-key") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| key, err := x509.ParsePKCS8PrivateKey(block.Bytes) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Try SEC 1/EC format as fallback | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| key, err = x509.ParseECPrivateKey(block.Bytes) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| logger.Fatal("failed to parse private key: %v (pem length: %d)", err, len(privateKeyPEM)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| privateKey, ok := key.(*ecdsa.PrivateKey) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if !ok { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| logger.Fatal("private key is not an ECDSA key") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| agent := stack.AgentMetadata{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| OrgID: orgID, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ProjectID: projectID, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| InstanceID: endpointID, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| PrivateKey: privateKey, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+82
to
109
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# First, let's find and read the file cmd/start.go
find . -name "cmd" -type d | head -5
find . -name "start.go" -type f | head -5Repository: agentuity/gravity Length of output: 81 🏁 Script executed: #!/bin/bash
# Read the specific lines in question (82-109)
if [ -f "cmd/start.go" ]; then
echo "=== cmd/start.go lines 75-115 ==="
sed -n '75,115p' "cmd/start.go" | cat -n
else
echo "File not found, searching..."
find . -name "start.go" -type f -exec wc -l {} \; -exec echo "File: {}" \;
fiRepository: agentuity/gravity Length of output: 1535 🏁 Script executed: #!/bin/bash
# Also check if there are any tests or examples showing how privateKeyPEM is used
rg -A 5 -B 5 "pem.Decode" --type goRepository: agentuity/gravity Length of output: 1754 🏁 Script executed: #!/bin/bash
# Find the loadPrivateKeyPEM function
rg -A 15 "func loadPrivateKeyPEM" cmd/start.goRepository: agentuity/gravity Length of output: 524 🏁 Script executed: #!/bin/bash
# Check for tests or examples that show input format
find . -name "*test*.go" -type f -exec rg -l "privateKeyPEM\|loadPrivateKeyPEM" {} \;Repository: agentuity/gravity Length of output: 43 🏁 Script executed: #!/bin/bash
# Check Go's crypto/x509 documentation via looking at how EC PARAMETERS blocks work
# EC PARAMETERS are sometimes generated in openssl EC key output
# Let's see if there are any examples in the codebase
rg -i "EC PARAMETERS|ec parameters" .Repository: agentuity/gravity Length of output: 43 🏁 Script executed: #!/bin/bash
# Get the full loadPrivateKeyPEM function
rg -A 30 "func loadPrivateKeyPEM" cmd/start.goRepository: agentuity/gravity Length of output: 1116 🏁 Script executed: #!/bin/bash
# Look at the parsePEMBundle implementation in stack.go to see the pattern
rg -A 25 "func parsePEMBundle" internal/stack/stack.goRepository: agentuity/gravity Length of output: 665 🏁 Script executed: #!/bin/bash
# Check Go's crypto documentation online to confirm pem.Decode behavior
# Let's also look for any comments about key format expectations
rg -B 5 -A 5 "PKCS8\|ParseEC" cmd/start.goRepository: agentuity/gravity Length of output: 43 Loop through PEM blocks to find a private key block instead of parsing the first block unconditionally. PEM files may contain EC PARAMETERS blocks, certificates, or other data before the private key. The current code calls This pattern is already established in Suggested fix- block, _ := pem.Decode(privateKeyPEM)
- if block == nil {
- logger.Fatal("no PEM block found in --private-key")
- }
+ var block *pem.Block
+ rest := privateKeyPEM
+ for {
+ var b *pem.Block
+ b, rest = pem.Decode(rest)
+ if b == nil {
+ break
+ }
+ if strings.Contains(b.Type, "PRIVATE KEY") {
+ block = b
+ break
+ }
+ }
+ if block == nil {
+ logger.Fatal("no private key PEM block found in --private-key")
+ }📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ipv6Address := cnet.NewIPv6Address(cnet.GetRegion(""), cnet.NetworkHadron, agent.OrgID, agent.InstanceID, ipv4addr) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -83,32 +119,42 @@ var rootCmd = &cobra.Command{ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| IPv6Addr: ipv6Address.String(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| LocalPort: localPort, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ProxyPort: proxyPort, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Token: token, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| URL: gravityUrl, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Version: version, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| provResp, err := stack.ProvisionGravity(ctx, logger, agent, urls) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| logger.Fatal("failed to provision gravity: %v", err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tlsConfig, err := stack.GenerateCertificate(ctx, logger, provResp) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| logger.Fatal("failed to generate certificate: %v", err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| server, err := stack.StartServer(ctx, logger, tlsConfig, urls) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| logger.Fatal("failed to start server: %v", err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| netStack, linkEP, err := stack.CreateNetworkStack(logger, urls) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| logger.Fatal("failed to create network stack: %v", err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| defer netStack.Close() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| defer linkEP.Close() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| provider, client, err := stack.CreateNetworkProvider(ctx, logger, linkEP, provResp, urls, agent) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var server *http.Server | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var serverMu sync.Mutex | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| provider, client, err := stack.CreateNetworkProvider(ctx, logger, linkEP, urls, agent, func(c *provider.Configuration) error { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| serverMu.Lock() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| oldServer := server | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| server = nil | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| serverMu.Unlock() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if oldServer != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err := oldServer.Shutdown(ctx); err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| logger.Error("failed to shutdown server: %v", err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tlsConfig, err := stack.GenerateCertificate(ctx, logger, c.MachineCertBundle) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return fmt.Errorf("failed to generate certificate: %w", err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| newServer, err := stack.StartServer(ctx, logger, tlsConfig, urls) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return fmt.Errorf("failed to start server: %w", err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| serverMu.Lock() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| server = newServer | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| serverMu.Unlock() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+133
to
+155
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ❓ Verification inconclusiveScript executed: git ls-files cmd/ | head -20Repository: agentuity/gravity Repository: agentuity/gravity stdout: Script executed: cat -n cmd/start.go | sed -n '120,170p'Repository: agentuity/gravity Repository: agentuity/gravity stdout: Script executed: cat -n cmd/start.go | sed -n '1,140p' | grep -E "(func |ctx\s*:=|ctx\s*=)"Repository: agentuity/gravity Repository: agentuity/gravity Script executed: cat -n cmd/start.go | head -80Repository: agentuity/gravity Repository: agentuity/gravity stdout: Script executed: fd -t f "\.go$" internal/stack/ | head -20Repository: agentuity/gravity Repository: agentuity/gravity stdout: Script executed: rg "func CreateNetworkProvider" --type go -A 20Repository: agentuity/gravity Repository: agentuity/gravity stdout: Script executed: rg "onConnect" internal/stack/stack.go -B 3 -A 3Repository: agentuity/gravity Repository: agentuity/gravity stdout: Script executed: cat -n internal/stack/stack.go | wc -lRepository: agentuity/gravity Repository: agentuity/gravity stdout: Script executed: cat -n internal/stack/stack.go | sed -n '50,150p'Repository: agentuity/gravity Repository: agentuity/gravity stdout: Script executed: rg "\.onConnect\(" internal/stack/ -B 5 -A 5Repository: agentuity/gravity Repository: agentuity/gravity stdout: Script executed: cat -n internal/stack/gravityClient.goRepository: agentuity/gravity Repository: agentuity/gravity stdout: Script executed: rg "\.Configure\(" --type go | head -20Repository: agentuity/gravity Repository: agentuity/gravity Script executed: rg "provider\.Configuration" --type go -B 3 -A 3 | head -50Repository: agentuity/gravity Repository: agentuity/gravity stdout: Script executed: rg "func.*Shutdown" --type go -B 2 -A 5Repository: agentuity/gravity Repository: agentuity/gravity stdout: Script executed: cat -n cmd/start.go | sed -n '135,160p'Repository: agentuity/gravity Repository: agentuity/gravity stdout: Script executed: web_search
http.Server.Shutdown behavior with context timeoutRepository: agentuity/gravity Repository: agentuity/gravity stderr: http.Server.Shutdown context timeout behavior golang In Go’s What
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var server *http.Server | |
| var serverMu sync.Mutex | |
| provider, client, err := stack.CreateNetworkProvider(ctx, logger, linkEP, urls, agent, func(c *provider.Configuration) error { | |
| serverMu.Lock() | |
| oldServer := server | |
| server = nil | |
| serverMu.Unlock() | |
| if oldServer != nil { | |
| if err := oldServer.Shutdown(ctx); err != nil { | |
| logger.Error("failed to shutdown server: %v", err) | |
| } | |
| } | |
| tlsConfig, err := stack.GenerateCertificate(ctx, logger, c.MachineCertBundle) | |
| if err != nil { | |
| return fmt.Errorf("failed to generate certificate: %w", err) | |
| } | |
| newServer, err := stack.StartServer(ctx, logger, tlsConfig, urls) | |
| if err != nil { | |
| return fmt.Errorf("failed to start server: %w", err) | |
| } | |
| serverMu.Lock() | |
| server = newServer | |
| serverMu.Unlock() | |
| var server *http.Server | |
| var serverMu sync.Mutex | |
| provider, client, err := stack.CreateNetworkProvider(ctx, logger, linkEP, urls, agent, func(c *provider.Configuration) error { | |
| serverMu.Lock() | |
| oldServer := server | |
| server = nil | |
| serverMu.Unlock() | |
| if oldServer != nil { | |
| shutdownCtx, cancel := context.WithTimeout(ctx, 10*time.Second) | |
| defer cancel() | |
| if err := oldServer.Shutdown(shutdownCtx); err != nil { | |
| logger.Error("failed to shutdown server: %v", err) | |
| } | |
| } | |
| tlsConfig, err := stack.GenerateCertificate(ctx, logger, c.MachineCertBundle) | |
| if err != nil { | |
| return fmt.Errorf("failed to generate certificate: %w", err) | |
| } | |
| newServer, err := stack.StartServer(ctx, logger, tlsConfig, urls) | |
| if err != nil { | |
| return fmt.Errorf("failed to start server: %w", err) | |
| } | |
| serverMu.Lock() | |
| server = newServer | |
| serverMu.Unlock() |
🤖 Prompt for AI Agents
In `@cmd/start.go` around lines 133 - 155, The shutdown of oldServer in the
provider reconfigure callback currently calls oldServer.Shutdown(ctx) with the
long-lived root context and can block indefinitely; change that call to use a
bounded timeout context (e.g., via context.WithTimeout(parentCtx, timeout)) so
the shutdown completes or aborts within a fixed grace period, ensure you call
cancel() and handle/log Shutdown errors including context deadline exceeded, and
keep the rest of the callback (GenerateCertificate, StartServer, and assignment
to server under serverMu) unchanged; update the closure where oldServer is set
and Shutdown is invoked (the variables server, serverMu, oldServer in the
CreateNetworkProvider callback).
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| package stack | ||
|
|
||
| import ( | ||
| "net/url" | ||
| "strings" | ||
|
|
||
| "github.com/agentuity/go-common/logger" | ||
| ) | ||
|
|
||
| const gravityPublicCACertProd = `-----BEGIN CERTIFICATE----- | ||
| MIIBvDCCAWKgAwIBAgIIQpGyfo9xbKUwCgYIKoZIzj0EAwIwQjELMAkGA1UEBhMC | ||
| VVMxFzAVBgNVBAoTDkFnZW50dWl0eSwgSW5jMRowGAYDVQQDExFBZ2VudHVpdHkg | ||
| Um9vdCBDQTAeFw0yNTA4MjgyMDAyNDJaFw0zNTA4MjgyMTAyNDJaMEIxCzAJBgNV | ||
| BAYTAlVTMRcwFQYDVQQKEw5BZ2VudHVpdHksIEluYzEaMBgGA1UEAxMRQWdlbnR1 | ||
| aXR5IFJvb3QgQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASuQLIe47OC2EtE | ||
| 3cwkXJ3siuBeoi5FuJ5wmny1BqA60FrHqHnCiYHIZSyv79WvGs6NAxlJsCQbBtcE | ||
| FNvrFfUso0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV | ||
| HQ4EFgQURmQweSNnxsTZ/ckG+A08IW7S+fwwCgYIKoZIzj0EAwIDSAAwRQIhAJzN | ||
| k5ZrKQPMCAEh1zBuUbWTcuRCnqdk583gcCBkUo58AiBny+nX/KLE46z1B1NK8qg9 | ||
| /K75YibTFYFFQAXMF10aNg== | ||
| -----END CERTIFICATE-----` | ||
|
|
||
| const gravityPublicCACertDev = `-----BEGIN CERTIFICATE----- | ||
| MIIBtTCCAVugAwIBAgIBATAKBggqhkjOPQQDAjBCMQswCQYDVQQGEwJVUzEXMBUG | ||
| A1UEChMOQWdlbnR1aXR5LCBJbmMxGjAYBgNVBAMTEUFnZW50dWl0eSBSb290IENB | ||
| MB4XDTI1MDgyNzIwNTIxM1oXDTM1MDgyNzIxNTIxM1owQjELMAkGA1UEBhMCVVMx | ||
| FzAVBgNVBAoTDkFnZW50dWl0eSwgSW5jMRowGAYDVQQDExFBZ2VudHVpdHkgUm9v | ||
| dCBDQTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABMleqtFE+8V/nC2eUEOEkfX+ | ||
| SZDT9+QSIr2B2HoCllDVnyzOKZFGxURvr90dKa/SUiwfS6LjZp6xNUv2gP7GOIWj | ||
| QjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSg | ||
| O9ViNhPYNISETcjqCsgs+TN80TAKBggqhkjOPQQDAgNIADBFAiAPcCANK2aU/Q/t | ||
| J4R6Su68r+iGJKpONFOiD3DX3p8oMgIhAI32feTJZwUVkNtjTYBRxoYUdZlyobp1 | ||
| lTpZE2H0bHCM | ||
| -----END CERTIFICATE----- | ||
| ` | ||
|
|
||
| // GravityCACertificate returns the Agentuity gravity CA certificate | ||
| func GravityCACertificate(logger logger.Logger, gravityURL string) string { | ||
| // Select the appropriate hash based on the API URL | ||
| if isDevelopmentGravityURL(gravityURL) { | ||
| logger.Debug("Using development CA") | ||
| return gravityPublicCACertDev | ||
| } | ||
|
|
||
| logger.Debug("Using production CA") | ||
| return gravityPublicCACertProd | ||
| } | ||
|
|
||
| // isDevelopmentGravityURL determines if we're in a development environment based on the API URL | ||
| func isDevelopmentGravityURL(apiURL string) bool { | ||
| parsedURL, err := url.Parse(apiURL) | ||
| if err != nil { | ||
| return false | ||
| } | ||
|
|
||
| // Extract hostname, stripping any port | ||
| hostname := parsedURL.Hostname() | ||
|
|
||
| // Exact matches for development environments | ||
| if hostname == "localhost" || hostname == "127.0.0.1" || hostname == "host.docker" { | ||
| return true | ||
| } | ||
|
|
||
| // Safe suffix check for agentuity.io domain | ||
| if hostname == "agentuity.io" || strings.HasSuffix(hostname, ".agentuity.io") { | ||
| return true | ||
| } | ||
|
|
||
| return false | ||
| } |
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.
Make the
--tokendeprecation message actionable.The current fatal message implies “update CLI,” but the fix is to remove
--token/AGENTUITY_SDK_KEYand use--private-key. Consider updating the text to reduce user confusion.💡 Suggested wording tweak
📝 Committable suggestion
🤖 Prompt for AI Agents