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  }