Browse Source

etcdserver: replace "hostWhitelist" with "AccessController"

Signed-off-by: Gyuho Lee <gyuhox@gmail.com>
Gyuho Lee 7 years ago
parent
commit
29db853317
2 changed files with 76 additions and 21 deletions
  1. 11 21
      etcdserver/server.go
  2. 65 0
      etcdserver/server_access_control.go

+ 11 - 21
etcdserver/server.go

@@ -253,7 +253,7 @@ type EtcdServer struct {
 	leadTimeMu      sync.RWMutex
 	leadElectedTime time.Time
 
-	hostWhitelist map[string]struct{}
+	*AccessController
 }
 
 // NewServer creates a new EtcdServer from the supplied configuration. The
@@ -434,16 +434,16 @@ func NewServer(cfg ServerConfig) (srv *EtcdServer, err error) {
 				storage:     NewStorage(w, ss),
 			},
 		),
-		id:            id,
-		attributes:    membership.Attributes{Name: cfg.Name, ClientURLs: cfg.ClientURLs.StringSlice()},
-		cluster:       cl,
-		stats:         sstats,
-		lstats:        lstats,
-		SyncTicker:    time.NewTicker(500 * time.Millisecond),
-		peerRt:        prt,
-		reqIDGen:      idutil.NewGenerator(uint16(id), time.Now()),
-		forceVersionC: make(chan struct{}),
-		hostWhitelist: cfg.HostWhitelist,
+		id:               id,
+		attributes:       membership.Attributes{Name: cfg.Name, ClientURLs: cfg.ClientURLs.StringSlice()},
+		cluster:          cl,
+		stats:            sstats,
+		lstats:           lstats,
+		SyncTicker:       time.NewTicker(500 * time.Millisecond),
+		peerRt:           prt,
+		reqIDGen:         idutil.NewGenerator(uint16(id), time.Now()),
+		forceVersionC:    make(chan struct{}),
+		AccessController: &AccessController{CORS: cfg.CORS, HostWhitelist: cfg.HostWhitelist},
 	}
 
 	srv.applyV2 = &applierV2store{store: srv.v2store, cluster: srv.cluster}
@@ -673,16 +673,6 @@ func (s *EtcdServer) ReportSnapshot(id uint64, status raft.SnapshotStatus) {
 	s.r.ReportSnapshot(id, status)
 }
 
-// IsHostWhitelisted returns true if the host is whitelisted.
-// If whitelist is empty, allow all.
-func (s *EtcdServer) IsHostWhitelisted(host string) bool {
-	if len(s.hostWhitelist) == 0 { // allow all
-		return true
-	}
-	_, ok := s.hostWhitelist[host]
-	return ok
-}
-
 type etcdProgress struct {
 	confState raftpb.ConfState
 	snapi     uint64

+ 65 - 0
etcdserver/server_access_control.go

@@ -0,0 +1,65 @@
+// Copyright 2018 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package etcdserver
+
+import "sync"
+
+// AccessController controls etcd server HTTP request access.
+type AccessController struct {
+	corsMu          sync.RWMutex
+	CORS            map[string]struct{}
+	hostWhitelistMu sync.RWMutex
+	HostWhitelist   map[string]struct{}
+}
+
+// NewAccessController returns a new "AccessController" with default "*" values.
+func NewAccessController() *AccessController {
+	return &AccessController{
+		CORS:          map[string]struct{}{"*": {}},
+		HostWhitelist: map[string]struct{}{"*": {}},
+	}
+}
+
+// OriginAllowed determines whether the server will allow a given CORS origin.
+// If CORS is empty, allow all.
+func (ac *AccessController) OriginAllowed(origin string) bool {
+	ac.corsMu.RLock()
+	defer ac.corsMu.RUnlock()
+	if len(ac.CORS) == 0 { // allow all
+		return true
+	}
+	_, ok := ac.CORS["*"]
+	if ok {
+		return true
+	}
+	_, ok = ac.CORS[origin]
+	return ok
+}
+
+// IsHostWhitelisted returns true if the host is whitelisted.
+// If whitelist is empty, allow all.
+func (ac *AccessController) IsHostWhitelisted(host string) bool {
+	ac.hostWhitelistMu.RLock()
+	defer ac.hostWhitelistMu.RUnlock()
+	if len(ac.HostWhitelist) == 0 { // allow all
+		return true
+	}
+	_, ok := ac.HostWhitelist["*"]
+	if ok {
+		return true
+	}
+	_, ok = ac.HostWhitelist[host]
+	return ok
+}