Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
488 changes: 287 additions & 201 deletions api/gen/proto/go/teleport/accesslist/v1/accesslist.pb.go

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions api/proto/teleport/accesslist/v1/accesslist.proto
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ syntax = "proto3";

package teleport.accesslist.v1;

import "google/protobuf/duration.proto";
import "google/protobuf/timestamp.proto";
import "teleport/header/v1/resourceheader.proto";
import "teleport/trait/v1/trait.proto";
Expand Down Expand Up @@ -87,6 +88,9 @@ message AccessListAudit {

// recurrence is the recurrence definition
Recurrence recurrence = 3;

// notifications is the configuration for notifying users.
Notifications notifications = 4;
}

// ReviewFrequency is the frequency of reviews.
Expand Down Expand Up @@ -115,6 +119,12 @@ message Recurrence {
ReviewDayOfMonth day_of_month = 2;
}

// Notifications contains the configuration for notifying users of a nearing next audit date.
message Notifications {
// start specifies when to start notifying users that the next audit date is coming up.
google.protobuf.Duration start = 1;
}

// AccessListRequires describes a requirement section for an access list. A user must
// meet the following criteria to obtain the specific access to the list.
message AccessListRequires {
Expand Down
47 changes: 47 additions & 0 deletions api/types/accesslist/accesslist.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ const (
ThreeMonths ReviewFrequency = 3
SixMonths ReviewFrequency = 6
OneYear ReviewFrequency = 12

twoWeeks = 24 * time.Hour * 14
)

func (r ReviewFrequency) String() string {
Expand Down Expand Up @@ -168,6 +170,9 @@ type Audit struct {
// Recurrence is the recurrence definition for auditing. Valid values are
// 1, first, 15, and last.
Recurrence Recurrence `json:"recurrence" yaml:"recurrence"`

// Notifications is the configuration for notifying users.
Notifications Notifications `json:"notifications" yaml:"notifications"`
}

// Recurrence defines when access list reviews should occur.
Expand All @@ -179,6 +184,12 @@ type Recurrence struct {
DayOfMonth ReviewDayOfMonth `json:"day_of_month" yaml:"day_of_month"`
}

// Notifications contains the configuration for notifying users of a nearing next audit date.
type Notifications struct {
// Start specifies when to start notifying users that the next audit date is coming up.
Start time.Duration `json:"start" yaml:"start"`
}

// Requires describes a requirement section for an access list. A user must
// meet the following criteria to obtain the specific access to the list.
type Requires struct {
Expand Down Expand Up @@ -271,6 +282,10 @@ func (a *AccessList) CheckAndSetDefaults() error {
return trace.BadParameter("recurrence day of month is an invalid value")
}

if a.Spec.Audit.Notifications.Start == 0 {
a.Spec.Audit.Notifications.Start = twoWeeks
}

if len(a.Spec.Grants.Roles) == 0 && len(a.Spec.Grants.Traits) == 0 {
return trace.BadParameter("grants must specify at least one role or trait")
}
Expand Down Expand Up @@ -403,3 +418,35 @@ func (r Recurrence) MarshalJSON() ([]byte, error) {
DayOfMonth: r.DayOfMonth.String(),
})
}

func (n *Notifications) UnmarshalJSON(data []byte) error {
type Alias Notifications
notifications := struct {
Start string `json:"start"`
*Alias
}{
Alias: (*Alias)(n),
}
if err := json.Unmarshal(data, &notifications); err != nil {
return trace.Wrap(err)
}

var err error
n.Start, err = time.ParseDuration(notifications.Start)
if err != nil {
return trace.Wrap(err)
}

return nil
}

func (n Notifications) MarshalJSON() ([]byte, error) {
type Alias Notifications
return json.Marshal(&struct {
Start string `json:"start"`
Alias
}{
Alias: (Alias)(n),
Start: n.Start.String(),
})
}
9 changes: 8 additions & 1 deletion api/types/accesslist/accesslist_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,12 +169,15 @@ func TestAuditMarshaling(t *testing.T) {
Frequency: SixMonths,
DayOfMonth: LastDayOfMonth,
},
Notifications: Notifications{
Start: 4 * time.Hour,
},
}

data, err := json.Marshal(&audit)
require.NoError(t, err)

require.Equal(t, `{"next_audit_date":"2023-02-02T00:00:00Z","recurrence":{"frequency":"6 months","day_of_month":"last"}}`, string(data))
require.Equal(t, `{"next_audit_date":"2023-02-02T00:00:00Z","recurrence":{"frequency":"6 months","day_of_month":"last"},"notifications":{"start":"4h0m0s"}}`, string(data))
}

func TestAuditUnmarshaling(t *testing.T) {
Expand All @@ -184,6 +187,9 @@ func TestAuditUnmarshaling(t *testing.T) {
"frequency": "3 months",
"day_of_month": "1",
},
"notifications": map[string]interface{}{
"start": twoWeeks.String(),
},
}

data, err := json.Marshal(&raw)
Expand All @@ -195,4 +201,5 @@ func TestAuditUnmarshaling(t *testing.T) {
require.Equal(t, time.Date(2023, 02, 02, 0, 0, 0, 0, time.UTC), audit.NextAuditDate)
require.Equal(t, ThreeMonths, audit.Recurrence.Frequency)
require.Equal(t, FirstDayOfMonth, audit.Recurrence.DayOfMonth)
require.Equal(t, twoWeeks, audit.Notifications.Start)
}
12 changes: 12 additions & 0 deletions api/types/accesslist/convert/v1/accesslist.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package v1

import (
"github.com/gravitational/trace"
"google.golang.org/protobuf/types/known/durationpb"
"google.golang.org/protobuf/types/known/timestamppb"

accesslistv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/accesslist/v1"
Expand Down Expand Up @@ -56,6 +57,13 @@ func FromProto(msg *accesslistv1.AccessList, opts ...AccessListOption) (*accessl
recurrence.DayOfMonth = accesslist.ReviewDayOfMonth(msg.Spec.Audit.Recurrence.DayOfMonth)
}

var notifications accesslist.Notifications
if msg.Spec.Audit.Notifications != nil {
if msg.Spec.Audit.Notifications.Start != nil {
notifications.Start = msg.Spec.Audit.Notifications.Start.AsDuration()
}
}

owners := make([]accesslist.Owner, len(msg.Spec.Owners))
for i, owner := range msg.Spec.Owners {
owners[i] = accesslist.Owner{
Expand All @@ -74,6 +82,7 @@ func FromProto(msg *accesslistv1.AccessList, opts ...AccessListOption) (*accessl
Audit: accesslist.Audit{
NextAuditDate: msg.Spec.Audit.NextAuditDate.AsTime(),
Recurrence: recurrence,
Notifications: notifications,
},
MembershipRequires: accesslist.Requires{
Roles: msg.Spec.MembershipRequires.Roles,
Expand Down Expand Up @@ -126,6 +135,9 @@ func ToProto(accessList *accesslist.AccessList) *accesslistv1.AccessList {
Frequency: accesslistv1.ReviewFrequency(accessList.Spec.Audit.Recurrence.Frequency),
DayOfMonth: accesslistv1.ReviewDayOfMonth(accessList.Spec.Audit.Recurrence.DayOfMonth),
},
Notifications: &accesslistv1.Notifications{
Start: durationpb.New(accessList.Spec.Audit.Notifications.Start),
},
},
MembershipRequires: &accesslistv1.AccessListRequires{
Roles: accessList.Spec.MembershipRequires.Roles,
Expand Down
14 changes: 14 additions & 0 deletions api/types/accesslist/convert/v1/accesslist_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,20 @@ func TestFromProtoNils(t *testing.T) {
_, err = FromProto(accessList)
require.Error(t, err)

// Recurrence is nil
accessList = ToProto(newAccessList(t, "access-list"))
accessList.Spec.Audit.Recurrence = nil

_, err = FromProto(accessList)
require.NoError(t, err)

// Notifications is nil
accessList = ToProto(newAccessList(t, "access-list"))
accessList.Spec.Audit.Notifications = nil

_, err = FromProto(accessList)
require.NoError(t, err)

// MembershipRequires is nil
accessList = ToProto(newAccessList(t, "access-list"))
accessList.Spec.MembershipRequires = nil
Expand Down