You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ac...@apache.org on 2018/03/01 19:49:53 UTC
qpid-proton git commit: PROTON-1696 [go] reliable SASL config and
test initialization
Repository: qpid-proton
Updated Branches:
refs/heads/master 1b9c09582 -> 817609a54
PROTON-1696 [go] reliable SASL config and test initialization
- lock access to global SASL config variables to ensure no races.
- panic if SASL config is called too late (lost config)
- do SASL init before starting tests to avoid ordering and parallel test
problems with on-demand initialization.
Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/817609a5
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/817609a5
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/817609a5
Branch: refs/heads/master
Commit: 817609a5476aea7219e432a04962e8ba194a8ad0
Parents: 1b9c095
Author: Alan Conway <ac...@redhat.com>
Authored: Thu Mar 1 14:11:23 2018 -0500
Committer: Alan Conway <ac...@redhat.com>
Committed: Thu Mar 1 14:48:27 2018 -0500
----------------------------------------------------------------------
.../src/qpid.apache.org/electron/auth_test.go | 92 +++++++++++---------
.../src/qpid.apache.org/electron/connection.go | 65 +++++++++-----
2 files changed, 92 insertions(+), 65 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/817609a5/proton-c/bindings/go/src/qpid.apache.org/electron/auth_test.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/electron/auth_test.go b/proton-c/bindings/go/src/qpid.apache.org/electron/auth_test.go
index 9fa9fa2..77b033c 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/electron/auth_test.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/electron/auth_test.go
@@ -48,7 +48,6 @@ func testAuthClientServer(t *testing.T, copts []ConnectionOption, sopts []Connec
}
func TestAuthAnonymous(t *testing.T) {
- configureSASL()
got, err := testAuthClientServer(t,
[]ConnectionOption{User("fred"), VirtualHost("vhost"), SASLAllowInsecure(true)},
[]ConnectionOption{SASLAllowedMechs("ANONYMOUS"), SASLAllowInsecure(true)})
@@ -57,10 +56,7 @@ func TestAuthAnonymous(t *testing.T) {
}
func TestAuthPlain(t *testing.T) {
- if !SASLExtended() {
- t.Skip()
- }
- fatalIf(t, configureSASL())
+ extendedSASL.startTest(t)
got, err := testAuthClientServer(t,
[]ConnectionOption{SASLAllowInsecure(true), SASLAllowedMechs("PLAIN"), User("fred@proton"), Password([]byte("xxx"))},
[]ConnectionOption{SASLAllowInsecure(true), SASLAllowedMechs("PLAIN")})
@@ -69,10 +65,7 @@ func TestAuthPlain(t *testing.T) {
}
func TestAuthBadPass(t *testing.T) {
- if !SASLExtended() {
- t.Skip()
- }
- fatalIf(t, configureSASL())
+ extendedSASL.startTest(t)
_, err := testAuthClientServer(t,
[]ConnectionOption{SASLAllowInsecure(true), SASLAllowedMechs("PLAIN"), User("fred@proton"), Password([]byte("yyy"))},
[]ConnectionOption{SASLAllowInsecure(true), SASLAllowedMechs("PLAIN")})
@@ -82,10 +75,7 @@ func TestAuthBadPass(t *testing.T) {
}
func TestAuthBadUser(t *testing.T) {
- if !SASLExtended() {
- t.Skip()
- }
- fatalIf(t, configureSASL())
+ extendedSASL.startTest(t)
_, err := testAuthClientServer(t,
[]ConnectionOption{SASLAllowInsecure(true), SASLAllowedMechs("PLAIN"), User("foo@bar"), Password([]byte("yyy"))},
[]ConnectionOption{SASLAllowInsecure(true), SASLAllowedMechs("PLAIN")})
@@ -94,44 +84,60 @@ func TestAuthBadUser(t *testing.T) {
}
}
-var confDir string
-var confErr error
+type extendedSASLState struct {
+ err error
+ dir string
+}
-func configureSASL() error {
- if confDir != "" || confErr != nil {
- return confErr
- }
- confDir, confErr = ioutil.TempDir("", "")
- if confErr != nil {
- return confErr
+func (s *extendedSASLState) setup() {
+ if SASLExtended() {
+ if s.dir, s.err = ioutil.TempDir("", ""); s.err == nil {
+ GlobalSASLConfigDir(s.dir)
+ GlobalSASLConfigName("test")
+ conf := filepath.Join(s.dir, "test.conf")
+ db := filepath.Join(s.dir, "proton.sasldb")
+ saslpasswd := os.Getenv("SASLPASSWD")
+ if saslpasswd == "" {
+ saslpasswd = "saslpasswd2"
+ }
+ cmd := exec.Command(saslpasswd, "-c", "-p", "-f", db, "-u", "proton", "fred")
+ cmd.Stdin = strings.NewReader("xxx") // Password
+ if _, s.err = cmd.CombinedOutput(); s.err == nil {
+ confStr := fmt.Sprintf(`
+sasldb_path: %s
+mech_list: EXTERNAL DIGEST-MD5 SCRAM-SHA-1 CRAM-MD5 PLAIN ANONYMOUS
+`, db)
+ s.err = ioutil.WriteFile(conf, []byte(confStr), os.ModePerm)
+ }
+ }
}
+ // Note we don't do anything with s.err now, tests that need the
+ // extended SASL config will fail if s.err != nil. If no such tests
+ // are run then it is not an error that we couldn't set it up.
+}
- GlobalSASLConfigDir(confDir)
- GlobalSASLConfigName("test")
- conf := filepath.Join(confDir, "test.conf")
-
- db := filepath.Join(confDir, "proton.sasldb")
- saslpasswd := os.Getenv("SASLPASSWD");
- if saslpasswd == "" {
- saslpasswd = "saslpasswd2"
- }
- cmd := exec.Command(saslpasswd, "-c", "-p", "-f", db, "-u", "proton", "fred")
- cmd.Stdin = strings.NewReader("xxx") // Password
- if out, err := cmd.CombinedOutput(); err != nil {
- confErr = fmt.Errorf("saslpasswd2 failed: %s\n%s", err, out)
- return confErr
+func (s extendedSASLState) teardown() {
+ if s.dir != "" {
+ _ = os.RemoveAll(s.dir)
}
- confStr := "sasldb_path: " + db + "\nmech_list: EXTERNAL DIGEST-MD5 SCRAM-SHA-1 CRAM-MD5 PLAIN ANONYMOUS\n"
- if err := ioutil.WriteFile(conf, []byte(confStr), os.ModePerm); err != nil {
- confErr = fmt.Errorf("write conf file %s failed: %s", conf, err)
+}
+
+func (s extendedSASLState) startTest(t *testing.T) {
+ if SASLExtended() {
+ fatalIf(t, extendedSASL.err)
+ } else {
+ t.Skip()
}
- return confErr
}
+var extendedSASL extendedSASLState
+
func TestMain(m *testing.M) {
+ // Do global SASL setup/teardown in main.
+ // Doing it on-demand makes the tests fragile to parallel test runs and
+ // changes in test ordering.
+ extendedSASL.setup()
status := m.Run()
- if confDir != "" {
- _ = os.RemoveAll(confDir)
- }
+ extendedSASL.teardown()
os.Exit(status)
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/817609a5/proton-c/bindings/go/src/qpid.apache.org/electron/connection.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/electron/connection.go b/proton-c/bindings/go/src/qpid.apache.org/electron/connection.go
index 731e64d..9c0ef31 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/electron/connection.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/electron/connection.go
@@ -196,8 +196,7 @@ func NewConnection(conn net.Conn, opts ...ConnectionOption) (*connection, error)
c.container = NewContainer("").(*container)
}
c.pConnection.SetContainer(c.container.Id())
- globalSASLInit(c.engine)
-
+ saslConfig.setup(c.engine)
c.endpoint.init(c.engine.String())
go c.run()
return c, nil
@@ -356,13 +355,52 @@ func Heartbeat(delay time.Duration) ConnectionOption {
return func(c *connection) { c.engine.Transport().SetIdleTimeout(2 * delay) }
}
+type saslConfigState struct {
+ lock sync.Mutex
+ name string
+ dir string
+ initialized bool
+}
+
+func (s *saslConfigState) set(target *string, value string) {
+ s.lock.Lock()
+ defer s.lock.Unlock()
+ if s.initialized {
+ panic("SASL configuration cannot be changed after a Connection has been created")
+ }
+ *target = value
+}
+
+// Apply the global SASL configuration the first time a proton.Engine needs it
+//
+// TODO aconway 2016-09-15: Current pn_sasl C impl config is broken, so all we
+// can realistically offer is global configuration. Later if/when the pn_sasl C
+// impl is fixed we can offer per connection over-rides.
+func (s *saslConfigState) setup(eng *proton.Engine) {
+ s.lock.Lock()
+ defer s.lock.Unlock()
+ if !s.initialized {
+ s.initialized = true
+ sasl := eng.Transport().SASL()
+ if s.name != "" {
+ sasl.ConfigName(saslConfig.name)
+ }
+ if s.dir != "" {
+ sasl.ConfigPath(saslConfig.dir)
+ }
+ }
+}
+
+var saslConfig saslConfigState
+
// GlobalSASLConfigDir sets the SASL configuration directory for every
// Connection created in this process. If not called, the default is determined
// by your SASL installation.
//
// You can set SASLAllowInsecure and SASLAllowedMechs on individual connections.
//
-func GlobalSASLConfigDir(dir string) { globalSASLConfigDir = dir }
+// Must be called at most once, before any connections are created.
+func GlobalSASLConfigDir(dir string) { saslConfig.set(&saslConfig.dir, dir) }
// GlobalSASLConfigName sets the SASL configuration name for every Connection
// created in this process. If not called the default is "proton-server".
@@ -372,7 +410,8 @@ func GlobalSASLConfigDir(dir string) { globalSASLConfigDir = dir }
//
// You can set SASLAllowInsecure and SASLAllowedMechs on individual connections.
//
-func GlobalSASLConfigName(dir string) { globalSASLConfigName = dir }
+// Must be called at most once, before any connections are created.
+func GlobalSASLConfigName(name string) { saslConfig.set(&saslConfig.name, name) }
// Do we support extended SASL negotiation?
// All implementations of Proton support ANONYMOUS and EXTERNAL on both
@@ -382,24 +421,6 @@ func GlobalSASLConfigName(dir string) { globalSASLConfigName = dir }
// to support other mechanisms beyond these basic ones.
func SASLExtended() bool { return proton.SASLExtended() }
-var (
- globalSASLConfigName string
- globalSASLConfigDir string
-)
-
-// TODO aconway 2016-09-15: Current pn_sasl C impl config is broken, so all we
-// can realistically offer is global configuration. Later if/when the pn_sasl C
-// impl is fixed we can offer per connection over-rides.
-func globalSASLInit(eng *proton.Engine) {
- sasl := eng.Transport().SASL()
- if globalSASLConfigName != "" {
- sasl.ConfigName(globalSASLConfigName)
- }
- if globalSASLConfigDir != "" {
- sasl.ConfigPath(globalSASLConfigDir)
- }
-}
-
// Dial is shorthand for using net.Dial() then NewConnection()
// See net.Dial() for the meaning of the network, address arguments.
func Dial(network, address string, opts ...ConnectionOption) (c Connection, err error) {
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org