Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add saml_idp_service_provider label and label expression to RoleConditions #39039

Merged
merged 11 commits into from
Mar 7, 2024
Merged
Show file tree
Hide file tree
Changes from 7 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
10 changes: 10 additions & 0 deletions api/proto/teleport/legacy/types/types.proto
Original file line number Diff line number Diff line change
Expand Up @@ -3006,6 +3006,16 @@ message RoleConditions {
// SPIFFE is used to allow or deny access to a role holder to generating a
// SPIFFE SVID.
repeated SPIFFERoleCondition SPIFFE = 39 [(gogoproto.jsontag) = "spiffe,omitempty"];
// SAMLIdPServiceProviderLabels is a labels map used in RBAC system to allow/deny access
// to saml_idp_service_provider resource.
wrappers.LabelValues SAMLIdPServiceProviderLabels = 40 [
(gogoproto.nullable) = false,
(gogoproto.jsontag) = "saml_idp_service_provider_labels,omitempty",
(gogoproto.customtype) = "Labels"
];
// SAMLIdPServiceProviderLabelsExpression is a predicate expression used to allow/deny
// access to saml_idp_service_provider resource.
string SAMLIdPServiceProviderLabelsExpression = 41 [(gogoproto.jsontag) = "saml_idp_service_provider_labels_expression,omitempty"];
}

// SPIFFERoleCondition sets out which SPIFFE identities this role is allowed or
Expand Down
34 changes: 34 additions & 0 deletions api/types/role.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,13 @@ type Role interface {
GetSPIFFEConditions(rct RoleConditionType) []*SPIFFERoleCondition
// SetSPIFFEConditions sets the allow or deny SPIFFERoleCondition.
SetSPIFFEConditions(rct RoleConditionType, cond []*SPIFFERoleCondition)

// GetSAMLIdPServiceProviderLabels gets the map of saml_idp_service_provider resource
// labels this role is allowed or denied access to.
GetSAMLIdPServiceProviderLabels(RoleConditionType) Labels
// SetSAMLIdPServiceProviderLabels sets the map of saml_idp_service_provider resource
// labels this role is allowed or denied access to.
SetSAMLIdPServiceProviderLabels(RoleConditionType, Labels)
}

// NewRole constructs new standard V7 role.
Expand Down Expand Up @@ -932,6 +939,25 @@ func (r *RoleV6) SetSPIFFEConditions(rct RoleConditionType, cond []*SPIFFERoleCo
}
}

// GetSAMLIdPServiceProviderLabels gets the map of saml_idp_service_provider resource
// labels this role is allowed or denied access to.
func (r *RoleV6) GetSAMLIdPServiceProviderLabels(rct RoleConditionType) Labels {
if rct == Allow {
return r.Spec.Allow.SAMLIdPServiceProviderLabels
}
return r.Spec.Deny.SAMLIdPServiceProviderLabels
}

// SetSAMLIdPServiceProviderLabels sets the map of saml_idp_service_provider resource
// labels this role is allowed or denied access to.
func (r *RoleV6) SetSAMLIdPServiceProviderLabels(rct RoleConditionType, labels Labels) {
if rct == Allow {
r.Spec.Allow.SAMLIdPServiceProviderLabels = labels.Clone()
} else {
r.Spec.Deny.SAMLIdPServiceProviderLabels = labels.Clone()
}
}

// GetPrivateKeyPolicy returns the private key policy enforced for this role.
func (r *RoleV6) GetPrivateKeyPolicy() keys.PrivateKeyPolicy {
switch r.Spec.Options.RequireMFAType {
Expand Down Expand Up @@ -1190,6 +1216,7 @@ func (r *RoleV6) CheckAndSetDefaults() error {
r.Spec.Allow.DatabaseLabels,
r.Spec.Allow.WindowsDesktopLabels,
r.Spec.Allow.GroupLabels,
r.Spec.Allow.SAMLIdPServiceProviderLabels,
} {
if err := checkWildcardSelector(labels); err != nil {
return trace.Wrap(err)
Expand Down Expand Up @@ -1836,6 +1863,8 @@ func (r *RoleV6) GetLabelMatchers(rct RoleConditionType, kind string) (LabelMatc
return LabelMatchers{cond.WindowsDesktopLabels, cond.WindowsDesktopLabelsExpression}, nil
case KindUserGroup:
return LabelMatchers{cond.GroupLabels, cond.GroupLabelsExpression}, nil
case KindSAMLIdPServiceProvider:
return LabelMatchers{cond.SAMLIdPServiceProviderLabels, cond.SAMLIdPServiceProviderLabelsExpression}, nil
}
return LabelMatchers{}, trace.BadParameter("can't get label matchers for resource kind %q", kind)
}
Expand Down Expand Up @@ -1886,6 +1915,10 @@ func (r *RoleV6) SetLabelMatchers(rct RoleConditionType, kind string, labelMatch
cond.GroupLabels = labelMatchers.Labels
cond.GroupLabelsExpression = labelMatchers.Expression
return nil
case KindSAMLIdPServiceProvider:
cond.SAMLIdPServiceProviderLabels = labelMatchers.Labels
cond.SAMLIdPServiceProviderLabelsExpression = labelMatchers.Expression
return nil
}
return trace.BadParameter("can't set label matchers for resource kind %q", kind)
}
Expand Down Expand Up @@ -1948,6 +1981,7 @@ var LabelMatcherKinds = []string{
KindWindowsDesktop,
KindWindowsDesktopService,
KindUserGroup,
KindSAMLIdPServiceProvider,
}

const (
Expand Down
41 changes: 32 additions & 9 deletions api/types/role_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ func TestRoleV6_CheckAndSetDefaults(t *testing.T) {
require.ErrorContains(t, err, contains)
}
}
newRole := func(t *testing.T, spec RoleSpecV6) *RoleV6 {
newRole := func(spec RoleSpecV6) *RoleV6 {
return &RoleV6{
Metadata: Metadata{
Name: "test",
Expand All @@ -453,13 +453,14 @@ func TestRoleV6_CheckAndSetDefaults(t *testing.T) {
}

tests := []struct {
name string
role *RoleV6
requireError require.ErrorAssertionFunc
name string
role *RoleV6
requireError require.ErrorAssertionFunc
compareDefaultValue RoleConditions
}{
{
name: "spiffe: valid",
role: newRole(t, RoleSpecV6{
role: newRole(RoleSpecV6{
Allow: RoleConditions{
SPIFFE: []*SPIFFERoleCondition{{Path: "/test"}},
},
Expand All @@ -468,7 +469,7 @@ func TestRoleV6_CheckAndSetDefaults(t *testing.T) {
},
{
name: "spiffe: valid regex path",
role: newRole(t, RoleSpecV6{
role: newRole(RoleSpecV6{
Allow: RoleConditions{
SPIFFE: []*SPIFFERoleCondition{{Path: `^\/svc\/foo\/.*\/bar$`}},
},
Expand All @@ -477,7 +478,7 @@ func TestRoleV6_CheckAndSetDefaults(t *testing.T) {
},
{
name: "spiffe: missing path",
role: newRole(t, RoleSpecV6{
role: newRole(RoleSpecV6{
Allow: RoleConditions{
SPIFFE: []*SPIFFERoleCondition{{Path: ""}},
},
Expand All @@ -486,7 +487,7 @@ func TestRoleV6_CheckAndSetDefaults(t *testing.T) {
},
{
name: "spiffe: path not prepended",
role: newRole(t, RoleSpecV6{
role: newRole(RoleSpecV6{
Allow: RoleConditions{
SPIFFE: []*SPIFFERoleCondition{{Path: "foo"}},
},
Expand All @@ -495,7 +496,7 @@ func TestRoleV6_CheckAndSetDefaults(t *testing.T) {
},
{
name: "spiffe: invalid ip cidr",
role: newRole(t, RoleSpecV6{
role: newRole(RoleSpecV6{
Allow: RoleConditions{
SPIFFE: []*SPIFFERoleCondition{
{
Expand All @@ -510,6 +511,28 @@ func TestRoleV6_CheckAndSetDefaults(t *testing.T) {
}),
requireError: requireBadParameterContains("validating ip_sans[1]: invalid CIDR address: llama"),
},
{
name: "SAMLIdpServiceProviderLabels: valid wildcard labels",
role: newRole(RoleSpecV6{
Allow: RoleConditions{
SAMLIdPServiceProviderLabels: Labels{
Wildcard: {Wildcard},
},
},
}),
requireError: require.NoError,
},
{
name: "SAMLIdpServiceProviderLabels: invalid labels",
role: newRole(RoleSpecV6{
Allow: RoleConditions{
SAMLIdPServiceProviderLabels: Labels{
Wildcard: {"val"},
},
},
}),
requireError: requireBadParameterContains("not supported"),
},
}

for _, tt := range tests {
Expand Down
Loading
Loading