github.com/gravitational/teleport/api@v0.0.0-20240507183017-3110591cbafc/types/lock.go (about) 1 /* 2 Copyright 2021 Gravitational, Inc. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package types 18 19 import ( 20 "strings" 21 "time" 22 23 "github.com/gogo/protobuf/proto" 24 "github.com/gravitational/trace" 25 26 "github.com/gravitational/teleport/api/utils" 27 ) 28 29 // Lock configures locking out of a particular access vector. 30 type Lock interface { 31 Resource 32 ResourceWithOrigin 33 ResourceWithLabels 34 35 // Target returns the lock's target. 36 Target() LockTarget 37 // SetTarget sets the lock's target. 38 SetTarget(LockTarget) 39 40 // Message returns the message displayed to locked-out users. 41 Message() string 42 // SetMessage sets the lock's user message. 43 SetMessage(string) 44 45 // LockExpiry returns when the lock ceases to be in force. 46 LockExpiry() *time.Time 47 // SetLockExpiry sets the lock's expiry. 48 SetLockExpiry(*time.Time) 49 50 // CreatedAt returns the time the lock was created. 51 CreatedAt() time.Time 52 // SetCreatedAt sets the lock's created time. 53 SetCreatedAt(time.Time) 54 // CreatedBy returns the user that created the lock. 55 CreatedBy() string 56 // SetCreatedBy sets the lock's creator. 57 SetCreatedBy(string) 58 59 // IsInForce returns whether the lock is in force at a particular time. 60 IsInForce(time.Time) bool 61 } 62 63 // NewLock is a convenience method to create a Lock resource. 64 func NewLock(name string, spec LockSpecV2) (Lock, error) { 65 lock := &LockV2{ 66 Metadata: Metadata{ 67 Name: name, 68 }, 69 Spec: spec, 70 } 71 if err := lock.CheckAndSetDefaults(); err != nil { 72 return nil, trace.Wrap(err) 73 } 74 return lock, nil 75 } 76 77 // GetVersion returns resource version. 78 func (c *LockV2) GetVersion() string { 79 return c.Version 80 } 81 82 // GetName returns the name of the resource. 83 func (c *LockV2) GetName() string { 84 return c.Metadata.Name 85 } 86 87 // SetName sets the name of the resource. 88 func (c *LockV2) SetName(e string) { 89 c.Metadata.Name = e 90 } 91 92 // SetExpiry sets expiry time for the object. 93 func (c *LockV2) SetExpiry(expires time.Time) { 94 c.Metadata.SetExpiry(expires) 95 } 96 97 // Expiry returns object expiry setting. 98 func (c *LockV2) Expiry() time.Time { 99 return c.Metadata.Expiry() 100 } 101 102 // GetMetadata returns object metadata. 103 func (c *LockV2) GetMetadata() Metadata { 104 return c.Metadata 105 } 106 107 // GetResourceID returns resource ID. 108 func (c *LockV2) GetResourceID() int64 { 109 return c.Metadata.ID 110 } 111 112 // SetResourceID sets resource ID. 113 func (c *LockV2) SetResourceID(id int64) { 114 c.Metadata.ID = id 115 } 116 117 // GetRevision returns the revision 118 func (c *LockV2) GetRevision() string { 119 return c.Metadata.GetRevision() 120 } 121 122 // SetRevision sets the revision 123 func (c *LockV2) SetRevision(rev string) { 124 c.Metadata.SetRevision(rev) 125 } 126 127 // GetKind returns resource kind. 128 func (c *LockV2) GetKind() string { 129 return c.Kind 130 } 131 132 // GetSubKind returns resource subkind. 133 func (c *LockV2) GetSubKind() string { 134 return c.SubKind 135 } 136 137 // SetSubKind sets resource subkind. 138 func (c *LockV2) SetSubKind(sk string) { 139 c.SubKind = sk 140 } 141 142 // Target returns the lock's target. 143 func (c *LockV2) Target() LockTarget { 144 return c.Spec.Target 145 } 146 147 // SetTarget sets the lock's target. 148 func (c *LockV2) SetTarget(target LockTarget) { 149 c.Spec.Target = target 150 } 151 152 // Message returns the message displayed to locked-out users. 153 func (c *LockV2) Message() string { 154 return c.Spec.Message 155 } 156 157 // SetMessage sets the lock's user message. 158 func (c *LockV2) SetMessage(message string) { 159 c.Spec.Message = message 160 } 161 162 // LockExpiry returns when the lock ceases to be in force. 163 func (c *LockV2) LockExpiry() *time.Time { 164 return c.Spec.Expires 165 } 166 167 // SetLockExpiry sets the lock's expiry. 168 func (c *LockV2) SetLockExpiry(expiry *time.Time) { 169 c.Spec.Expires = expiry 170 } 171 172 func (c *LockV2) CreatedAt() time.Time { 173 return c.Spec.CreatedAt 174 } 175 176 func (c *LockV2) SetCreatedAt(t time.Time) { 177 c.Spec.CreatedAt = t 178 } 179 180 func (c *LockV2) CreatedBy() string { 181 return c.Spec.CreatedBy 182 } 183 184 func (c *LockV2) SetCreatedBy(user string) { 185 c.Spec.CreatedBy = user 186 } 187 188 // IsInForce returns whether the lock is in force at a particular time. 189 func (c *LockV2) IsInForce(t time.Time) bool { 190 if c.Spec.Expires == nil { 191 return true 192 } 193 return t.Before(*c.Spec.Expires) 194 } 195 196 // setStaticFields sets static resource header and metadata fields. 197 func (c *LockV2) setStaticFields() { 198 c.Kind = KindLock 199 c.Version = V2 200 } 201 202 // CheckAndSetDefaults verifies the constraints for Lock. 203 func (c *LockV2) CheckAndSetDefaults() error { 204 c.setStaticFields() 205 err := c.Metadata.CheckAndSetDefaults() 206 if err != nil { 207 return trace.Wrap(err) 208 } 209 210 if c.Spec.Target.IsEmpty() { 211 return trace.BadParameter("at least one target field must be set") 212 } 213 return nil 214 } 215 216 // Origin fetches the lock's origin, if any. Returns the empty string if no 217 // origin is set. 218 func (c *LockV2) Origin() string { 219 return c.Metadata.Labels[OriginLabel] 220 } 221 222 func (c *LockV2) SetOrigin(origin string) { 223 c.Metadata.SetOrigin(origin) 224 } 225 226 // GetLabel fetches the given user label, with the same semantics 227 // as a map read 228 func (c *LockV2) GetLabel(key string) (value string, ok bool) { 229 value, ok = c.Metadata.Labels[key] 230 return 231 } 232 233 // GetAllLabels fetches all the user labels. 234 func (c *LockV2) GetAllLabels() map[string]string { 235 return c.Metadata.Labels 236 } 237 238 // GetStaticLabels fetches all the user labels. 239 func (c *LockV2) GetStaticLabels() map[string]string { 240 return c.Metadata.Labels 241 } 242 243 // SetStaticLabels sets the entire label set for the user. 244 func (c *LockV2) SetStaticLabels(sl map[string]string) { 245 c.Metadata.Labels = sl 246 } 247 248 // MatchSearch goes through select field values and tries to 249 // match against the list of search values. 250 func (c *LockV2) MatchSearch(values []string) bool { 251 fieldVals := append(utils.MapToStrings(c.Metadata.Labels), c.GetName()) 252 return MatchSearch(fieldVals, values, nil) 253 } 254 255 // IntoMap returns the target attributes in the form of a map. 256 func (t LockTarget) IntoMap() (map[string]string, error) { 257 m := map[string]string{} 258 if err := utils.ObjectToStruct(t, &m); err != nil { 259 return nil, trace.Wrap(err) 260 } 261 return m, nil 262 } 263 264 // FromMap copies values from a map into this LockTarget. 265 func (t *LockTarget) FromMap(m map[string]string) error { 266 return trace.Wrap(utils.ObjectToStruct(m, t)) 267 } 268 269 // IsEmpty returns true if none of the target's fields is set. 270 func (t LockTarget) IsEmpty() bool { 271 return t.User == "" && 272 t.Role == "" && 273 t.Login == "" && 274 t.Node == "" && 275 t.MFADevice == "" && 276 t.WindowsDesktop == "" && 277 t.AccessRequest == "" && 278 t.Device == "" && 279 t.ServerID == "" 280 } 281 282 // Match returns true if the lock's target is matched by this target. 283 func (t LockTarget) Match(lock Lock) bool { 284 if t.IsEmpty() { 285 return false 286 } 287 lockTarget := lock.Target() 288 return (t.User == "" || lockTarget.User == t.User) && 289 (t.Role == "" || lockTarget.Role == t.Role) && 290 (t.Login == "" || lockTarget.Login == t.Login) && 291 (t.MFADevice == "" || lockTarget.MFADevice == t.MFADevice) && 292 (t.WindowsDesktop == "" || lockTarget.WindowsDesktop == t.WindowsDesktop) && 293 (t.AccessRequest == "" || lockTarget.AccessRequest == t.AccessRequest) && 294 (t.Device == "" || lockTarget.Device == t.Device) && 295 ((t.Node == "" && t.ServerID == "") || 296 // Node lock overrides ServerID lock because we want to keep backwards compatibility 297 // with previous versions of Teleport where a node lock only locked the ssh_service 298 // and not the other services running on that host. 299 // Newer versions of Teleport will lock all services based on the ServerID field. 300 (lockTarget.Node != "" && lockTarget.Node == t.Node) || 301 (lockTarget.ServerID != "" && lockTarget.ServerID == t.ServerID)) 302 } 303 304 // String returns string representation of the LockTarget. 305 func (t LockTarget) String() string { 306 return strings.TrimSpace(proto.CompactTextString(&t)) 307 } 308 309 // Equals returns true when the two lock targets are equal. 310 func (t LockTarget) Equals(t2 LockTarget) bool { 311 return proto.Equal(&t, &t2) 312 }