Browse code

authz: eliminate race during plugin removal from middleware

Also, this removes the use of a questionable golang range feature which
corrects for mutation of a slice during iteration over that slice. This
makes the filter operation easier to read and reason about.

Signed-off-by: David Sheets <dsheets@docker.com>

David Sheets authored on 2017/06/13 19:52:04
Showing 2 changed files
... ...
@@ -46,6 +46,19 @@ func (m *Middleware) SetPlugins(names []string) {
46 46
 	m.mu.Unlock()
47 47
 }
48 48
 
49
+// RemovePlugin removes a single plugin from this authz middleware chain
50
+func (m *Middleware) RemovePlugin(name string) {
51
+	m.mu.Lock()
52
+	defer m.mu.Unlock()
53
+	plugins := m.plugins[:0]
54
+	for _, authPlugin := range m.plugins {
55
+		if authPlugin.Name() != name {
56
+			plugins = append(plugins, authPlugin)
57
+		}
58
+	}
59
+	m.plugins = plugins
60
+}
61
+
49 62
 // WrapHandler returns a new handler function wrapping the previous one in the request chain.
50 63
 func (m *Middleware) WrapHandler(handler func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error) func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
51 64
 	return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
... ...
@@ -60,14 +60,7 @@ func (pm *Manager) Disable(refOrID string, config *types.PluginDisableConfig) er
60 60
 
61 61
 	for _, typ := range p.GetTypes() {
62 62
 		if typ.Capability == authorization.AuthZApiImplements {
63
-			authzList := pm.config.AuthzMiddleware.GetAuthzPlugins()
64
-			for i, authPlugin := range authzList {
65
-				if authPlugin.Name() == p.Name() {
66
-					// Remove plugin from authzmiddleware chain
67
-					authzList = append(authzList[:i], authzList[i+1:]...)
68
-					pm.config.AuthzMiddleware.SetAuthzPlugins(authzList)
69
-				}
70
-			}
63
+			pm.config.AuthzMiddleware.RemovePlugin(p.Name())
71 64
 		}
72 65
 	}
73 66