Skip to content
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

feat(server): stop if not associated [EE-1610] #225

Merged
merged 7 commits into from Jan 18, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Next
feat(server): stop if not associated
  • Loading branch information
chiptus committed Jan 12, 2022
commit a66977c76043fcff4a8f69c4b65988272d27c01f
3 changes: 3 additions & 0 deletions agent.go
Expand Up @@ -122,6 +122,7 @@ type (

// DigitalSignatureService is used to validate digital signatures.
DigitalSignatureService interface {
IsAssociated() bool
VerifySignature(signature, key string) (bool, error)
}

Expand Down Expand Up @@ -178,6 +179,8 @@ const (
DefaultAgentPort = "9001"
// DefaultLogLevel is the default logging level.
DefaultLogLevel = "INFO"
// DefaultAgentSecurityShutdown is the default time after which the API server will shutdown if not associated with a Portainer instance
DefaultAgentSecurityShutdown = "3d"
// DefaultEdgeSecurityShutdown is the default time after which the Edge server will shutdown if no key is specified
DefaultEdgeSecurityShutdown = 15
// DefaultEdgeServerAddr is the default address used by the Edge server.
Expand Down
7 changes: 6 additions & 1 deletion cmd/agent/main.go
@@ -1,8 +1,11 @@
package main

import (
"errors"
"fmt"
"log"
gohttp "net/http"
"runtime"
"time"

"github.com/portainer/agent"
Expand Down Expand Up @@ -232,10 +235,12 @@ func main() {
}

err = startAPIServer(config)
if err != nil {
if err != nil && !errors.Is(err, gohttp.ErrServerClosed) {
log.Fatalf("[ERROR] [main,http] [message: Unable to start Agent API server] [error: %s]", err)
}

runtime.Goexit()
chiptus marked this conversation as resolved.
Show resolved Hide resolved

// !API
}

Expand Down
6 changes: 6 additions & 0 deletions crypto/ecdsa.go
Expand Up @@ -26,6 +26,12 @@ func NewECDSAService(secret string) *ECDSAService {
}
}

// IsAssociated tells if the service is associated with a public key
// or if it's secured behind a secret
func (service *ECDSAService) IsAssociated() bool {
return service.publicKey != nil || service.secret != ""
}

// VerifySignature is used to verify a digital signature using a specified public
// key. The public key specified as a parameter must be hexadecimal encoded.
// The public key will be decoded and parsed as DER data. If the service is not
Expand Down
22 changes: 22 additions & 0 deletions http/server.go
@@ -1,6 +1,7 @@
package http

import (
"context"
"crypto/tls"
"log"
"net/http"
Expand Down Expand Up @@ -134,5 +135,26 @@ func (server *APIServer) StartSecured() error {
WriteTimeout: 30 * time.Minute,
}

go func() {
agentSecurityShutdown := 10

timer1 := time.NewTimer(time.Duration(agentSecurityShutdown) * time.Second)
<-timer1.C
chiptus marked this conversation as resolved.
Show resolved Hide resolved

if !server.signatureService.IsAssociated() {
log.Printf("[INFO] [main,http] [message: Shutting down API server as no client was associated after %d minutes , keeping alive to prevent restart by docker/kubernetes]", agentSecurityShutdown)

err := httpServer.Shutdown(context.Background())
if err != nil {
log.Fatalf("[ERROR] [server] [message: failed shutting down server] [error: %s]", err)
}

// Keep alive
for {
time.Sleep(time.Second)
}
chiptus marked this conversation as resolved.
Show resolved Hide resolved
}
}()

return httpServer.ListenAndServeTLS(agent.TLSCertPath, agent.TLSKeyPath)
}