Skip to content

Commit

Permalink
Merge branch 'release/1.17.1'
Browse files Browse the repository at this point in the history
  • Loading branch information
deviantony committed May 21, 2018
2 parents 19bb83b + 19f9840 commit f42733b
Show file tree
Hide file tree
Showing 32 changed files with 297 additions and 210 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,3 @@ steps:
candidate: '${{build_image}}'
tag: '${{CF_BRANCH}}'
registry: dockerhub
when:
branch:
only:
- develop
28 changes: 28 additions & 0 deletions api/bolt/migrate_dbversion10.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package bolt

import "github.com/portainer/portainer"

func (m *Migrator) updateEndpointsToVersion11() error {
legacyEndpoints, err := m.EndpointService.Endpoints()
if err != nil {
return err
}

for _, endpoint := range legacyEndpoints {
if endpoint.Type == portainer.AgentOnDockerEnvironment {
endpoint.TLSConfig.TLS = true
endpoint.TLSConfig.TLSSkipVerify = true
} else {
if endpoint.TLSConfig.TLSSkipVerify && !endpoint.TLSConfig.TLS {
endpoint.TLSConfig.TLSSkipVerify = false
}
}

err = m.EndpointService.UpdateEndpoint(endpoint.ID, &endpoint)
if err != nil {
return err
}
}

return nil
}
8 changes: 8 additions & 0 deletions api/bolt/migrator.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,14 @@ func (m *Migrator) Migrate() error {
}
}

// https://github.com/portainer/portainer/issues/1906
if m.CurrentDBVersion < 11 {
err := m.updateEndpointsToVersion11()
if err != nil {
return err
}
}

err := m.VersionService.StoreDBVersion(portainer.DBVersion)
if err != nil {
return err
Expand Down
18 changes: 9 additions & 9 deletions api/cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ func (*Service) ParseFlags(version string) (*portainer.CLIFlags, error) {
Addr: kingpin.Flag("bind", "Address and port to serve Portainer").Default(defaultBindAddress).Short('p').String(),
Assets: kingpin.Flag("assets", "Path to the assets").Default(defaultAssetsDirectory).Short('a').String(),
Data: kingpin.Flag("data", "Path to the folder where the data is stored").Default(defaultDataDirectory).Short('d').String(),
Endpoint: kingpin.Flag("host", "Dockerd endpoint").Short('H').String(),
EndpointURL: kingpin.Flag("host", "Endpoint URL").Short('H').String(),
ExternalEndpoints: kingpin.Flag("external-endpoints", "Path to a file defining available endpoints").String(),
NoAuth: kingpin.Flag("no-auth", "Disable authentication").Default(defaultNoAuth).Bool(),
NoAnalytics: kingpin.Flag("no-analytics", "Disable Analytics in app").Default(defaultNoAnalytics).Bool(),
TLSVerify: kingpin.Flag("tlsverify", "TLS support").Default(defaultTLSVerify).Bool(),
TLS: kingpin.Flag("tlsverify", "TLS support").Default(defaultTLS).Bool(),
TLSSkipVerify: kingpin.Flag("tlsskipverify", "Disable TLS server verification").Default(defaultTLSSkipVerify).Bool(),
TLSCacert: kingpin.Flag("tlscacert", "Path to the CA").Default(defaultTLSCACertPath).String(),
TLSCert: kingpin.Flag("tlscert", "Path to the TLS certificate file").Default(defaultTLSCertPath).String(),
Expand Down Expand Up @@ -69,11 +69,11 @@ func (*Service) ParseFlags(version string) (*portainer.CLIFlags, error) {
// ValidateFlags validates the values of the flags.
func (*Service) ValidateFlags(flags *portainer.CLIFlags) error {

if *flags.Endpoint != "" && *flags.ExternalEndpoints != "" {
if *flags.EndpointURL != "" && *flags.ExternalEndpoints != "" {
return errEndpointExcludeExternal
}

err := validateEndpoint(*flags.Endpoint)
err := validateEndpointURL(*flags.EndpointURL)
if err != nil {
return err
}
Expand All @@ -99,14 +99,14 @@ func (*Service) ValidateFlags(flags *portainer.CLIFlags) error {
return nil
}

func validateEndpoint(endpoint string) error {
if endpoint != "" {
if !strings.HasPrefix(endpoint, "unix://") && !strings.HasPrefix(endpoint, "tcp://") {
func validateEndpointURL(endpointURL string) error {
if endpointURL != "" {
if !strings.HasPrefix(endpointURL, "unix://") && !strings.HasPrefix(endpointURL, "tcp://") {
return errInvalidEndpointProtocol
}

if strings.HasPrefix(endpoint, "unix://") {
socketPath := strings.TrimPrefix(endpoint, "unix://")
if strings.HasPrefix(endpointURL, "unix://") {
socketPath := strings.TrimPrefix(endpointURL, "unix://")
if _, err := os.Stat(socketPath); err != nil {
if os.IsNotExist(err) {
return errSocketNotFound
Expand Down
2 changes: 1 addition & 1 deletion api/cli/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const (
defaultAssetsDirectory = "./"
defaultNoAuth = "false"
defaultNoAnalytics = "false"
defaultTLSVerify = "false"
defaultTLS = "false"
defaultTLSSkipVerify = "false"
defaultTLSCACertPath = "/certs/ca.pem"
defaultTLSCertPath = "/certs/cert.pem"
Expand Down
2 changes: 1 addition & 1 deletion api/cli/defaults_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const (
defaultAssetsDirectory = "./"
defaultNoAuth = "false"
defaultNoAnalytics = "false"
defaultTLSVerify = "false"
defaultTLS = "false"
defaultTLSSkipVerify = "false"
defaultTLSCACertPath = "C:\\certs\\ca.pem"
defaultTLSCertPath = "C:\\certs\\cert.pem"
Expand Down
136 changes: 95 additions & 41 deletions api/cmd/portainer/main.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package main // import "github.com/portainer/portainer"

import (
"strings"

"github.com/portainer/portainer"
"github.com/portainer/portainer/bolt"
"github.com/portainer/portainer/cli"
Expand Down Expand Up @@ -62,8 +64,8 @@ func initStore(dataStorePath string) *bolt.Store {
return store
}

func initStackManager(assetsPath string, signatureService portainer.DigitalSignatureService, fileService portainer.FileService) (portainer.StackManager, error) {
return exec.NewStackManager(assetsPath, signatureService, fileService)
func initStackManager(assetsPath string, dataStorePath string, signatureService portainer.DigitalSignatureService, fileService portainer.FileService) (portainer.StackManager, error) {
return exec.NewStackManager(assetsPath, dataStorePath, signatureService, fileService)
}

func initJWTService(authenticationEnabled bool) portainer.JWTService {
Expand Down Expand Up @@ -207,6 +209,93 @@ func initKeyPair(fileService portainer.FileService, signatureService portainer.D
return generateAndStoreKeyPair(fileService, signatureService)
}

func createTLSSecuredEndpoint(flags *portainer.CLIFlags, endpointService portainer.EndpointService) error {
tlsConfiguration := portainer.TLSConfiguration{
TLS: *flags.TLS,
TLSSkipVerify: *flags.TLSSkipVerify,
}

if *flags.TLS {
tlsConfiguration.TLSCACertPath = *flags.TLSCacert
tlsConfiguration.TLSCertPath = *flags.TLSCert
tlsConfiguration.TLSKeyPath = *flags.TLSKey
} else if !*flags.TLS && *flags.TLSSkipVerify {
tlsConfiguration.TLS = true
}

endpoint := &portainer.Endpoint{
Name: "primary",
URL: *flags.EndpointURL,
GroupID: portainer.EndpointGroupID(1),
Type: portainer.DockerEnvironment,
TLSConfig: tlsConfiguration,
AuthorizedUsers: []portainer.UserID{},
AuthorizedTeams: []portainer.TeamID{},
Extensions: []portainer.EndpointExtension{},
}

if strings.HasPrefix(endpoint.URL, "tcp://") {
tlsConfig, err := crypto.CreateTLSConfigurationFromDisk(tlsConfiguration.TLSCACertPath, tlsConfiguration.TLSCertPath, tlsConfiguration.TLSKeyPath, tlsConfiguration.TLSSkipVerify)
if err != nil {
return err
}

agentOnDockerEnvironment, err := client.ExecutePingOperation(endpoint.URL, tlsConfig)
if err != nil {
return err
}

if agentOnDockerEnvironment {
endpoint.Type = portainer.AgentOnDockerEnvironment
}
}

return endpointService.CreateEndpoint(endpoint)
}

func createUnsecuredEndpoint(endpointURL string, endpointService portainer.EndpointService) error {
if strings.HasPrefix(endpointURL, "tcp://") {
_, err := client.ExecutePingOperation(endpointURL, nil)
if err != nil {
return err
}
}

endpoint := &portainer.Endpoint{
Name: "primary",
URL: endpointURL,
GroupID: portainer.EndpointGroupID(1),
Type: portainer.DockerEnvironment,
TLSConfig: portainer.TLSConfiguration{},
AuthorizedUsers: []portainer.UserID{},
AuthorizedTeams: []portainer.TeamID{},
Extensions: []portainer.EndpointExtension{},
}

return endpointService.CreateEndpoint(endpoint)
}

func initEndpoint(flags *portainer.CLIFlags, endpointService portainer.EndpointService) error {
if *flags.EndpointURL == "" {
return nil
}

endpoints, err := endpointService.Endpoints()
if err != nil {
return err
}

if len(endpoints) > 0 {
log.Println("Instance already has defined endpoints. Skipping the endpoint defined via CLI.")
return nil
}

if *flags.TLS || *flags.TLSSkipVerify {
return createTLSSecuredEndpoint(flags, endpointService)
}
return createUnsecuredEndpoint(*flags.EndpointURL, endpointService)
}

func main() {
flags := initCLI()

Expand All @@ -232,7 +321,7 @@ func main() {
log.Fatal(err)
}

stackManager, err := initStackManager(*flags.Assets, digitalSignatureService, fileService)
stackManager, err := initStackManager(*flags.Assets, *flags.Data, digitalSignatureService, fileService)
if err != nil {
log.Fatal(err)
}
Expand All @@ -249,44 +338,9 @@ func main() {

applicationStatus := initStatus(authorizeEndpointMgmt, flags)

if *flags.Endpoint != "" {
endpoints, err := store.EndpointService.Endpoints()
if err != nil {
log.Fatal(err)
}
if len(endpoints) == 0 {
endpoint := &portainer.Endpoint{
Name: "primary",
URL: *flags.Endpoint,
Type: portainer.DockerEnvironment,
TLSConfig: portainer.TLSConfiguration{
TLS: *flags.TLSVerify,
TLSSkipVerify: *flags.TLSSkipVerify,
TLSCACertPath: *flags.TLSCacert,
TLSCertPath: *flags.TLSCert,
TLSKeyPath: *flags.TLSKey,
},
AuthorizedUsers: []portainer.UserID{},
AuthorizedTeams: []portainer.TeamID{},
Extensions: []portainer.EndpointExtension{},
}

agentOnDockerEnvironment, err := client.ExecutePingOperationFromEndpoint(endpoint)
if err != nil {
log.Fatal(err)
}

if agentOnDockerEnvironment {
endpoint.Type = portainer.AgentOnDockerEnvironment
}

err = store.EndpointService.CreateEndpoint(endpoint)
if err != nil {
log.Fatal(err)
}
} else {
log.Println("Instance already has defined endpoints. Skipping the endpoint defined via CLI.")
}
err = initEndpoint(flags, store.EndpointService)
if err != nil {
log.Fatal(err)
}

adminPasswordHash := ""
Expand Down
31 changes: 15 additions & 16 deletions api/crypto/tls.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import (
"crypto/tls"
"crypto/x509"
"io/ioutil"

"github.com/portainer/portainer"
)

func CreateTLSConfig(caCert, cert, key []byte, skipClientVerification, skipServerVerification bool) (*tls.Config, error) {
// CreateTLSConfigurationFromBytes initializes a tls.Config using a CA certificate, a certificate and a key
// loaded from memory.
func CreateTLSConfigurationFromBytes(caCert, cert, key []byte, skipClientVerification, skipServerVerification bool) (*tls.Config, error) {
config := &tls.Config{}
config.InsecureSkipVerify = skipServerVerification

Expand All @@ -29,32 +29,31 @@ func CreateTLSConfig(caCert, cert, key []byte, skipClientVerification, skipServe
return config, nil
}

// CreateTLSConfiguration initializes a tls.Config using a CA certificate, a certificate and a key
func CreateTLSConfiguration(config *portainer.TLSConfiguration) (*tls.Config, error) {
TLSConfig := &tls.Config{}
// CreateTLSConfigurationFromDisk initializes a tls.Config using a CA certificate, a certificate and a key
// loaded from disk.
func CreateTLSConfigurationFromDisk(caCertPath, certPath, keyPath string, skipServerVerification bool) (*tls.Config, error) {
config := &tls.Config{}
config.InsecureSkipVerify = skipServerVerification

if config.TLS && config.TLSCertPath != "" && config.TLSKeyPath != "" {
cert, err := tls.LoadX509KeyPair(config.TLSCertPath, config.TLSKeyPath)
if certPath != "" && keyPath != "" {
cert, err := tls.LoadX509KeyPair(certPath, keyPath)
if err != nil {
return nil, err
}

TLSConfig.Certificates = []tls.Certificate{cert}
config.Certificates = []tls.Certificate{cert}
}

if config.TLS && !config.TLSSkipVerify {
caCert, err := ioutil.ReadFile(config.TLSCACertPath)
if !skipServerVerification && caCertPath != "" {
caCert, err := ioutil.ReadFile(caCertPath)
if err != nil {
return nil, err
}

caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert)

TLSConfig.RootCAs = caCertPool
config.RootCAs = caCertPool
}

TLSConfig.InsecureSkipVerify = config.TLSSkipVerify

return TLSConfig, nil
return config, nil
}
Loading

0 comments on commit f42733b

Please sign in to comment.