Skip to content

Commit

Permalink
add --sslcert, --sslkey, --sslcacert to agent
Browse files Browse the repository at this point in the history
Signed-off-by: Sven Dowideit <[email protected]>
  • Loading branch information
SvenDowideit committed Feb 7, 2022
1 parent 1359a82 commit 96b0e2d
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 62 deletions.
3 changes: 3 additions & 0 deletions agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ type (
EdgeInactivityTimeout string
EdgeInsecurePoll bool
LogLevel string
SSLCert string
SSLKey string
SSLCacert string
}

// PciDevice is the representation of a physical pci device on a host
Expand Down
18 changes: 2 additions & 16 deletions edge/client/portainer_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,12 @@ package client

import (
"bytes"
"crypto/tls"
"encoding/json"
"errors"
"fmt"
"log"
"net/http"
"strconv"
"time"

"github.com/portainer/agent"
)
Expand All @@ -23,24 +21,12 @@ type PortainerClient struct {
}

// NewPortainerClient returns a pointer to a new PortainerClient instance
func NewPortainerClient(serverAddress, endpointID, edgeID string, insecurePoll bool) *PortainerClient {
httpCli := &http.Client{
Timeout: 10 * time.Second,
}

if insecurePoll {
httpCli.Transport = &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
}
}

func NewPortainerClient(serverAddress, endpointID, edgeID string, httpClient *http.Client) *PortainerClient {
return &PortainerClient{
serverAddress: serverAddress,
endpointID: endpointID,
edgeID: edgeID,
httpClient: httpCli,
httpClient: httpClient, //GetNewHttpClient(10, insecurePoll),
}
}

Expand Down
81 changes: 74 additions & 7 deletions edge/edge.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
package edge

import (
"crypto/tls"
"crypto/x509"
"errors"
"fmt"
"github.com/portainer/agent/edge/scheduler"
"github.com/portainer/agent/edge/stack"
"io/ioutil"
"log"
"net/http"
"time"

"github.com/portainer/agent/edge/client"
"github.com/portainer/agent/edge/scheduler"
"github.com/portainer/agent/edge/stack"

"github.com/portainer/agent"
)

Expand Down Expand Up @@ -60,26 +66,44 @@ func (manager *Manager) Start() error {
EdgeID: manager.agentOptions.EdgeID,
PollFrequency: agent.DefaultEdgePollInterval,
InactivityTimeout: manager.agentOptions.EdgeInactivityTimeout,
InsecurePoll: manager.agentOptions.EdgeInsecurePoll,
PortainerURL: manager.key.PortainerInstanceURL,
EndpointID: manager.key.EndpointID,
TunnelServerAddr: manager.key.TunnelServerAddr,
TunnelServerFingerprint: manager.key.TunnelServerFingerprint,
ContainerPlatform: manager.containerPlatform,
}

log.Printf("[DEBUG] [internal,edge] [api_addr: %s] [edge_id: %s] [poll_frequency: %s] [inactivity_timeout: %s] [insecure_poll: %t]", pollServiceConfig.APIServerAddr, pollServiceConfig.EdgeID, pollServiceConfig.PollFrequency, pollServiceConfig.InactivityTimeout, pollServiceConfig.InsecurePoll)
log.Printf("[DEBUG] [internal,edge] [api_addr: %s] [edge_id: %s] [poll_frequency: %s] [inactivity_timeout: %s] [insecure_poll: %t]", pollServiceConfig.APIServerAddr, pollServiceConfig.EdgeID, pollServiceConfig.PollFrequency, pollServiceConfig.InactivityTimeout, manager.agentOptions.EdgeInsecurePoll)

stackManager, err := stack.NewStackManager(manager.key.PortainerInstanceURL, manager.key.EndpointID, manager.agentOptions.EdgeID, pollServiceConfig.InsecurePoll)
stackManager, err := stack.NewStackManager(
client.NewPortainerClient(
manager.key.PortainerInstanceURL,
manager.key.EndpointID,
manager.agentOptions.EdgeID,
GetNewHttpClient(10, manager.agentOptions),
),
)
if err != nil {
return err
}
manager.stackManager = stackManager

manager.logsManager = scheduler.NewLogsManager(manager.key.PortainerInstanceURL, manager.key.EndpointID, manager.agentOptions.EdgeID, pollServiceConfig.InsecurePoll)
manager.logsManager = scheduler.NewLogsManager(
client.NewPortainerClient(
manager.key.PortainerInstanceURL,
manager.key.EndpointID,
manager.agentOptions.EdgeID,
GetNewHttpClient(10, manager.agentOptions),
),
)
manager.logsManager.Start()

pollService, err := newPollService(manager.stackManager, manager.logsManager, pollServiceConfig)
pollService, err := newPollService(
manager.stackManager,
manager.logsManager,
pollServiceConfig,
GetNewHttpClient(clientDefaultPollTimeout, manager.agentOptions),
)
if err != nil {
return err
}
Expand Down Expand Up @@ -220,3 +244,46 @@ func (manager *Manager) checkDockerRuntimeConfig() error {

return nil
}

func GetNewHttpClient(timeout float64, options *agent.Options) *http.Client {
httpCli := &http.Client{
Timeout: time.Duration(timeout) * time.Second,
}

if options.EdgeInsecurePoll {
httpCli.Transport = &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
}
}

// if ssl certs for edge agent are set
if options.SSLCert != "" && options.SSLKey != "" {
// Read the key pair to create certificate
cert, err := tls.LoadX509KeyPair(options.SSLCert, options.SSLKey)
if err != nil {
log.Fatal(err)
}

var caCertPool *x509.CertPool
// Create a CA certificate pool and add cert.pem to it
if options.SSLCacert != "" {
caCert, err := ioutil.ReadFile(options.SSLCacert)
if err != nil {
log.Fatal(err)
}
caCertPool = x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert)
}

// Create a HTTPS client and supply the created CA pool and certificate
httpCli.Transport = &http.Transport{
TLSClientConfig: &tls.Config{
RootCAs: caCertPool,
Certificates: []tls.Certificate{cert},
},
}
}
return httpCli
}
43 changes: 11 additions & 32 deletions edge/poll.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
package edge

import (
"crypto/tls"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"github.com/portainer/agent/edge/scheduler"
"github.com/portainer/agent/edge/stack"
"log"
"net/http"
"strconv"
"time"

"github.com/portainer/agent/edge/scheduler"
"github.com/portainer/agent/edge/stack"

"github.com/portainer/agent"
"github.com/portainer/agent/chisel"
"github.com/portainer/libcrypto"
Expand All @@ -26,7 +26,6 @@ const tunnelActivityCheckInterval = 30 * time.Second
type PollService struct {
apiServerAddr string
pollIntervalInSeconds float64
insecurePoll bool
inactivityTimeout time.Duration
edgeID string
httpClient *http.Client
Expand All @@ -44,11 +43,11 @@ type PollService struct {
}

type pollServiceConfig struct {
APIServerAddr string
EdgeID string
InactivityTimeout string
PollFrequency string
InsecurePoll bool
APIServerAddr string
EdgeID string
InactivityTimeout string
PollFrequency string
//InsecurePoll bool
PortainerURL string
EndpointID string
TunnelServerAddr string
Expand All @@ -57,7 +56,7 @@ type pollServiceConfig struct {
}

// newPollService returns a pointer to a new instance of PollService
func newPollService(edgeStackManager *stack.StackManager, logsManager *scheduler.LogsManager, config *pollServiceConfig) (*PollService, error) {
func newPollService(edgeStackManager *stack.StackManager, logsManager *scheduler.LogsManager, config *pollServiceConfig, httpClient *http.Client) (*PollService, error) {
pollFrequency, err := time.ParseDuration(config.PollFrequency)
if err != nil {
return nil, err
Expand All @@ -72,7 +71,6 @@ func newPollService(edgeStackManager *stack.StackManager, logsManager *scheduler
apiServerAddr: config.APIServerAddr,
edgeID: config.EdgeID,
pollIntervalInSeconds: pollFrequency.Seconds(),
insecurePoll: config.InsecurePoll,
inactivityTimeout: inactivityTimeout,
tunnelClient: chisel.NewClient(),
scheduleManager: scheduler.NewCronManager(),
Expand All @@ -84,6 +82,7 @@ func newPollService(edgeStackManager *stack.StackManager, logsManager *scheduler
tunnelServerFingerprint: config.TunnelServerFingerprint,
logsManager: logsManager,
containerPlatform: config.ContainerPlatform,
httpClient: httpClient, //client.GetNewHttpClient(clientDefaultPollTimeout, config.InsecurePoll),
}, nil
}

Expand Down Expand Up @@ -204,22 +203,6 @@ type pollStatusResponse struct {
Stacks []stackStatus `json:"stacks"`
}

func (service *PollService) createHTTPClient(timeout float64) {
httpCli := &http.Client{
Timeout: time.Duration(timeout) * time.Second,
}

if service.insecurePoll {
httpCli.Transport = &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
}
}

service.httpClient = httpCli
}

func (service *PollService) poll() error {

pollURL := fmt.Sprintf("%s/api/endpoints/%s/status", service.portainerURL, service.endpointID)
Expand All @@ -240,10 +223,6 @@ func (service *PollService) poll() error {

log.Printf("[DEBUG] [internal,edge,poll] [message: sending agent platform header] [header: %s]", strconv.Itoa(int(agentPlatformIdentifier)))

if service.httpClient == nil {
service.createHTTPClient(clientDefaultPollTimeout)
}

resp, err := service.httpClient.Do(req)
if err != nil {
return err
Expand Down Expand Up @@ -299,7 +278,7 @@ func (service *PollService) poll() error {
if responseData.CheckinInterval != service.pollIntervalInSeconds {
log.Printf("[DEBUG] [internal,edge,poll] [old_interval: %f] [new_interval: %f] [message: updating poll interval]", service.pollIntervalInSeconds, responseData.CheckinInterval)
service.pollIntervalInSeconds = responseData.CheckinInterval
service.createHTTPClient(responseData.CheckinInterval)
service.httpClient.Timeout = time.Duration(responseData.CheckinInterval) * time.Second
go service.restartStatusPollLoop()
}

Expand Down
7 changes: 3 additions & 4 deletions edge/scheduler/logs.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ package scheduler

import (
"fmt"
"github.com/portainer/agent/edge/client"
"log"
"time"

"github.com/portainer/agent/edge/client"

"github.com/portainer/agent"
"github.com/portainer/agent/filesystem"
)
Expand All @@ -25,9 +26,7 @@ const (
logFailed
)

func NewLogsManager(portainerURL, endpointID, edgeID string, insecurePoll bool) *LogsManager {
cli := client.NewPortainerClient(portainerURL, endpointID, edgeID, insecurePoll)

func NewLogsManager(cli *client.PortainerClient) *LogsManager {
return &LogsManager{
httpClient: cli,
stopSignal: nil,
Expand Down
4 changes: 1 addition & 3 deletions edge/stack/stack.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,7 @@ type StackManager struct {
}

// NewStackManager returns a pointer to a new instance of StackManager
func NewStackManager(portainerURL, endpointID, edgeID string, insecurePoll bool) (*StackManager, error) {
cli := client.NewPortainerClient(portainerURL, endpointID, edgeID, insecurePoll)

func NewStackManager(cli *client.PortainerClient) (*StackManager, error) {
stackManager := &StackManager{
stacks: map[edgeStackID]*edgeStack{},
stopSignal: nil,
Expand Down
8 changes: 8 additions & 0 deletions os/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ var (
fEdgeServerPort = kingpin.Flag("EdgeServerPort", EnvKeyEdgeServerPort+" port on which the Edge UI will be exposed (default to 80)").Envar(EnvKeyEdgeServerPort).Default(agent.DefaultEdgeServerPort).Int()
fEdgeInactivityTimeout = kingpin.Flag("EdgeInactivityTimeout", EnvKeyEdgeInactivityTimeout+" timeout used by the agent to close the reverse tunnel after inactivity (default to 5m)").Envar(EnvKeyEdgeInactivityTimeout).Default(agent.DefaultEdgeSleepInterval).String()
fEdgeInsecurePoll = kingpin.Flag("EdgeInsecurePoll", EnvKeyEdgeInsecurePoll+" enable this option if you need the agent to poll a HTTPS Portainer instance with self-signed certificates. Disabled by default, set to 1 to enable it").Envar(EnvKeyEdgeInsecurePoll).Bool()

// mTLS edge agent certs
fSSLCert = kingpin.Flag("sslcert", "Path to the SSL certificate used to identify the agent to Portainer").String()
fSSLKey = kingpin.Flag("sslkey", "Path to the SSL key used to identify the agent to Portainer").String()
fSSLCacert = kingpin.Flag("sslcacert", "Path to the SSL CA certificate used to validate the Portainer server").String()
)

func (parser *EnvOptionParser) Options() (*agent.Options, error) {
Expand All @@ -65,5 +70,8 @@ func (parser *EnvOptionParser) Options() (*agent.Options, error) {
EdgeInactivityTimeout: *fEdgeInactivityTimeout,
EdgeInsecurePoll: *fEdgeInsecurePoll,
LogLevel: *fLogLevel,
SSLCert: *fSSLCert,
SSLKey: *fSSLKey,
SSLCacert: *fSSLCacert,
}, nil
}

0 comments on commit 96b0e2d

Please sign in to comment.