Skip to content

Commit

Permalink
[v13] Long living approval (#29754)
Browse files Browse the repository at this point in the history
* Add max duration option to access request (#29042)

* "Add 'persist' attribute to time-limited access requests

A 'persist' attribute was added to access requests, specifying how long the access will be granted for.

* Add comments
Remove unused code

* Add new role and refactor testing for persist durations

Included a new role, 'requestedRole2' to increase the diversity of the tests. Also refactored the testing descriptions for 'persist can exceed maxTTL' and 'persist shorter than maxTTL' to the user 'bob'. Added new test situations considering the role's maximum time to live. The purpose of these edits is to ensure that only the required roles are taken into account for persist duration, and this needs to be properly reflected in our tests.

* Initialize role persist cache

This change allows the initialization of the role persist cache under the local user role map.
This is necessary because previously, if the map was not initialized, it could result in null pointer exceptions when attempting to add entries. Now, the map is guaranteed to be initialized prior to adding any roles.

* Replace "Persist" with "MaxDuration" in various files

Renamed the "Persist" field in a number of auth and tsh related files to "MaxDuration". This name change more accurately reflects the nature of these fields, namely how long certain types of access should be granted for.

* "Rename 'persist' to 'maxDuration' in access request logic"

This commit renames all variables, parameters, and functions called 'persist' to 'maxDuration' and modifies the relevant comments and error messages in the access request logic in the services library. The aim is to make the naming more descriptive and meaningful, which could lead to more maintainable code. Specifically, 'maxDuration' is a more accurate description of the maximum duration an access request can be active and granted for. 'persist' may be easily misconstrued as relating to data persistence, which is not the intention.

* Refactor 'persist' to 'maxDuration' in access request code

Changes have been made to the variable name 'persist' in the access request code, renaming it to 'maxDuration'. This change is aimed towards improving code readability and determining the function of the variable more clearly. The adjusted name 'maxDuration' reflects its actual purpose - limiting the maximum duration of access requests. This change affects the 'access_request.go' file and the respective tests in 'tsh_test.go'.

* Apply code review suggestions

* Refactor max duration calculation in access requests

Add more tests

* Add SessionTTL to the Access Request object (#29658)

* Add SessionTTL to the Access Request object

New field Session TTL holds information on how long a generated certificate will be valid for when the max duration is used. The newly implemented V2 API endpoint is to be used for this purpose, to ensure backwards compatibility. The V1 API usage marked for deprecation in version 15.0.0.

* Update session TTL handling and fix access request string representation

Modified the access request logic to consider the maxDuration flag while setting the sessionTTL. Instead of simply replacing sessionTTL with the maxDuration (when maxDuration is set), the minimum value of sessionTTL and maxDuration is now used. This change has been reflected in the unit test as well. Also, the string representation of AccessRequest is fixed to accurately represent the user and roles.

The changes improve the handling of sessionTTL, providing a more accurate session duration that considers both session TTL and max duration. Furthermore, this improves AccessRequest debugging by providing a more descriptive string representation.

* Deprecate old CreateAccessRequest method

The old CreateAccessRequest method is marked as deprecated in the proto files. This commit indicates it will be deleted in v15.0.0. Users are urged to use CreateAccessRequestV2 instead to create new access requests.

* Fix test

* Fix test

* Add 'max_duration' to role operator configuration files

A 'max_duration' field has been added to the role configuration files. This field specifies the amount of time for which access is granted. If set to zero, the default duration will be used.
  • Loading branch information
jakule committed Jul 31, 2023
1 parent cca08e7 commit af7dbe2
Show file tree
Hide file tree
Showing 20 changed files with 3,553 additions and 2,861 deletions.
10 changes: 10 additions & 0 deletions api/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -1018,6 +1018,16 @@ func (c *Client) CreateAccessRequest(ctx context.Context, req types.AccessReques
return trail.FromGRPC(err)
}

// CreateAccessRequestV2 registers a new access request with the auth server.
func (c *Client) CreateAccessRequestV2(ctx context.Context, req types.AccessRequest) (types.AccessRequest, error) {
r, ok := req.(*types.AccessRequestV3)
if !ok {
return nil, trace.BadParameter("unexpected access request type %T", req)
}
resp, err := c.grpc.CreateAccessRequestV2(ctx, r)
return resp, trail.FromGRPC(err)
}

// DeleteAccessRequest deletes an access request.
func (c *Client) DeleteAccessRequest(ctx context.Context, reqID string) error {
_, err := c.grpc.DeleteAccessRequest(ctx, &proto.RequestID{ID: reqID})
Expand Down
1,639 changes: 841 additions & 798 deletions api/client/proto/authservice.pb.go

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions api/proto/teleport/legacy/client/proto/authservice.proto
Original file line number Diff line number Diff line change
Expand Up @@ -2351,7 +2351,11 @@ service AuthService {
// GetAccessRequestsV2 gets all pending access requests.
rpc GetAccessRequestsV2(types.AccessRequestFilter) returns (stream types.AccessRequestV3);
// CreateAccessRequest creates a new access request.
// Deprecated: use CreateAccessRequestV2 instead.
// DELETE IN v15.0.0.
rpc CreateAccessRequest(types.AccessRequestV3) returns (google.protobuf.Empty);
// CreateAccessRequestV2 creates a new access request.
rpc CreateAccessRequestV2(types.AccessRequestV3) returns (types.AccessRequestV3);
// DeleteAccessRequest deletes an access request.
rpc DeleteAccessRequest(RequestID) returns (google.protobuf.Empty);
// SetAccessRequestState sets the state of an access request.
Expand Down
19 changes: 13 additions & 6 deletions api/proto/teleport/legacy/types/events/events.proto
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ option (gogoproto.unmarshaler_all) = true;

// Metadata is a common event metadata
message Metadata {
// Index is a monotonicaly incremented index in the event sequence
// Index is a monotonically incremented index in the event sequence
int64 Index = 1 [(gogoproto.jsontag) = "ei"];

// Type is the event type
Expand All @@ -53,7 +53,7 @@ message Metadata {
string ClusterName = 6 [(gogoproto.jsontag) = "cluster_name,omitempty"];
}

// SesssionMetadata is a common session event metadata
// SessionMetadata is a common session event metadata
message SessionMetadata {
// SessionID is a unique UUID of the session.
string SessionID = 1 [(gogoproto.jsontag) = "sid"];
Expand Down Expand Up @@ -328,7 +328,7 @@ message SessionJoin {
}

// SessionPrint event happens every time a write occurs to
// temirnal I/O during a session
// terminal I/O during a session
message SessionPrint {
// Metadata is a common event metadata
Metadata Metadata = 1 [
Expand All @@ -337,7 +337,7 @@ message SessionPrint {
(gogoproto.jsontag) = ""
];

// ChunkIndex is a monotonicaly incremented index for ordering print events
// ChunkIndex is a monotonically incremented index for ordering print events
int64 ChunkIndex = 2 [(gogoproto.jsontag) = "ci"];

// Data is data transferred, it is not marshaled to JSON format
Expand Down Expand Up @@ -1089,7 +1089,7 @@ message SessionLeave {
];
}

// UserLogin records a successfull or failed user login event
// UserLogin records a successfully or failed user login event
message UserLogin {
// Metadata is a common event metadata
Metadata Metadata = 1 [
Expand Down Expand Up @@ -1277,7 +1277,7 @@ message AccessRequestCreate {
string Reason = 8 [(gogoproto.jsontag) = "reason,omitempty"];

// Annotations is an optional set of attributes supplied by a plugin during
// approval/denail of the request.
// approval/denial of the request.
google.protobuf.Struct Annotations = 9 [
(gogoproto.jsontag) = "annotations,omitempty",
(gogoproto.casttype) = "Struct"
Expand All @@ -1295,6 +1295,13 @@ message AccessRequestCreate {
(gogoproto.jsontag) = "resource_ids,omitempty",
(gogoproto.nullable) = false
];

// MaxDuration indicates how long the access should be granted for.
google.protobuf.Timestamp MaxDuration = 13 [
(gogoproto.stdtime) = true,
(gogoproto.nullable) = false,
(gogoproto.jsontag) = "max_duration,omitempty"
];
}

// ResourceID is a unique identifier for a teleport resource. This is duplicated
Expand Down
21 changes: 21 additions & 0 deletions api/proto/teleport/legacy/types/types.proto
Original file line number Diff line number Diff line change
Expand Up @@ -2213,6 +2213,20 @@ message AccessRequestSpecV3 {
// DryRun indicates that the request should not actually be created, the
// auth server should only validate the access request.
bool DryRun = 16 [(gogoproto.jsontag) = "dry_run,omitempty"];

// MaxDuration indicates how long the access should be granted for.
google.protobuf.Timestamp MaxDuration = 17 [
(gogoproto.stdtime) = true,
(gogoproto.nullable) = false,
(gogoproto.jsontag) = "max_duration,omitempty"
];

// SessionTLL indicated how long a certificate for a session should be valid for.
google.protobuf.Timestamp SessionTTL = 18 [
(gogoproto.stdtime) = true,
(gogoproto.nullable) = false,
(gogoproto.jsontag) = "session_ttl,omitempty"
];
}

// AccessRequestFilter encodes filter params for access requests.
Expand Down Expand Up @@ -2856,6 +2870,13 @@ message AccessRequestConditions {
// defines the underlying roles which will be requested as part of any
// Resource Access Request.
repeated string SearchAsRoles = 6 [(gogoproto.jsontag) = "search_as_roles,omitempty"];

// MaxDuration is the amount of time the access will be granted for.
// If this is zero, the default duration is used.
int64 MaxDuration = 7 [
(gogoproto.jsontag) = "max_duration,omitempty",
(gogoproto.casttype) = "Duration"
];
}

// AccessReviewConditions is a matcher for allow/deny restrictions on
Expand Down
28 changes: 28 additions & 0 deletions api/types/access_request.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ type AccessRequest interface {
// SetAccessExpiry sets the expiration time for the elevated certificate
// that will be issued if the Access Request is approved.
SetAccessExpiry(time.Time)
// GetSessionTLL gets the session TTL for generated certificates.
GetSessionTLL() time.Time
// SetSessionTLL sets the session TTL for generated certificates.
SetSessionTLL(time.Time)
// GetRequestReason gets the reason for the request's creation.
GetRequestReason() string
// SetRequestReason sets the reason for the request's creation.
Expand Down Expand Up @@ -98,6 +102,10 @@ type AccessRequest interface {
GetLoginHint() string
// SetLoginHint sets the requested login hint.
SetLoginHint(string)
// GetMaxDuration gets the maximum time at which the access should be approved for.
GetMaxDuration() time.Time
// SetMaxDuration sets the maximum time at which the access should be approved for.
SetMaxDuration(time.Time)
// GetDryRun returns true if this request should not be created and is only
// a dry run to validate request capabilities.
GetDryRun() bool
Expand Down Expand Up @@ -183,6 +191,16 @@ func (r *AccessRequestV3) SetAccessExpiry(expiry time.Time) {
r.Spec.Expires = expiry.UTC()
}

// GetSessionTLL gets SessionTLL
func (r *AccessRequestV3) GetSessionTLL() time.Time {
return r.Spec.SessionTTL
}

// SetSessionTLL sets SessionTLL
func (r *AccessRequestV3) SetSessionTLL(t time.Time) {
r.Spec.SessionTTL = t.UTC()
}

// GetRequestReason gets RequestReason
func (r *AccessRequestV3) GetRequestReason() string {
return r.Spec.RequestReason
Expand Down Expand Up @@ -414,6 +432,16 @@ func (r *AccessRequestV3) GetDryRun() bool {
return r.Spec.DryRun
}

// GetMaxDuration gets the maximum time at which the access should be approved for.
func (r *AccessRequestV3) GetMaxDuration() time.Time {
return r.Spec.MaxDuration
}

// SetMaxDuration sets the maximum time at which the access should be approved for.
func (r *AccessRequestV3) SetMaxDuration(t time.Time) {
r.Spec.MaxDuration = t
}

// SetDryRun sets the dry run flag on the request.
func (r *AccessRequestV3) SetDryRun(dryRun bool) {
r.Spec.DryRun = dryRun
Expand Down

0 comments on commit af7dbe2

Please sign in to comment.