go.etcd.io/etcd@v3.3.27+incompatible/etcdserver/auth/auth_requests.go (about) 1 // Copyright 2015 The etcd Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package auth 16 17 import ( 18 "context" 19 "encoding/json" 20 "path" 21 22 etcderr "github.com/coreos/etcd/error" 23 "github.com/coreos/etcd/etcdserver" 24 "github.com/coreos/etcd/etcdserver/etcdserverpb" 25 ) 26 27 func (s *store) ensureAuthDirectories() error { 28 if s.ensuredOnce { 29 return nil 30 } 31 for _, res := range []string{StorePermsPrefix, StorePermsPrefix + "/users/", StorePermsPrefix + "/roles/"} { 32 ctx, cancel := context.WithTimeout(context.Background(), s.timeout) 33 defer cancel() 34 pe := false 35 rr := etcdserverpb.Request{ 36 Method: "PUT", 37 Path: res, 38 Dir: true, 39 PrevExist: &pe, 40 } 41 _, err := s.server.Do(ctx, rr) 42 if err != nil { 43 if e, ok := err.(*etcderr.Error); ok { 44 if e.ErrorCode == etcderr.EcodeNodeExist { 45 continue 46 } 47 } 48 plog.Errorf("failed to create auth directories in the store (%v)", err) 49 return err 50 } 51 } 52 ctx, cancel := context.WithTimeout(context.Background(), s.timeout) 53 defer cancel() 54 pe := false 55 rr := etcdserverpb.Request{ 56 Method: "PUT", 57 Path: StorePermsPrefix + "/enabled", 58 Val: "false", 59 PrevExist: &pe, 60 } 61 _, err := s.server.Do(ctx, rr) 62 if err != nil { 63 if e, ok := err.(*etcderr.Error); ok { 64 if e.ErrorCode == etcderr.EcodeNodeExist { 65 s.ensuredOnce = true 66 return nil 67 } 68 } 69 return err 70 } 71 s.ensuredOnce = true 72 return nil 73 } 74 75 func (s *store) enableAuth() error { 76 _, err := s.updateResource("/enabled", true) 77 return err 78 } 79 func (s *store) disableAuth() error { 80 _, err := s.updateResource("/enabled", false) 81 return err 82 } 83 84 func (s *store) detectAuth() bool { 85 if s.server == nil { 86 return false 87 } 88 value, err := s.requestResource("/enabled", false, false) 89 if err != nil { 90 if e, ok := err.(*etcderr.Error); ok { 91 if e.ErrorCode == etcderr.EcodeKeyNotFound { 92 return false 93 } 94 } 95 plog.Errorf("failed to detect auth settings (%s)", err) 96 return false 97 } 98 99 var u bool 100 err = json.Unmarshal([]byte(*value.Event.Node.Value), &u) 101 if err != nil { 102 plog.Errorf("internal bookkeeping value for enabled isn't valid JSON (%v)", err) 103 return false 104 } 105 return u 106 } 107 108 func (s *store) requestResource(res string, dir, quorum bool) (etcdserver.Response, error) { 109 ctx, cancel := context.WithTimeout(context.Background(), s.timeout) 110 defer cancel() 111 p := path.Join(StorePermsPrefix, res) 112 method := "GET" 113 if quorum { 114 method = "QGET" 115 } 116 rr := etcdserverpb.Request{ 117 Method: method, 118 Path: p, 119 Dir: dir, 120 } 121 return s.server.Do(ctx, rr) 122 } 123 124 func (s *store) updateResource(res string, value interface{}) (etcdserver.Response, error) { 125 return s.setResource(res, value, true) 126 } 127 func (s *store) createResource(res string, value interface{}) (etcdserver.Response, error) { 128 return s.setResource(res, value, false) 129 } 130 func (s *store) setResource(res string, value interface{}, prevexist bool) (etcdserver.Response, error) { 131 err := s.ensureAuthDirectories() 132 if err != nil { 133 return etcdserver.Response{}, err 134 } 135 ctx, cancel := context.WithTimeout(context.Background(), s.timeout) 136 defer cancel() 137 data, err := json.Marshal(value) 138 if err != nil { 139 return etcdserver.Response{}, err 140 } 141 p := path.Join(StorePermsPrefix, res) 142 rr := etcdserverpb.Request{ 143 Method: "PUT", 144 Path: p, 145 Val: string(data), 146 PrevExist: &prevexist, 147 } 148 return s.server.Do(ctx, rr) 149 } 150 151 func (s *store) deleteResource(res string) (etcdserver.Response, error) { 152 err := s.ensureAuthDirectories() 153 if err != nil { 154 return etcdserver.Response{}, err 155 } 156 ctx, cancel := context.WithTimeout(context.Background(), s.timeout) 157 defer cancel() 158 pex := true 159 p := path.Join(StorePermsPrefix, res) 160 rr := etcdserverpb.Request{ 161 Method: "DELETE", 162 Path: p, 163 PrevExist: &pex, 164 } 165 return s.server.Do(ctx, rr) 166 }