[lxc-devel] [lxd/master] [WIP] Improve candid/macaroon based authentication

monstermunchkin on Github lxc-bot at linuxcontainers.org
Thu Aug 9 05:11:34 UTC 2018


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 301 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20180809/2800d781/attachment.bin>
-------------- next part --------------
From 771b59e9a35b3538ca849592ab095a597f09d553 Mon Sep 17 00:00:00 2001
From: Thomas Hipp <thomas.hipp at canonical.com>
Date: Wed, 8 Aug 2018 15:39:33 +0200
Subject: [PATCH 1/2] *: Rename macaroon(s) -> candid

Signed-off-by: Thomas Hipp <thomas.hipp at canonical.com>
---
 client/connection.go         |  4 ++--
 doc/security.md              | 10 +++++-----
 doc/server.md                |  2 +-
 lxc/remote.go                |  4 ++--
 lxd/api_1.0.go               |  6 +++---
 lxd/cluster/config.go        |  8 ++++----
 lxd/daemon.go                |  6 +++---
 scripts/bash/lxd-client      |  2 +-
 test/suites/external_auth.sh | 10 +++++-----
 9 files changed, 26 insertions(+), 26 deletions(-)

diff --git a/client/connection.go b/client/connection.go
index a2ebbdc5f6..c0d621c6ab 100644
--- a/client/connection.go
+++ b/client/connection.go
@@ -173,7 +173,7 @@ func httpsLXD(url string, args *ConnectionArgs) (ContainerServer, error) {
 		httpUserAgent:    args.UserAgent,
 		bakeryInteractor: args.AuthInteractor,
 	}
-	if args.AuthType == "macaroons" {
+	if args.AuthType == "candid" {
 		server.RequireAuthenticated(true)
 	}
 
@@ -188,7 +188,7 @@ func httpsLXD(url string, args *ConnectionArgs) (ContainerServer, error) {
 	}
 
 	server.http = httpClient
-	if args.AuthType == "macaroons" {
+	if args.AuthType == "candid" {
 		server.setupBakeryClient()
 	}
 
diff --git a/doc/security.md b/doc/security.md
index c9d9199761..0c31ac1817 100644
--- a/doc/security.md
+++ b/doc/security.md
@@ -78,15 +78,15 @@ pre-generated files.
 
 After this is done, restarting the server will have it run in PKI mode.
 
-# Adding a remote with Macaroon-based authentication
-When LXD is configured with Macaroon-based authentication, it will request that
-clients trying to authenticating with it get a Discharge token from the
-authentication server specified by the `core.macaroon.endpoint` setting.
+# Adding a remote with Candid
+When LXD is configured with Candid, it will request that clients trying to
+authenticating with it get a Discharge token from the authentication server
+specified by the `core.candid.endpoint` setting.
 
 The authentication server certificate needs to be trusted by the LXD server.
 
 To add a remote pointing to a LXD configured with Macaroon auth, run `lxc
-remote add REMOTE ENDPOINT --auth-type=macaroons`.  The client will prompt for
+remote add REMOTE ENDPOINT --auth-type=candid`.  The client will prompt for
 the credentials required by the authentication server in order to verify the
 user. If the authentication is successful, it will connect to the LXD server
 presenting the token received from the authentication server.  The LXD server
diff --git a/doc/server.md b/doc/server.md
index d71ceccaf1..94d1f13b9b 100644
--- a/doc/server.md
+++ b/doc/server.md
@@ -17,7 +17,7 @@ core.https\_allowed\_credentials| boolean   | -         | -
 core.https\_allowed\_headers    | string    | -         | -                        | Access-Control-Allow-Headers http header value
 core.https\_allowed\_methods    | string    | -         | -                        | Access-Control-Allow-Methods http header value
 core.https\_allowed\_origin     | string    | -         | -                        | Access-Control-Allow-Origin http header value
-core.macaroon.endpoint          | string    | -         | macaroon\_authentication | URL of the the external authentication endpoint using Macaroons
+core.candid.endpoint            | string    | -         | macaroon\_authentication | URL of the the external authentication endpoint using Candid
 core.proxy\_https               | string    | -         | -                        | https proxy to use, if any (falls back to HTTPS\_PROXY environment variable)
 core.proxy\_http                | string    | -         | -                        | http proxy to use, if any (falls back to HTTP\_PROXY environment variable)
 core.proxy\_ignore\_hosts       | string    | -         | -                        | hosts which don't need the proxy for use (similar format to NO\_PROXY, e.g. 1.2.3.4,1.2.3.5, falls back to NO\_PROXY environment variable)
diff --git a/lxc/remote.go b/lxc/remote.go
index 9f3748771f..cb02190333 100644
--- a/lxc/remote.go
+++ b/lxc/remote.go
@@ -91,7 +91,7 @@ func (c *cmdRemoteAdd) Command() *cobra.Command {
 	cmd.Flags().BoolVar(&c.flagAcceptCert, "accept-certificate", false, i18n.G("Accept certificate"))
 	cmd.Flags().StringVar(&c.flagPassword, "password", "", i18n.G("Remote admin password")+"``")
 	cmd.Flags().StringVar(&c.flagProtocol, "protocol", "", i18n.G("Server protocol (lxd or simplestreams)")+"``")
-	cmd.Flags().StringVar(&c.flagAuthType, "auth-type", "", i18n.G("Server authentication type (tls or macaroons)")+"``")
+	cmd.Flags().StringVar(&c.flagAuthType, "auth-type", "", i18n.G("Server authentication type (tls or candid)")+"``")
 	cmd.Flags().BoolVar(&c.flagPublic, "public", false, i18n.G("Public image server"))
 
 	return cmd
@@ -297,7 +297,7 @@ func (c *cmdRemoteAdd) Run(cmd *cobra.Command, args []string) error {
 		return conf.SaveConfig(c.global.confPath)
 	}
 
-	if c.flagAuthType == "macaroons" {
+	if c.flagAuthType == "candid" {
 		d.(lxd.ContainerServer).RequireAuthenticated(false)
 	}
 
diff --git a/lxd/api_1.0.go b/lxd/api_1.0.go
index ca0f062479..b38468a946 100644
--- a/lxd/api_1.0.go
+++ b/lxd/api_1.0.go
@@ -85,8 +85,8 @@ func api10Get(d *Daemon, r *http.Request) Response {
 		if err != nil {
 			return err
 		}
-		if config.MacaroonEndpoint() != "" {
-			authMethods = append(authMethods, "macaroons")
+		if config.CandidEndpoint() != "" {
+			authMethods = append(authMethods, "candid")
 		}
 		return nil
 	})
@@ -378,7 +378,7 @@ func doApi10UpdateTriggers(d *Daemon, nodeChanged, clusterChanged map[string]str
 			fallthrough
 		case "maas.api.key":
 			maasChanged = true
-		case "core.macaroon.endpoint":
+		case "core.candid.endpoint":
 			err := d.setupExternalAuthentication(value)
 			if err != nil {
 				return err
diff --git a/lxd/cluster/config.go b/lxd/cluster/config.go
index 19eb4d855e..6cb8f9f735 100644
--- a/lxd/cluster/config.go
+++ b/lxd/cluster/config.go
@@ -64,10 +64,10 @@ func (c *Config) TrustPassword() string {
 	return c.m.GetString("core.trust_password")
 }
 
-// MacaroonEndpoint returns the address of the macaroon endpoint to use for
+// CandidEndpoint returns the address of the Candid endpoint to use for
 // authentication, if any.
-func (c *Config) MacaroonEndpoint() string {
-	return c.m.GetString("core.macaroon.endpoint")
+func (c *Config) CandidEndpoint() string {
+	return c.m.GetString("core.candid.endpoint")
 }
 
 // AutoUpdateInterval returns the configured images auto update interval.
@@ -210,7 +210,7 @@ var ConfigSchema = config.Schema{
 	"core.proxy_https":               {},
 	"core.proxy_ignore_hosts":        {},
 	"core.trust_password":            {Hidden: true, Setter: passwordSetter},
-	"core.macaroon.endpoint":         {},
+	"core.candid.endpoint":           {},
 	"images.auto_update_cached":      {Type: config.Bool, Default: "true"},
 	"images.auto_update_interval":    {Type: config.Int64, Default: "6"},
 	"images.compression_algorithm":   {Default: "gzip", Validator: validateCompression},
diff --git a/lxd/daemon.go b/lxd/daemon.go
index 354c493033..4197a665a4 100644
--- a/lxd/daemon.go
+++ b/lxd/daemon.go
@@ -574,7 +574,7 @@ func (d *Daemon) init() error {
 	d.tasks.Add(expireLogsTask(d.State()))
 
 	/* Setup the proxy handler, external authentication and MAAS */
-	macaroonEndpoint := ""
+	candidEndpoint := ""
 	maasAPIURL := ""
 	maasAPIKey := ""
 	maasMachine := ""
@@ -602,7 +602,7 @@ func (d *Daemon) init() error {
 		d.proxy = shared.ProxyFromConfig(
 			config.ProxyHTTPS(), config.ProxyHTTP(), config.ProxyIgnoreHosts(),
 		)
-		macaroonEndpoint = config.MacaroonEndpoint()
+		candidEndpoint = config.CandidEndpoint()
 		maasAPIURL, maasAPIKey = config.MAASController()
 		return nil
 	})
@@ -610,7 +610,7 @@ func (d *Daemon) init() error {
 		return err
 	}
 
-	err = d.setupExternalAuthentication(macaroonEndpoint)
+	err = d.setupExternalAuthentication(candidEndpoint)
 	if err != nil {
 		return err
 	}
diff --git a/scripts/bash/lxd-client b/scripts/bash/lxd-client
index 19eb19ef92..491c11da70 100644
--- a/scripts/bash/lxd-client
+++ b/scripts/bash/lxd-client
@@ -66,7 +66,7 @@ _have lxc && {
 
     global_keys="core.https_address core.https_allowed_credentials \
       core.https_allowed_headers core.https_allowed_methods \
-      core.https_allowed_origin core.macaroon.endpoint core.proxy_https \
+      core.https_allowed_origin core.candid.endpoint core.proxy_https \
       core.proxy_http core.proxy_ignore_hosts core.trust_password \
       core.debug_address cluster.offline_threshold \
       images.auto_update_cached images.auto_update_interval \
diff --git a/test/suites/external_auth.sh b/test/suites/external_auth.sh
index 999927e453..553c916672 100644
--- a/test/suites/external_auth.sh
+++ b/test/suites/external_auth.sh
@@ -6,27 +6,27 @@ test_macaroon_auth() {
 
     ensure_has_localhost_remote "$LXD_ADDR"
 
-    lxc config set core.macaroon.endpoint "$identity_endpoint"
+    lxc config set core.candid.endpoint "$identity_endpoint"
 
     # invalid credentials make the remote add fail
     # shellcheck disable=SC2039
-    ! cat <<EOF | lxc remote add macaroon-remote "https://$LXD_ADDR" --auth-type macaroons --accept-certificate
+    ! cat <<EOF | lxc remote add macaroon-remote "https://$LXD_ADDR" --auth-type candid --accept-certificate
 wrong-user
 wrong-pass
 EOF
 
     # valid credentials work
     # shellcheck disable=SC2039
-    cat <<EOF | lxc remote add macaroon-remote "https://$LXD_ADDR" --auth-type macaroons --accept-certificate
+    cat <<EOF | lxc remote add macaroon-remote "https://$LXD_ADDR" --auth-type candid --accept-certificate
 user1
 pass1
 EOF
 
     # run a lxc command through the new remote
-    lxc config show macaroon-remote: | grep -q core.macaroon.endpoint
+    lxc config show macaroon-remote: | grep -q core.candid.endpoint
 
     # cleanup
-    lxc config unset core.macaroon.endpoint
+    lxc config unset core.candid.endpoint
     lxc config unset core.https_address
     lxc remote remove macaroon-remote
 }

From 7f4e099e311dc8bc99c2f88c001b1a7794f13cec Mon Sep 17 00:00:00 2001
From: Thomas Hipp <thomas.hipp at canonical.com>
Date: Wed, 8 Aug 2018 17:18:55 +0200
Subject: [PATCH 2/2] auth: Support URL based auth

Signed-off-by: Thomas Hipp <thomas.hipp at canonical.com>
---
 client/connection.go | 2 +-
 client/lxd.go        | 7 +++++--
 lxc/config/config.go | 4 ++--
 lxc/main.go          | 6 +++++-
 4 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/client/connection.go b/client/connection.go
index c0d621c6ab..b300cae198 100644
--- a/client/connection.go
+++ b/client/connection.go
@@ -32,7 +32,7 @@ type ConnectionArgs struct {
 	AuthType string
 
 	// Authentication interactor
-	AuthInteractor httpbakery.Interactor
+	AuthInteractor []httpbakery.Interactor
 
 	// Custom proxy
 	Proxy func(*http.Request) (*url.URL, error)
diff --git a/client/lxd.go b/client/lxd.go
index 8bba043ad1..1cc494670b 100644
--- a/client/lxd.go
+++ b/client/lxd.go
@@ -34,7 +34,7 @@ type ProtocolLXD struct {
 	httpUserAgent   string
 
 	bakeryClient         *httpbakery.Client
-	bakeryInteractor     httpbakery.Interactor
+	bakeryInteractor     []httpbakery.Interactor
 	requireAuthenticated bool
 
 	clusterTarget string
@@ -365,7 +365,10 @@ func (r *ProtocolLXD) websocket(path string) (*websocket.Conn, error) {
 func (r *ProtocolLXD) setupBakeryClient() {
 	r.bakeryClient = httpbakery.NewClient()
 	r.bakeryClient.Client = r.http
+	//r.bakeryClient.AddInteractor(httpbakery.WebBrowserInteractor{})
 	if r.bakeryInteractor != nil {
-		r.bakeryClient.AddInteractor(r.bakeryInteractor)
+		for _, interactor := range r.bakeryInteractor {
+			r.bakeryClient.AddInteractor(interactor)
+		}
 	}
 }
diff --git a/lxc/config/config.go b/lxc/config/config.go
index f6e9a3fe07..7b51cf6ba0 100644
--- a/lxc/config/config.go
+++ b/lxc/config/config.go
@@ -27,7 +27,7 @@ type Config struct {
 	// The UserAgent to pass for all queries
 	UserAgent string `yaml:"-"`
 
-	authInteractor httpbakery.Interactor
+	authInteractor []httpbakery.Interactor
 
 	cookiejar *cookiejar.Jar
 }
@@ -46,7 +46,7 @@ func (c *Config) ServerCertPath(remote string) string {
 }
 
 // SetAuthInteractor sets the interactor for macaroon-based authorization
-func (c *Config) SetAuthInteractor(interactor httpbakery.Interactor) {
+func (c *Config) SetAuthInteractor(interactor []httpbakery.Interactor) {
 	c.authInteractor = interactor
 }
 
diff --git a/lxc/main.go b/lxc/main.go
index 605881ff7f..59cbe52ad0 100644
--- a/lxc/main.go
+++ b/lxc/main.go
@@ -8,6 +8,7 @@ import (
 	"path/filepath"
 
 	"github.com/spf13/cobra"
+	"gopkg.in/macaroon-bakery.v2/httpbakery"
 	"gopkg.in/macaroon-bakery.v2/httpbakery/form"
 
 	"github.com/lxc/lxd/client"
@@ -304,7 +305,10 @@ func (c *cmdGlobal) PreRun(cmd *cobra.Command, args []string) error {
 	// Only setup macaroons if a config path exists (so the jar can be saved)
 	if shared.PathExists(c.confPath) {
 		// Add interactor for external authentication
-		c.conf.SetAuthInteractor(form.Interactor{Filler: schemaform.IOFiller{}})
+		c.conf.SetAuthInteractor([]httpbakery.Interactor{
+			form.Interactor{Filler: schemaform.IOFiller{}},
+			httpbakery.WebBrowserInteractor{},
+		})
 	}
 
 	// Set the user agent


More information about the lxc-devel mailing list